diff options
170 files changed, 3455 insertions, 1720 deletions
diff --git a/.gitignore b/.gitignore index 871d17b386..8298f5a894 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,12 @@ *~ +phpunit.xml phpBB/cache/*.php +phpBB/cache/queue.php.lock phpBB/config.php phpBB/files/* +phpBB/images/avatars/gallery/* phpBB/images/avatars/upload/* phpBB/store/* tests/phpbb_unit_tests.sqlite2 tests/test_config.php +tests/utf/data/*.txt diff --git a/build/build.xml b/build/build.xml index 8d2afcb00c..268f09d674 100644 --- a/build/build.xml +++ b/build/build.xml @@ -13,6 +13,7 @@ <!-- These are the main targets which you will probably want to use --> <target name="package" depends="clean,prepare,create-package" /> <target name="all" depends="clean,prepare,test,docs,create-package" /> + <target name="build" depends="clean,prepare,test,docs" /> <target name="prepare"> <mkdir dir="build/logs" /> @@ -42,12 +43,11 @@ <delete dir="build/save" /> </target> - <target name="test"> - <exec dir="tests" - command="phpunit --log-junit ../build/logs/phpunit.xml - --coverage-clover ../build/logs/clover.xml - --coverage-html ../build/coverage - phpbb_all_tests all_tests.php" + <target name="test" depends="clean,prepare"> + <exec dir="." + command="phpunit --log-junit build/logs/phpunit.xml + --coverage-clover build/logs/clover.xml + --coverage-html build/coverage" passthru="true" /> @@ -65,8 +65,14 @@ </target> <target name="docs"> + <!-- only works if you setup phpdoctor: + git clone https://github.com/peej/phpdoctor.git + and then create an executable phpdoctor in your path containing + #!/bin/sh + php -f /path/to/phpdoctor/phpdoc.php $@ + --> <exec dir="build" - command="phpdoc -c phpdoc-phpbb.ini" + command="phpdoctor phpdoc-phpbb.ini" passthru="true" /> </target> diff --git a/build/phpdoc-phpbb.ini b/build/phpdoc-phpbb.ini index 86d33549c0..f1a7a4bee5 100644 --- a/build/phpdoc-phpbb.ini +++ b/build/phpdoc-phpbb.ini @@ -1,106 +1,145 @@ -;; phpDocumentor parse configuration file -;; -;; This file is designed to cut down on repetitive typing on the command-line or web interface -;; You can copy this file to create a number of configuration files that can be used with the -;; command-line switch -c, as in phpdoc -c default.ini or phpdoc -c myini.ini. The web -;; interface will automatically generate a list of .ini files that can be used. -;; -;; default.ini is used to generate the online manual at http://www.phpdoc.org/docs -;; -;; ALL .ini files must be in the user subdirectory of phpDocumentor with an extension of .ini -;; -;; Copyright 2002, Greg Beaver <cellog@users.sourceforge.net> -;; -;; WARNING: do not change the name of any command-line parameters, phpDocumentor will ignore them - -[Parse Data] -;; title of all the documentation -;; legal values: any string -title = phpBB3 Sourcecode Documentation - -;; parse files that start with a . like .bash_profile -;; legal values: true, false -hidden = false - -;; show elements marked @access private in documentation by setting this to on -;; legal values: on, off -parseprivate = on - -;; parse with javadoc-like description (first sentence is always the short description) -;; legal values: on, off -javadocdesc = off - -;; add any custom @tags separated by commas here -;; legal values: any legal tagname separated by commas. -;customtags = mytag1,mytag2 - -;; This is only used by the XML:DocBook/peardoc2 converter -defaultcategoryname = sourcecode - -;; what is the main package? -;; legal values: alphanumeric string plus - and _ -defaultpackagename = phpBB3 - -;; output any parsing information? set to on for cron jobs -;; legal values: on -;quiet = on - -;; parse a PEAR-style repository. Do not turn this on if your project does -;; not have a parent directory named "pear" -;; legal values: on/off -;pear = on - -;; where should the documentation be written? -;; legal values: a legal path -target = api - -;; Which files should be parsed out as special documentation files, such as README, -;; INSTALL and CHANGELOG? This overrides the default files found in -;; phpDocumentor.ini (this file is not a user .ini file, but the global file) -readmeinstallchangelog = README.html, INSTALL.html, CHANGELOG.html, COPYING - -;; limit output to the specified packages, even if others are parsed -;; legal values: package names separated by commas -;packageoutput = phpBB3,ACP,SEARCH,DBAL,ACM,MCP,UCP,LOGIN,lang_english - -;; comma-separated list of files to parse -;; legal values: paths separated by commas -;filename = /path/to/file1,/path/to/file2,fileincurrentdirectory - -;; comma-separated list of directories to parse -;; legal values: directory paths separated by commas -;directory = /path1,/path2,.,..,subdirectory -;directory = /home/jeichorn/cvs/pear -directory = ../phpBB/ - -;; template base directory (the equivalent directory of <installdir>/phpDocumentor) -;templatebase = /path/to/my/templates - -;; directory to find any example files in through @example and {@example} tags -;examplesdir = c:\wamp\www\examples - -;; comma-separated list of files, directories or wildcards ? and * (any wildcard) to ignore -;; legal values: any wildcard strings separated by commas -;ignore = /path/to/ignore*,*list.php,myfile.php,subdirectory/ -ignore = templates_c/,*HTML/default/*,spec/,*config.php*,*CVS/,test_chora.php,testupdate/,cache/,store/,*proSilver/,develop/,includes/utf/data/,includes/captcha/fonts/,install/update/,install/update.new/,files/,*phpinfo.php*,*update_script.php*,*upgrade.php*,*convert.php*,install/converter/,language/de/,script/,*swatch.php*,*test.php*,*test2.php*,*install.php*,*functions_diff.php*,*acp_update.php* - -;; comma-separated list of Converters to use in outputformat:Convertername:templatedirectory format -;; legal values: HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib, -;; HTML:frames:earthli, -;; HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de, -;; HTML:frames:DOM/phphtmllib,HTML:frames:DOM/earthli -;; HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS -;; PDF:default:default,CHM:default:default,XML:DocBook/peardoc2:default -;output=HTML:frames:earthli,HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:frames:DOM/earthli,HTML:frames:DOM/phphtmllib,HTML:frames:phpedit,HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS,CHM:default:default,PDF:default:default -;output=HTML:frames:DOM/default,XML:DocBook/peardoc2:default,CHM:default:default,HTML:frames:DOM/earthli,HTML:frames:DOM/phpdoc.de,HTML:frames:DOM/phphtmllib,HTML:frames:phphtmllib -;HTML:frames:earthli -;output=XML:DocBook/peardoc2:default - -;output=HTML:frames:DOM/earthli -;output=HTML:frames:earthli,HTML:frames:default,HTML:frames:l0l33t,HTML:frames:phpdoc.de,HTML:frames:phphtmllib,HTML:frames:DOM/default,HTML:frames:DOM/l0l33t,HTML:frames:DOM/phpdoc.de,HTML:frames:DOM/earthli,HTML:frames:DOM/phphtmllib,HTML:frames:phpedit,HTML:Smarty:default,HTML:Smarty:PHP,HTML:Smarty:HandS,CHM:default:default,PDF:default:default -;output=HTML:Smarty:PHP -output=HTML:frames:earthli - -;; turn this option on if you want highlighted source code for every file -;; legal values: on/off -sourcecode = off +; Default configuration file for PHPDoctor + +; This config file will cause PHPDoctor to generate API documentation of +; itself. + + +; PHPDoctor settings +; ----------------------------------------------------------------------------- + +; Names of files to parse. This can be a single filename, or a comma separated +; list of filenames. Wildcards are allowed. + +files = "*.php" + +; Names of files or directories to ignore. This can be a single filename, or a +; comma separated list of filenames. Wildcards are NOT allowed. + +;ignore = "CVS, .svn, .git, _compiled" +ignore = templates_c/,*HTML/default/*,spec/,*config.php*,*CVS/,test_chora.php,testupdate/,cache/,store/,*proSilver/,develop/,includes/utf/data/,includes/captcha/fonts/,install/update/,install/update.new/,files/,*phpinfo.php*,*update_script.php*,*upgrade.php*,*convert.php*,install/converter/,language/de/,script/,*swatch.php*,*test.php*,*test2.php*,*install.php*,*functions_diff.php*,*acp_update.php*,acm_xcache.php + +; The directory to look for files in, if not used the PHPDoctor will look in +; the current directory (the directory it is run from). + +source_path = "../phpBB/" + +; If you do not want PHPDoctor to look in each sub directory for files +; uncomment this line. + +;subdirs = off + +; Set how loud PHPDoctor is as it runs. Quiet mode suppresses all output other +; than warnings and errors. Verbose mode outputs additional messages during +; execution. + +quiet = on +;verbose = on + +; Select the doclet to use for generating output. + +doclet = standard +;doclet = debug + +; The directory to find the doclet in. Doclets control the HTML output of +; phpDoctor and can be modified to suit your needs. They are expected to be +; in a directory named after themselves at the location given. + +;doclet_path = ./doclets + +; Select the formatter to use for generating output. + +;formatter = htmlStandardFormatter + +; The directory to find the formatter in. Formatters convert textual markup +; for use by the doclet. + +;formatter_path = ./formatters + +; The directory to find taglets in. Taglets allow you to make PHPDoctor handle +; new tags and to alter the behavour of existing tags and their output. + +;taglet_path = ./taglets + +; If the code you are parsing does not use package tags or not all elements +; have package tags, use this setting to place unbound elements into a +; particular package. + +default_package = "phpBB" + +use_class_path_as_package = off + +ignore_package_tags = off + +; Specifies the name of a HTML file containing text for the overview +; documentation to be placed on the overview page. The path is relative to +; "source_path" unless an absolute path is given. + +overview = ../README.md + +; Package comments will be looked for in a file named package.html in the same +; directory as the first source file parsed in that package or in the directory +; given below. If package comments are placed in the directory given below then +; they should be named "<packageName>.html". + +package_comment_dir = ./ + +; Parse out global variables and/or global constants? + +;globals = off +;constants = off + +; Generate documentation for all class members + +;private = on + +; Generate documentation for public and protected class members + +;protected = on + +; Generate documentation for only public class members + +;public = on + +; Use the PEAR compatible handling of the docblock first sentence + +;pear_compat = on + +; Standard doclet settings +; ----------------------------------------------------------------------------- + +; The directory to place generated documentation in. If the given path is +; relative to it will be relative to "source_path". + +d = "../build/api/" + +; Specifies the title to be placed in the HTML <title> tag. + +windowtitle = "phpBB3" + +; Specifies the title to be placed near the top of the overview summary file. + +doctitle = "phpBB3 Sourcecode Documentation" + +; Specifies the header text to be placed at the top of each output file. The +; header will be placed to the right of the upper navigation bar. + +header = "phpBB3" + +; Specifies the footer text to be placed at the bottom of each output file. The +; footer will be placed to the right of the lower navigation bar. + +footer = "phpBB3" + +; Specifies the text to be placed at the bottom of each output file. The text +; will be placed at the bottom of the page, below the lower navigation bar. + +;bottom = "This document was generated by <a href="http://peej.github.com/phpdoctor/">PHPDoctor: The PHP Documentation Creator</a>" + +; Create a class tree? + +;tree = off + +; Use GeSHi to include formatted source files in the documentation. PHPDoctor will look in the current doclet directory for a /geshi subdirectory. Unpack the GeSHi archive from http://qbnz.com/highlighter to get this directory - it will contain a php script and a subdirectory with formatting files. + +include_source = off + diff --git a/git-tools/hooks/commit-msg b/git-tools/hooks/commit-msg index a6777ff9c9..4f6ae71d4b 100755 --- a/git-tools/hooks/commit-msg +++ b/git-tools/hooks/commit-msg @@ -55,12 +55,24 @@ quit() fi } -msg=$(grep -nE '.{81,}' "$1"); +# Check for empty commit message +if ! grep -qv '^#' "$1" +then + # Commit message is empty (or contains only comments). + # Let git handle this. + # It will abort with a message like so: + # + # Aborting commit due to empty commit message. + exit 0 +fi + +msg=$(grep -v '^#' "$1" |grep -nE '.{81,}') if [ $? -eq 0 ] then - echo "The following lines are greater than 80 characters long:\n" >&2; - echo $msg >&2; + echo "The following lines are greater than 80 characters long:" >&2; + echo >&2 + echo "$msg" >&2; quit $ERR_LENGTH; fi @@ -107,7 +119,19 @@ do case $expect in "header") err=$ERR_HEADER; - echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] [A-Z].+$" + echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] .+$" + result=$? + if ! echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] [A-Z].+$" + then + # Don't be too strict. + # Commits may be temporary, intended to be squashed later. + # Just issue a warning here. + echo "Warning: heading should be a sentence beginning with a capital letter." 1>&2 + echo "You entered:" 1>&2 + echo "$line" 1>&2 + fi + # restore exit code + (exit $result) ;; "empty") err=$ERR_EMPTY; @@ -128,6 +152,10 @@ do # Should not end up here false ;; + "possibly-eof") + # Allow empty and/or comment lines at the end + ! tail -n +"$i" "$1" |grep -qvE '^($|#)' + ;; "comment") echo "$line" | grep -Eq "^#"; ;; @@ -188,7 +216,7 @@ do in_description=1; ;; "footer") - expecting="footer eof"; + expecting="footer possibly-eof"; if [ "$tickets" = "" ] then tickets="$line"; @@ -199,6 +227,9 @@ do "comment") # Comments should expect the same thing again ;; + "possibly-eof") + expecting="eof"; + ;; *) echo "Unrecognised token $expect" >&2; quit 254; diff --git a/git-tools/hooks/prepare-commit-msg b/git-tools/hooks/prepare-commit-msg index 2bf25e58a4..11d2b6b2f2 100755 --- a/git-tools/hooks/prepare-commit-msg +++ b/git-tools/hooks/prepare-commit-msg @@ -35,8 +35,8 @@ then # Branch is prefixed with 'ticket/', append ticket ID to message if [ "$branch" != "${branch##ticket/}" ]; then - tail="\n\nPHPBB3-${branch##ticket/}"; + tail="$(printf "\n\nPHPBB3-${branch##ticket/}")"; fi - echo "[$branch]$tail $(cat "$1")" > "$1" + echo "[$branch] $tail$(cat "$1")" > "$1" fi diff --git a/git-tools/merge.php b/git-tools/merge.php new file mode 100755 index 0000000000..cbd84b896f --- /dev/null +++ b/git-tools/merge.php @@ -0,0 +1,175 @@ +#!/usr/bin/env php +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +function show_usage() +{ + $filename = basename(__FILE__); + + echo "$filename merges a github pull request.\n"; + echo "\n"; + + echo "Usage: [php] $filename -p pull_request_id [OPTIONS]\n"; + echo "\n"; + + echo "Options:\n"; + echo " -p pull_request_id The pull request id to be merged (mandatory)\n"; + echo " -r remote Remote of upstream, defaults to 'upstream' (optional)\n"; + echo " -d Outputs the commands instead of running them (optional)\n"; + echo " -h This help text\n"; + + exit(2); +} + +// Handle arguments +$opts = getopt('p:r:dh'); + +if (empty($opts) || isset($opts['h'])) +{ + show_usage(); +} + +$pull_id = get_arg($opts, 'p', ''); +$remote = get_arg($opts, 'r', 'upstream'); +$dry_run = !get_arg($opts, 'd', true); + +try +{ + exit(work($pull_id, $remote)); +} +catch (RuntimeException $e) +{ + echo $e->getMessage(); + exit($e->getCode()); +} + +function work($pull_id, $remote) +{ + // Get some basic data + $pull = get_pull('phpbb', 'phpbb3', $pull_id); + + if (!$pull_id) + { + show_usage(); + } + + if ($pull['state'] != 'open') + { + throw new RuntimeException(sprintf("Error: pull request is closed\n", + $target_branch), 5); + } + + $pull_user = $pull['head'][0]; + $pull_branch = $pull['head'][1]; + $target_branch = $pull['base'][1]; + + switch ($target_branch) + { + case 'develop-olympus': + run("git checkout develop-olympus"); + run("git pull $remote develop-olympus"); + + add_remote($pull_user, 'phpbb3'); + run("git fetch $pull_user"); + run("git merge --no-ff $pull_user/$pull_branch"); + run("phpunit"); + + run("git checkout develop"); + run("git pull $remote develop"); + run("git merge --no-ff develop-olympus"); + run("phpunit"); + break; + + case 'develop': + run("git checkout develop"); + run("git pull $remote develop"); + + add_remote($pull_user, 'phpbb3'); + run("git fetch $pull_user"); + run("git merge --no-ff $pull_user/$pull_branch"); + run("phpunit"); + break; + + default: + throw new RuntimeException(sprintf("Error: pull request target branch '%s' is not a main branch\n", + $target_branch), 5); + break; + } +} + +function add_remote($username, $repository, $pushable = false) +{ + $url = get_repository_url($username, $repository, false); + run("git remote add $username $url", true); + + if ($pushable) + { + $ssh_url = get_repository_url($username, $repository, true); + run("git remote set-url --push $username $ssh_url"); + } +} + +function get_repository_url($username, $repository, $ssh = false) +{ + $url_base = ($ssh) ? 'git@github.com:' : 'git://github.com/'; + + return $url_base . $username . '/' . $repository . '.git'; +} + +function api_request($query) +{ + $contents = file_get_contents("http://github.com/api/v2/json/$query"); + + if ($contents === false) + { + throw new RuntimeException("Error: failed to retrieve pull request data\n", 4); + } + + return json_decode($contents); +} + +function get_pull($username, $repository, $pull_id) +{ + $request = api_request("pulls/$username/$repository/$pull_id"); + + $pull = $request->pull; + + $pull_data = array( + 'base' => array($pull->base->user->login, $pull->base->ref), + 'head' => array($pull->head->user->login, $pull->head->ref), + 'state' => $pull->state, + ); + + return $pull_data; +} + +function get_arg($array, $index, $default) +{ + return isset($array[$index]) ? $array[$index] : $default; +} + +function run($cmd, $ignore_fail = false) +{ + global $dry_run; + + if (!empty($dry_run)) + { + echo "$cmd\n"; + } + else + { + passthru(escapeshellcmd($cmd), $status); + + if ($status != 0 && !$ignore_fail) + { + throw new RuntimeException(sprintf("Error: command '%s' failed with status %s'\n", + $cmd, $status), 6); + } + } +} diff --git a/git-tools/setup_github_network.php b/git-tools/setup_github_network.php new file mode 100755 index 0000000000..e4e212eef6 --- /dev/null +++ b/git-tools/setup_github_network.php @@ -0,0 +1,248 @@ +#!/usr/bin/env php +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +function show_usage() +{ + $filename = basename(__FILE__); + + echo "$filename adds repositories of a github network as remotes to a local git repository.\n"; + echo "\n"; + + echo "Usage: [php] $filename -s collaborators|organisation|contributors|network [OPTIONS]\n"; + echo "\n"; + + echo "Scopes:\n"; + echo " collaborators Repositories of people who have push access to the specified repository\n"; + echo " contributors Repositories of people who have contributed to the specified repository\n"; + echo " organisation Repositories of members of the organisation at github\n"; + echo " network All repositories of the whole github network\n"; + echo "\n"; + + echo "Options:\n"; + echo " -s scope See description above (mandatory)\n"; + echo " -u github_username Overwrites the github username (optional)\n"; + echo " -r repository_name Overwrites the repository name (optional)\n"; + echo " -m your_github_username Sets up ssh:// instead of git:// for pushable repositories (optional)\n"; + echo " -d Outputs the commands instead of running them (optional)\n"; + echo " -h This help text\n"; + + exit(1); +} + +// Handle arguments +$opts = getopt('s:u:r:m:dh'); + +if (empty($opts) || isset($opts['h'])) +{ + show_usage(); +} + +$scope = get_arg($opts, 's', ''); +$username = get_arg($opts, 'u', 'phpbb'); +$repository = get_arg($opts, 'r', 'phpbb3'); +$developer = get_arg($opts, 'm', ''); +$dry_run = !get_arg($opts, 'd', true); +run(null, $dry_run); +exit(work($scope, $username, $repository, $developer)); + +function work($scope, $username, $repository, $developer) +{ + // Get some basic data + $network = get_network($username, $repository); + $collaborators = get_collaborators($username, $repository); + + if ($network === false || $collaborators === false) + { + echo "Error: failed to retrieve network or collaborators\n"; + return 1; + } + + switch ($scope) + { + case 'collaborators': + $remotes = array_intersect_key($network, $collaborators); + break; + + case 'organisation': + $remotes = array_intersect_key($network, get_organisation_members($username)); + break; + + case 'contributors': + $remotes = array_intersect_key($network, get_contributors($username, $repository)); + break; + + case 'network': + $remotes = $network; + break; + + default: + show_usage(); + } + + if (file_exists('.git')) + { + add_remote($username, $repository, isset($collaborators[$developer])); + } + else + { + clone_repository($username, $repository, isset($collaborators[$developer])); + } + + // Add private security repository for developers + if ($username == 'phpbb' && $repository == 'phpbb3' && isset($collaborators[$developer])) + { + run("git remote add $username-security " . get_repository_url($username, "$repository-security", true)); + } + + // Skip blessed repository. + unset($remotes[$username]); + + foreach ($remotes as $remote) + { + add_remote($remote['username'], $remote['repository'], $remote['username'] == $developer); + } + + run('git remote update'); +} + +function clone_repository($username, $repository, $pushable = false) +{ + $url = get_repository_url($username, $repository, false); + run("git clone $url ./ --origin $username"); + + if ($pushable) + { + $ssh_url = get_repository_url($username, $repository, true); + run("git remote set-url --push $username $ssh_url"); + } +} + +function add_remote($username, $repository, $pushable = false) +{ + $url = get_repository_url($username, $repository, false); + run("git remote add $username $url"); + + if ($pushable) + { + $ssh_url = get_repository_url($username, $repository, true); + run("git remote set-url --push $username $ssh_url"); + } +} + +function get_repository_url($username, $repository, $ssh = false) +{ + $url_base = ($ssh) ? 'git@github.com:' : 'git://github.com/'; + + return $url_base . $username . '/' . $repository . '.git'; +} + +function api_request($query) +{ + $contents = file_get_contents("http://github.com/api/v2/json/$query"); + if ($contents === false) + { + return false; + } + return json_decode($contents); +} + +function get_contributors($username, $repository) +{ + $request = api_request("repos/show/$username/$repository/contributors"); + if ($request === false) + { + return false; + } + + $usernames = array(); + foreach ($request->contributors as $contributor) + { + $usernames[$contributor->login] = $contributor->login; + } + + return $usernames; +} + +function get_organisation_members($username) +{ + $request = api_request("organizations/$username/public_members"); + if ($request === false) + { + return false; + } + + $usernames = array(); + foreach ($request->users as $member) + { + $usernames[$member->login] = $member->login; + } + + return $usernames; +} + +function get_collaborators($username, $repository) +{ + $request = api_request("repos/show/$username/$repository/collaborators"); + if ($request === false) + { + return false; + } + + $usernames = array(); + foreach ($request->collaborators as $collaborator) + { + $usernames[$collaborator] = $collaborator; + } + + return $usernames; +} + +function get_network($username, $repository) +{ + $request = api_request("repos/show/$username/$repository/network"); + if ($request === false) + { + return false; + } + + $usernames = array(); + foreach ($request->network as $network) + { + $usernames[$network->owner] = array( + 'username' => $network->owner, + 'repository' => $network->name, + ); + } + + return $usernames; +} + +function get_arg($array, $index, $default) +{ + return isset($array[$index]) ? $array[$index] : $default; +} + +function run($cmd, $dry = false) +{ + static $dry_run; + + if (is_null($cmd)) + { + $dry_run = $dry; + } + else if (!empty($dry_run)) + { + echo "$cmd\n"; + } + else + { + passthru(escapeshellcmd($cmd)); + } +} diff --git a/phpBB/adm/index.php b/phpBB/adm/index.php index 92bcf90039..dd8f4c279d 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -573,7 +573,11 @@ function validate_range($value_ary, &$error) 'BOOL' => array('php_type' => 'int', 'min' => 0, 'max' => 1), 'USINT' => array('php_type' => 'int', 'min' => 0, 'max' => 65535), 'UINT' => array('php_type' => 'int', 'min' => 0, 'max' => (int) 0x7fffffff), - 'INT' => array('php_type' => 'int', 'min' => (int) 0x80000000, 'max' => (int) 0x7fffffff), + // Do not use (int) 0x80000000 - it evaluates to different + // values on 32-bit and 64-bit systems. + // Apparently -2147483648 is a float on 32-bit systems, + // despite fitting in an int, thus explicit cast is needed. + 'INT' => array('php_type' => 'int', 'min' => (int) -2147483648, 'max' => (int) 0x7fffffff), 'TINT' => array('php_type' => 'int', 'min' => -128, 'max' => 127), 'VCHAR' => array('php_type' => 'string', 'min' => 0, 'max' => 255), diff --git a/phpBB/adm/style/acp_ban.html b/phpBB/adm/style/acp_ban.html index cf44f4aaa7..0e2e71822e 100644 --- a/phpBB/adm/style/acp_ban.html +++ b/phpBB/adm/style/acp_ban.html @@ -33,7 +33,7 @@ { document.getElementById('acp_unban').unbangivereason.innerHTML = ban_give_reason[option]; document.getElementById('acp_unban').unbanreason.innerHTML = ban_reason[option]; - document.getElementById('acp_unban').unbanlength.innerHTML = ban_length[option]; + document.getElementById('acp_unban').unbanlength.value = ban_length[option]; } // ]]> diff --git a/phpBB/adm/style/acp_email.html b/phpBB/adm/style/acp_email.html index 885809ffe2..ff52500dca 100644 --- a/phpBB/adm/style/acp_email.html +++ b/phpBB/adm/style/acp_email.html @@ -39,6 +39,10 @@ <dd><select id="priority" name="mail_priority_flag">{S_PRIORITY_OPTIONS}</select></dd> </dl> <dl> + <dt><label for="banned">{L_MAIL_BANNED}:</label><br /><span>{L_MAIL_BANNED_EXPLAIN}</span></dt> + <dd><input id="banned" name="mail_banned_flag" type="checkbox" class="radio" /></dd> +</dl> +<dl> <dt><label for="send">{L_SEND_IMMEDIATELY}:</label></dt> <dd><input id="send" type="checkbox" class="radio" name="send_immediately" checked="checked" /></dd> </dl> diff --git a/phpBB/adm/style/acp_ranks.html b/phpBB/adm/style/acp_ranks.html index 9306e30269..2ad8b3e8aa 100644 --- a/phpBB/adm/style/acp_ranks.html +++ b/phpBB/adm/style/acp_ranks.html @@ -35,8 +35,8 @@ </dl> <dl> <dt><label for="special_rank">{L_RANK_SPECIAL}:</label></dt> - <dd><label><input onchange="dE('posts', -1)" type="radio" class="radio" name="special_rank" value="1" id="special_rank"<!-- IF S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> />{L_YES}</label> - <label><input onchange="dE('posts', 1)" type="radio" class="radio" name="special_rank" value="0"<!-- IF not S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> + <dd><label><input onclick="dE('posts', -1)" type="radio" class="radio" name="special_rank" value="1" id="special_rank"<!-- IF S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> />{L_YES}</label> + <label><input onclick="dE('posts', 1)" type="radio" class="radio" name="special_rank" value="0"<!-- IF not S_SPECIAL_RANK --> checked="checked"<!-- ENDIF --> /> {L_NO}</label></dd> </dl> <!-- IF S_SPECIAL_RANK --><div id="posts" style="display: none;"><!-- ELSE --><div id="posts"><!-- ENDIF --> <dl> diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index cb4361dd6f..098cc723d9 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -22,6 +22,21 @@ <dt><label for="new_id">{L_REPLACE}:</label><br /><span>{L_REPLACE_EXPLAIN}</span></dt> <dd><select id="new_id" name="new_id">{S_REPLACE_OPTIONS}</select></dd> </dl> + <!-- IF S_DELETE_STYLE --> + <hr /> + <dl> + <dt><label for="new_template_id">{L_DELETE_TEMPLATE}:</label><br /><span>{L_REPLACE_TEMPLATE_EXPLAIN}</span></dt> + <dd><select id="new_template_id" name="new_template_id">{S_REPLACE_TEMPLATE_OPTIONS}</select></dd> + </dl> + <dl> + <dt><label for="new_theme_id">{L_DELETE_THEME}:</label><br /><span>{L_REPLACE_THEME_EXPLAIN}</span></dt> + <dd><select id="new_theme_id" name="new_theme_id">{S_REPLACE_THEME_OPTIONS}</select></dd> + </dl> + <dl> + <dt><label for="new_imageset_id">{L_DELETE_IMAGESET}:</label><br /><span>{L_REPLACE_IMAGESET_EXPLAIN}</span></dt> + <dd><select id="new_imageset_id" name="new_imageset_id">{S_REPLACE_IMAGESET_OPTIONS}</select></dd> + </dl> + <!-- ENDIF --> <p class="quick"> <input class="button1" type="submit" name="update" value="{L_DELETE}" /> diff --git a/phpBB/adm/style/install_footer.html b/phpBB/adm/style/install_footer.html index 4df43eaaa0..9b5494b8b6 100644 --- a/phpBB/adm/style/install_footer.html +++ b/phpBB/adm/style/install_footer.html @@ -6,20 +6,9 @@ </div> </div> </div> - - <!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 - // --> - + <div id="page-footer"> - Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> + Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group </div> </div> diff --git a/phpBB/adm/style/overall_footer.html b/phpBB/adm/style/overall_footer.html index 8af299ad57..03ca369562 100644 --- a/phpBB/adm/style/overall_footer.html +++ b/phpBB/adm/style/overall_footer.html @@ -6,21 +6,10 @@ </div> </div> </div> - - <!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 - // --> - + <div id="page-footer"> <!-- IF S_COPYRIGHT_HTML --> - Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> + Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> <!-- ENDIF --> diff --git a/phpBB/adm/style/simple_footer.html b/phpBB/adm/style/simple_footer.html index 65cf724c2f..7276fb4b63 100644 --- a/phpBB/adm/style/simple_footer.html +++ b/phpBB/adm/style/simple_footer.html @@ -2,21 +2,10 @@ <br /><br /> </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -// --> - <div id="page-footer"> <!-- IF S_COPYRIGHT_HTML --> - <br />Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> + <br />Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> <!-- ENDIF --> diff --git a/phpBB/common.php b/phpBB/common.php index c8b2fb9609..ae174c8441 100644 --- a/phpBB/common.php +++ b/phpBB/common.php @@ -118,11 +118,6 @@ else define('STRIP', (get_magic_quotes_gpc()) ? true : false); } -if (defined('IN_CRON')) -{ - $phpbb_root_path = dirname(__FILE__) . DIRECTORY_SEPARATOR; -} - if (file_exists($phpbb_root_path . 'config.' . $phpEx)) { require($phpbb_root_path . 'config.' . $phpEx); diff --git a/phpBB/cron.php b/phpBB/cron.php index 3993a149b5..8000066c92 100644 --- a/phpBB/cron.php +++ b/phpBB/cron.php @@ -21,7 +21,6 @@ $user->session_begin(false); $auth->acl($user->data); $cron_type = request_var('cron_type', ''); -$use_shutdown_function = (@function_exists('register_shutdown_function')) ? true : false; // Output transparent gif header('Cache-Control: no-cache'); @@ -30,10 +29,9 @@ header('Content-length: 43'); echo base64_decode('R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='); -// test without flush ;) -// flush(); +// Flush here to prevent browser from showing the page as loading while running cron. +flush(); -// if (!isset($config['cron_lock'])) { set_config('cron_lock', '0', true); @@ -79,23 +77,10 @@ switch ($cron_type) break; } - // A user reported using the mail() function while using shutdown does not work. We do not want to risk that. - if ($use_shutdown_function && !$config['smtp_delivery']) - { - $use_shutdown_function = false; - } - include_once($phpbb_root_path . 'includes/functions_messenger.' . $phpEx); $queue = new queue(); - if ($use_shutdown_function) - { - register_shutdown_function(array(&$queue, 'process')); - } - else - { - $queue->process(); - } + $queue->process(); break; @@ -106,14 +91,7 @@ switch ($cron_type) break; } - if ($use_shutdown_function) - { - register_shutdown_function(array(&$cache, 'tidy')); - } - else - { - $cache->tidy(); - } + $cache->tidy(); break; @@ -138,14 +116,7 @@ switch ($cron_type) break; } - if ($use_shutdown_function) - { - register_shutdown_function(array(&$search, 'tidy')); - } - else - { - $search->tidy(); - } + $search->tidy(); break; @@ -158,14 +129,7 @@ switch ($cron_type) include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - if ($use_shutdown_function) - { - register_shutdown_function('tidy_warnings'); - } - else - { - tidy_warnings(); - } + tidy_warnings(); break; @@ -178,14 +142,7 @@ switch ($cron_type) include_once($phpbb_root_path . 'includes/functions_admin.' . $phpEx); - if ($use_shutdown_function) - { - register_shutdown_function('tidy_database'); - } - else - { - tidy_database(); - } + tidy_database(); break; @@ -196,14 +153,7 @@ switch ($cron_type) break; } - if ($use_shutdown_function) - { - register_shutdown_function(array(&$user, 'session_gc')); - } - else - { - $user->session_gc(); - } + $user->session_gc(); break; @@ -230,26 +180,12 @@ switch ($cron_type) if ($row['prune_days']) { - if ($use_shutdown_function) - { - register_shutdown_function('auto_prune', $row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']); - } - else - { - auto_prune($row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']); - } + auto_prune($row['forum_id'], 'posted', $row['forum_flags'], $row['prune_days'], $row['prune_freq']); } if ($row['prune_viewed']) { - if ($use_shutdown_function) - { - register_shutdown_function('auto_prune', $row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']); - } - else - { - auto_prune($row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']); - } + auto_prune($row['forum_id'], 'viewed', $row['forum_flags'], $row['prune_viewed'], $row['prune_freq']); } } @@ -257,16 +193,8 @@ switch ($cron_type) } // Unloading cache and closing db after having done the dirty work. -if ($use_shutdown_function) -{ - register_shutdown_function('unlock_cron'); - register_shutdown_function('garbage_collection'); -} -else -{ - unlock_cron(); - garbage_collection(); -} +unlock_cron(); +garbage_collection(); exit; diff --git a/phpBB/develop/create_schema_files.php b/phpBB/develop/create_schema_files.php index 0515d801f2..87670722aa 100644 --- a/phpBB/develop/create_schema_files.php +++ b/phpBB/develop/create_schema_files.php @@ -926,7 +926,7 @@ function get_schema_struct() $schema_data['phpbb_bbcodes'] = array( 'COLUMNS' => array( - 'bbcode_id' => array('TINT:3', 0), + 'bbcode_id' => array('USINT', 0), 'bbcode_tag' => array('VCHAR:16', ''), 'bbcode_helpline' => array('VCHAR_UNI', ''), 'display_on_posting' => array('BOOL', 0), diff --git a/phpBB/develop/create_variable_overview.php b/phpBB/develop/create_variable_overview.php index 3782f53e4c..b5ed090a75 100644 --- a/phpBB/develop/create_variable_overview.php +++ b/phpBB/develop/create_variable_overview.php @@ -528,7 +528,7 @@ foreach ($lang_fp as $filepointer) $html_data .= ' <br><br> -<div class="copyright" align="center">Powered by phpBB 2.2 © <a href="http://www.phpbb.com/" target="_phpbb" class="copyright">phpBB Group</a>, 2003</div> +<div class="copyright" align="center">Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group</div> <br clear="all" /></td> </tr> diff --git a/phpBB/develop/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 57230339e8..70c8173a32 100644 --- a/phpBB/develop/mysql_upgrader.php +++ b/phpBB/develop/mysql_upgrader.php @@ -21,6 +21,7 @@ die("Please read the first lines of this script for instructions on how to enable it"); define('IN_PHPBB', true); +$phpbb_root_path = (defined('PHPBB_ROOT_PATH')) ? PHPBB_ROOT_PATH : './'; $phpEx = substr(strrchr(__FILE__, '.'), 1); include($phpbb_root_path . 'common.' . $phpEx); @@ -414,7 +415,7 @@ function get_schema_struct() $schema_data['phpbb_bbcodes'] = array( 'COLUMNS' => array( - 'bbcode_id' => array('TINT:3', 0), + 'bbcode_id' => array('USINT', 0), 'bbcode_tag' => array('VCHAR:16', ''), 'bbcode_helpline' => array('VCHAR_UNI', ''), 'display_on_posting' => array('BOOL', 0), diff --git a/phpBB/docs/AUTHORS b/phpBB/docs/AUTHORS index b3166313c3..83feca009b 100644 --- a/phpBB/docs/AUTHORS +++ b/phpBB/docs/AUTHORS @@ -1,6 +1,6 @@ /** * -* phpBB3 © Copyright 2000, 2002, 2005, 2007 phpBB Group +* phpBB3 © Copyright phpBB Group * http://www.phpbb.com * * This program is free software: you can redistribute it and/or modify @@ -22,20 +22,18 @@ involved in phpBB. phpBB Lead Developer: naderman (Nils Adermann) -phpBB Developers: A_Jelly_Doughnut (Josh Woody) - Acyd Burn (Meik Sievertsen) [Lead 09/2005 - 01/2010] +phpBB Developers: Acyd Burn (Meik Sievertsen) [Lead 09/2005 - 01/2010] APTX (Marek A. R.) bantu (Andreas Fischer) - dhn (Dominik Dröscher) + ckwalsh (Cullen Walsh) igorw (Igor Wiedler) kellanved (Henry Sudhof) nickvergessen (Joas Schilling) + nn- (Oleg Pudeyev) rxu (Ruslan Uzdenov) - Terrafrost (Jim Wigginton) ToonArmy (Chris Smith) -Contributions by: Brainy (Cullen Walsh) - leviatan21 (Gabriel Vazquez) +Contributions by: leviatan21 (Gabriel Vazquez) Raimon (Raimon Meuldijk) Xore (Robert Hetzler) @@ -47,11 +45,14 @@ phpBB Project Manager: theFinn (James Atkinson) [Founder - 04/2007] phpBB Lead Developer: psoTFX (Paul S. Owen) [2001 - 09/2005] -phpBB Developers: Ashe (Ludovic Arnaud) [10/2002 - 11/2003, 06/2006 - 10/2006] - BartVB (Bart van Bragt) [11/2000 - 03/2006] - DavidMJ (David M.) [12/2005 - 08/2009] - GrahamJE (Graham Eames) [09/2005 - 11/2006] - Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009] +phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010] + Ashe (Ludovic Arnaud) [10/2002 - 11/2003, 06/2006 - 10/2006] + BartVB (Bart van Bragt) [11/2000 - 03/2006] + DavidMJ (David M.) [12/2005 - 08/2009] + dhn (Dominik Dröscher) [05/2007 - 01/2011] + GrahamJE (Graham Eames) [09/2005 - 11/2006] + TerraFrost (Jim Wigginton) [04/2009 - 01/2011] + Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009] -- Copyrights -- diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index 66915b18fa..253df4ac56 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="phpBB 3.0.x Changelog" /> <title>phpBB3 • Changelog</title> @@ -1676,7 +1676,7 @@ <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/FAQ.html b/phpBB/docs/FAQ.html index f91d4bc223..83d7a342e0 100644 --- a/phpBB/docs/FAQ.html +++ b/phpBB/docs/FAQ.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="phpBB 3.0.x frequently asked questions" /> <title>phpBB3 • FAQ</title> @@ -328,7 +328,7 @@ I want to sue you because i think you host an illegal board!</h2> <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 5857163759..9f635fe50b 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="phpBB 3.0.x Installation, updating and conversion informations" /> <title>phpBB3 • Install</title> @@ -79,6 +79,7 @@ <li><a href="#postinstall">Important (security related) post-Install tasks for all installation methods</a> <ol style="list-style-type: lower-roman;"> <li><a href="#avatars">Uploadable avatars</a></li> + <li><a href="#webserver_configuration">Webserver configuration</a></li> </ol> </li> <li><a href="#disclaimer">Disclaimer</a></li> @@ -408,6 +409,12 @@ <p>Please be aware that setting a directories permissions to global write access is a potential security issue. While it is unlikely that anything nasty will occur (such as all the avatars being deleted) there are always people out there to cause trouble. Therefore you should monitor this directory and if possible make regular backups.</p> +<a name="webserver_configuration"></a><h3>6.ii. Webserver configuration</h3> + + <p>Depending on your web server you may have to configure your server to deny web access to the <code>cache/</code>, <code>files/</code>, <code>store/</code> and other directories. This is to prevent users from accessing sensitive files.</p> + + <p>For <strong>apache</strong> there are <code>.htaccess</code> files already in place to do this for you. For other webservers you will have to adjust the configuration yourself. Sample files for <strong>nginx</strong> and <strong>lighttpd</strong> to help you get started may be found in docs directory.</p> + </div> <div class="back2top"><a href="#wrap" class="top">Back to Top</a></div> @@ -424,7 +431,7 @@ <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html index bb88fdc01f..7a0a42b34f 100644 --- a/phpBB/docs/README.html +++ b/phpBB/docs/README.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="phpBB 3.0.x Readme" /> <title>phpBB3 • Readme</title> @@ -339,7 +339,7 @@ <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/auth_api.html b/phpBB/docs/auth_api.html index 8973582bdb..88618fa640 100644 --- a/phpBB/docs/auth_api.html +++ b/phpBB/docs/auth_api.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="This is an explanation of how to use the phpBB auth/acl API" /> <title>phpBB3 • Auth API</title> @@ -275,7 +275,7 @@ $auth_admin = new auth_admin(); <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index 5a73554741..cd3c09f6fb 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="Olympus coding guidelines document" /> <title>phpBB3 • Coding Guidelines</title> @@ -240,6 +240,11 @@ PHPBB_ACM_MEMCACHE_PORT (overwrite memcached port, default is 11211) PHPBB_ACM_MEMCACHE_COMPRESS (overwrite memcached compress setting, default is disabled) PHPBB_ACM_MEMCACHE_HOST (overwrite memcached host name, default is localhost) +PHPBB_ACM_REDIS_HOST (overwrite redis host name, default is localhost) +PHPBB_ACM_REDIS_PORT (overwrite redis port, default is 6379) +PHPBB_ACM_REDIS_PASSWORD (overwrite redis password, default is empty) +PHPBB_ACM_REDIS_DB (overwrite redis default database) + PHPBB_QA (Set board to QA-Mode, which means the updater also checks for RC-releases) </pre></div> @@ -1018,7 +1023,7 @@ append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=group&amp; <h4>General function usage: </h4> - <p>Some of these functions are only chosen over others because of personal preference and having no other benefit than to be consistant over the code.</p> + <p>Some of these functions are only chosen over others because of personal preference and having no other benefit than to be consistent over the code.</p> <ul> <li> @@ -2369,7 +2374,7 @@ if (utf8_case_fold_nfc($string1) == utf8_case_fold_nfc($string2)) <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/hook_system.html b/phpBB/docs/hook_system.html index 34055c4661..a5fad0d530 100644 --- a/phpBB/docs/hook_system.html +++ b/phpBB/docs/hook_system.html @@ -8,7 +8,7 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2007 phpBB Group" /> +<meta name="copyright" content="phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="Hook System explanation" /> <title>phpBB3 • Hook System</title> @@ -867,7 +867,7 @@ function phpbb_hook_register(&$hook) <div class="content"> - <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> + <p>This application is opensource software released under the <a href="http://opensource.org/licenses/gpl-license.php">GPL</a>. Please see source code and the docs directory for more details. This package and its contents are Copyright (c) <a href="http://www.phpbb.com/">phpBB Group</a>, All Rights Reserved.</p> </div> diff --git a/phpBB/docs/nginx.conf.sample b/phpBB/docs/nginx.sample.conf index a22a126ff4..40b6ee76da 100644 --- a/phpBB/docs/nginx.conf.sample +++ b/phpBB/docs/nginx.sample.conf @@ -10,14 +10,23 @@ http { gzip_vary on; gzip_http_version 1.1; gzip_min_length 700; + + # Compression levels over 6 do not give an appreciable improvement + # in compression ratio, but take more resources. gzip_comp_level 6; - gzip_disable "MSIE [1-6]\."; + + # IE 6 and lower do not support gzip with Vary correctly. + gzip_disable "msie6"; + # Before nginx 0.7.63: + #gzip_disable "MSIE [1-6]\."; # Catch-all server for requests to invalid hosts. # Also catches vulnerability scanners probing IP addresses. - # Should be first. server { - listen 80; + # default specifies that this block is to be used when + # no other block matches. + listen 80 default; + server_name bogus; return 444; root /var/empty; @@ -26,14 +35,20 @@ http { # If you have domains with and without www prefix, # redirect one to the other. server { - listen 80; + # Default port is 80. + #listen 80; + server_name myforums.com; - rewrite ^(.*)$ http://www.myforums.com$1 permanent; + + # A trick from http://wiki.nginx.org/Pitfalls#Taxing_Rewrites: + rewrite ^ http://www.myforums.com$request_uri permanent; + # Equivalent to: + #rewrite ^(.*)$ http://www.myforums.com$1 permanent; } # The actual board domain. server { - listen 80; + #listen 80; server_name www.myforums.com; root /path/to/phpbb; @@ -46,6 +61,9 @@ http { # Deny access to internal phpbb files. location ~ /(config\.php|common\.php|includes|cache|files|store|images/avatars/upload) { deny all; + # deny was ignored before 0.8.40 for connections over IPv6. + # Use internal directive to prohibit access on older versions. + internal; } # Pass the php scripts to fastcgi server specified in upstream declaration. @@ -60,6 +78,7 @@ http { # Deny access to version control system directories. location ~ /\.svn|/\.git { deny all; + internal; } } diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 5f45b88359..e1ec835b9b 100644 --- a/phpBB/download/file.php +++ b/phpBB/download/file.php @@ -64,7 +64,7 @@ if (isset($_GET['avatar'])) $browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : 'msie 6.0'; $config = $cache->obtain_config(); - $filename = $_GET['avatar']; + $filename = request_var('avatar', ''); $avatar_group = false; $exit = false; @@ -125,11 +125,13 @@ $user->setup('viewtopic'); if (!$download_id) { + send_status_line(404, 'Not Found'); trigger_error('NO_ATTACHMENT_SELECTED'); } if (!$config['allow_attachments'] && !$config['allow_pm_attach']) { + send_status_line(404, 'Not Found'); trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED'); } @@ -142,11 +144,13 @@ $db->sql_freeresult($result); if (!$attachment) { + send_status_line(404, 'Not Found'); trigger_error('ERROR_NO_ATTACHMENT'); } if ((!$attachment['in_message'] && !$config['allow_attachments']) || ($attachment['in_message'] && !$config['allow_pm_attach'])) { + send_status_line(404, 'Not Found'); trigger_error('ATTACHMENT_FUNCTIONALITY_DISABLED'); } @@ -159,6 +163,7 @@ if ($attachment['is_orphan']) if (!$own_attachment || ($attachment['in_message'] && !$auth->acl_get('u_pm_download')) || (!$attachment['in_message'] && !$auth->acl_get('u_download'))) { + send_status_line(404, 'Not Found'); trigger_error('ERROR_NO_ATTACHMENT'); } @@ -191,6 +196,7 @@ else } else { + send_status_line(403, 'Forbidden'); trigger_error('SORRY_AUTH_VIEW_ATTACH'); } } @@ -231,6 +237,7 @@ else $extensions = array(); if (!extension_allowed($row['forum_id'], $attachment['extension'], $extensions)) { + send_status_line(404, 'Forbidden'); trigger_error(sprintf($user->lang['EXTENSION_DISABLED_AFTER_POSTING'], $attachment['extension'])); } } @@ -253,6 +260,7 @@ $db->sql_freeresult($result); if (!$attachment) { + send_status_line(404, 'Not Found'); trigger_error('ERROR_NO_ATTACHMENT'); } @@ -295,6 +303,7 @@ else // This presenting method should no longer be used if (!@is_dir($phpbb_root_path . $config['upload_path'])) { + send_status_line(500, 'Internal Server Error'); trigger_error($user->lang['PHYSICAL_DOWNLOAD_NOT_POSSIBLE']); } @@ -419,6 +428,7 @@ function send_file_to_browser($attachment, $upload_dir, $category) if (!@file_exists($filename)) { + send_status_line(404, 'Not Found'); trigger_error($user->lang['ERROR_NO_ATTACHMENT'] . '<br /><br />' . sprintf($user->lang['FILE_NOT_FOUND_404'], $filename)); } @@ -445,9 +455,11 @@ function send_file_to_browser($attachment, $upload_dir, $category) // PHP track_errors setting On? if (!empty($php_errormsg)) { + send_status_line(500, 'Internal Server Error'); trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg)); } + send_status_line(500, 'Internal Server Error'); trigger_error('UNABLE_TO_DELIVER_FILE'); } diff --git a/phpBB/feed.php b/phpBB/feed.php index c4b71f3a26..d737b8e10c 100644 --- a/phpBB/feed.php +++ b/phpBB/feed.php @@ -95,11 +95,13 @@ while ($row = $feed->get_item()) $title = (isset($row[$feed->get('title')]) && $row[$feed->get('title')] !== '') ? $row[$feed->get('title')] : ((isset($row[$feed->get('title2')])) ? $row[$feed->get('title2')] : ''); - $item_time = (int) $row[$feed->get('date')]; + $published = ($feed->get('published') !== NULL) ? (int) $row[$feed->get('published')] : 0; + $updated = ($feed->get('updated') !== NULL) ? (int) $row[$feed->get('updated')] : 0; $item_row = array( 'author' => ($feed->get('creator') !== NULL) ? $row[$feed->get('creator')] : '', - 'pubdate' => feed_format_date($item_time), + 'published' => ($published > 0) ? feed_format_date($published) : '', + 'updated' => ($updated > 0) ? feed_format_date($updated) : '', 'link' => '', 'title' => censor_text($title), 'category' => ($config['feed_item_statistics'] && !empty($row['forum_id'])) ? $board_url . '/viewforum.' . $phpEx . '?f=' . $row['forum_id'] : '', @@ -113,7 +115,7 @@ while ($row = $feed->get_item()) $item_vars[] = $item_row; - $feed_updated_time = max($feed_updated_time, $item_time); + $feed_updated_time = max($feed_updated_time, $published, $updated); } // If we do not have any items at all, sending the current time is better than sending no time. @@ -192,7 +194,13 @@ foreach ($item_vars as $row) echo '<author><name><![CDATA[' . $row['author'] . ']]></name></author>' . "\n"; } - echo '<updated>' . $row['pubdate'] . '</updated>' . "\n"; + echo '<updated>' . ((!empty($row['updated'])) ? $row['updated'] : $row['published']) . '</updated>' . "\n"; + + if (!empty($row['published'])) + { + echo '<published>' . $row['published'] . '</published>' . "\n"; + } + echo '<id>' . $row['link'] . '</id>' . "\n"; echo '<link href="' . $row['link'] . '"/>' . "\n"; echo '<title type="html"><![CDATA[' . $row['title'] . ']]></title>' . "\n\n"; @@ -675,7 +683,8 @@ class phpbb_feed_post_base extends phpbb_feed_base $this->set('author_id', 'user_id'); $this->set('creator', 'username'); - $this->set('date', 'post_time'); + $this->set('published', 'post_time'); + $this->set('updated', 'post_edit_time'); $this->set('text', 'post_text'); $this->set('bitfield', 'bbcode_bitfield'); @@ -695,7 +704,7 @@ class phpbb_feed_post_base extends phpbb_feed_base if ($config['feed_item_statistics']) { $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row) - . ' ' . $this->separator_stats . ' ' . $user->format_date($row['post_time']) + . ' ' . $this->separator_stats . ' ' . $user->format_date($row[$this->get('published')]) . (($this->is_moderator_approve_forum($row['forum_id']) && !$row['post_approved']) ? ' ' . $this->separator_stats . ' ' . $user->lang['POST_UNAPPROVED'] : ''); } } @@ -717,7 +726,8 @@ class phpbb_feed_topic_base extends phpbb_feed_base $this->set('author_id', 'topic_poster'); $this->set('creator', 'topic_first_poster_name'); - $this->set('date', 'topic_time'); + $this->set('published', 'post_time'); + $this->set('updated', 'post_edit_time'); $this->set('text', 'post_text'); $this->set('bitfield', 'bbcode_bitfield'); @@ -737,7 +747,7 @@ class phpbb_feed_topic_base extends phpbb_feed_base if ($config['feed_item_statistics']) { $item_row['statistics'] = $user->lang['POSTED'] . ' ' . $user->lang['POST_BY_AUTHOR'] . ' ' . $this->user_viewprofile($row) - . ' ' . $this->separator_stats . ' ' . $user->format_date($row[$this->get('date')]) + . ' ' . $this->separator_stats . ' ' . $user->format_date($row[$this->get('published')]) . ' ' . $this->separator_stats . ' ' . $user->lang['REPLIES'] . ' ' . (($this->is_moderator_approve_forum($row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies']) . ' ' . $this->separator_stats . ' ' . $user->lang['VIEWS'] . ' ' . $row['topic_views'] . (($this->is_moderator_approve_forum($row['forum_id']) && ($row['topic_replies_real'] != $row['topic_replies'])) ? ' ' . $this->separator_stats . ' ' . $user->lang['POSTS_UNAPPROVED'] : ''); @@ -800,7 +810,7 @@ class phpbb_feed_overall extends phpbb_feed_post_base // Get the actual data $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, ' . - 'p.post_id, p.topic_id, p.post_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, 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( USERS_TABLE => 'u', @@ -932,7 +942,7 @@ class phpbb_feed_forum extends phpbb_feed_post_base } $this->sql = array( - 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'SELECT' => 'p.post_id, p.topic_id, p.post_time, p.post_edit_time, p.post_approved, 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', @@ -1097,7 +1107,7 @@ class phpbb_feed_topic extends phpbb_feed_post_base global $auth, $db; $this->sql = array( - 'SELECT' => 'p.post_id, p.post_time, p.post_approved, p.post_subject, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url, ' . + 'SELECT' => 'p.post_id, p.post_time, p.post_edit_time, p.post_approved, 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', @@ -1136,7 +1146,7 @@ class phpbb_feed_forums extends phpbb_feed_base $this->set('text', 'forum_desc'); $this->set('bitfield', 'forum_desc_bitfield'); $this->set('bbcode_uid','forum_desc_uid'); - $this->set('date', 'forum_last_post_time'); + $this->set('updated', 'forum_last_post_time'); $this->set('options', 'forum_desc_options'); } @@ -1261,8 +1271,8 @@ class phpbb_feed_news extends phpbb_feed_topic_base $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, - t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, - p.post_id, p.post_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time, + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', @@ -1334,8 +1344,8 @@ class phpbb_feed_topics extends phpbb_feed_topic_base $this->sql = array( 'SELECT' => 'f.forum_id, f.forum_name, - t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, - p.post_id, p.post_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + t.topic_id, t.topic_title, t.topic_poster, t.topic_first_poster_name, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_time, t.topic_last_post_time, + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', @@ -1381,8 +1391,6 @@ class phpbb_feed_topics_active extends phpbb_feed_topic_base $this->set('author_id', 'topic_last_poster_id'); $this->set('creator', 'topic_last_poster_name'); - $this->set('date', 'topic_last_post_time'); - $this->set('text', 'post_text'); } function get_sql() @@ -1434,7 +1442,7 @@ class phpbb_feed_topics_active extends phpbb_feed_topic_base 'SELECT' => 'f.forum_id, f.forum_name, t.topic_id, t.topic_title, t.topic_replies, t.topic_replies_real, t.topic_views, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_post_time, - p.post_id, p.post_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', + p.post_id, p.post_time, p.post_edit_time, p.post_text, p.bbcode_bitfield, p.bbcode_uid, p.enable_bbcode, p.enable_smilies, p.enable_magic_url', 'FROM' => array( TOPICS_TABLE => 't', POSTS_TABLE => 'p', diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index 5c1876d006..524a28561e 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -88,11 +88,11 @@ class acm if (!phpbb_is_writable($this->cache_dir)) { // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) - die($this->cache_dir . ' is NOT writable.'); + die('Fatal: ' . $this->cache_dir . ' is NOT writable.'); exit; } - die('Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx); + die('Fatal: Not able to open ' . $this->cache_dir . 'data_global.' . $phpEx); exit; } diff --git a/phpBB/includes/acm/acm_redis.php b/phpBB/includes/acm/acm_redis.php new file mode 100644 index 0000000000..8954b9d0e7 --- /dev/null +++ b/phpBB/includes/acm/acm_redis.php @@ -0,0 +1,155 @@ +<?php +/** +* +* @package acm +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +// Include the abstract base +if (!class_exists('acm_memory')) +{ + require("{$phpbb_root_path}includes/acm/acm_memory.$phpEx"); +} + +if (!defined('PHPBB_ACM_REDIS_PORT')) +{ + define('PHPBB_ACM_REDIS_PORT', 6379); +} + +if (!defined('PHPBB_ACM_REDIS_HOST')) +{ + define('PHPBB_ACM_REDIS_HOST', 'localhost'); +} + +if (!defined('PHPBB_ACM_REDIS')) +{ + //can define multiple servers with host1/port1,host2/port2 format + define('PHPBB_ACM_REDIS', PHPBB_ACM_REDIS_HOST . '/' . PHPBB_ACM_REDIS_PORT); +} + +/** +* ACM for Redis +* +* Compatible with the php extension phpredis available +* at https://github.com/nicolasff/phpredis +* +* @package acm +*/ +class acm extends acm_memory +{ + var $extension = 'redis'; + + var $redis; + + function acm() + { + // Call the parent constructor + parent::acm_memory(); + + $this->redis = new Redis(); + foreach (explode(',', PHPBB_ACM_REDIS) as $server) + { + $parts = explode('/', $server); + $this->redis->connect(trim($parts[0]), trim($parts[1])); + } + + if (defined('PHPBB_ACM_REDIS_PASSWORD')) + { + if (!$this->redis->auth(PHPBB_ACM_REDIS_PASSWORD)) + { + global $acm_type; + + trigger_error("Incorrect password for the ACM module $acm_type.", E_USER_ERROR); + } + } + + $this->redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP); + $this->redis->setOption(Redis::OPT_PREFIX, $this->key_prefix); + + if (defined('PHPBB_ACM_REDIS_DB')) + { + if (!$this->redis->select(PHPBB_ACM_REDIS_DB)) + { + global $acm_type; + + trigger_error("Incorrect database for the ACM module $acm_type.", E_USER_ERROR); + } + } + } + + /** + * Unload the cache resources + * + * @return void + */ + function unload() + { + parent::unload(); + + $this->redis->close(); + } + + /** + * Purge cache data + * + * @return void + */ + function purge() + { + $this->redis->flushDB(); + + parent::purge(); + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + return $this->redis->get($var); + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + return $this->redis->setex($var, $ttl, $data); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + if ($this->redis->delete($var) > 0) + { + return true; + } + return false; + } +} diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php index 2b706394c4..0644b38eb1 100644 --- a/phpBB/includes/acp/acp_bbcodes.php +++ b/phpBB/includes/acp/acp_bbcodes.php @@ -213,7 +213,7 @@ class acp_bbcodes $bbcode_id = NUM_CORE_BBCODES + 1; } - if ($bbcode_id > 1511) + if ($bbcode_id > BBCODE_LIMIT) { trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING); } diff --git a/phpBB/includes/acp/acp_disallow.php b/phpBB/includes/acp/acp_disallow.php index 9549955cc8..e2176b7bcd 100644 --- a/phpBB/includes/acp/acp_disallow.php +++ b/phpBB/includes/acp/acp_disallow.php @@ -56,6 +56,18 @@ class acp_disallow trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); } + $sql = 'SELECT disallow_id + FROM ' . DISALLOW_TABLE . " + WHERE disallow_username = '" . $db->sql_escape($disallowed_user) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error($user->lang['DISALLOWED_ALREADY'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $sql = 'INSERT INTO ' . DISALLOW_TABLE . ' ' . $db->sql_build_array('INSERT', array('disallow_username' => $disallowed_user)); $db->sql_query($sql); diff --git a/phpBB/includes/acp/acp_email.php b/phpBB/includes/acp/acp_email.php index 350693a630..133fe47e09 100644 --- a/phpBB/includes/acp/acp_email.php +++ b/phpBB/includes/acp/acp_email.php @@ -82,23 +82,48 @@ class acp_email { if ($group_id) { - $sql = 'SELECT u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type - FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug - WHERE ug.group_id = ' . $group_id . ' + $sql_ary = array( + 'SELECT' => 'u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type', + 'FROM' => array( + USERS_TABLE => 'u', + USER_GROUP_TABLE => 'ug', + ), + 'WHERE' => 'ug.group_id = ' . $group_id . ' AND ug.user_pending = 0 AND u.user_id = ug.user_id AND u.user_allow_massemail = 1 - AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') - ORDER BY u.user_lang, u.user_notify_type'; + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')', + 'ORDER_BY' => 'u.user_lang, u.user_notify_type', + ); } else { - $sql = 'SELECT username, username_clean, user_email, user_jabber, user_notify_type, user_lang - FROM ' . USERS_TABLE . ' - WHERE user_allow_massemail = 1 - AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') - ORDER BY user_lang, user_notify_type'; + $sql_ary = array( + 'SELECT' => 'u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type', + 'FROM' => array( + USERS_TABLE => 'u', + ), + 'WHERE' => 'u.user_allow_massemail = 1 + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')', + 'ORDER_BY' => 'u.user_lang, u.user_notify_type', + ); } + + // Mail banned or not + if (!isset($_REQUEST['mail_banned_flag'])) + { + $sql_ary['WHERE'] .= ' AND (b.ban_id IS NULL + OR b.ban_exclude = 1)'; + $sql_ary['LEFT_JOIN'] = array( + array( + 'FROM' => array( + BANLIST_TABLE => 'b', + ), + 'ON' => 'u.user_id = b.ban_userid', + ), + ); + } + $sql = $db->sql_build_query('SELECT', $sql_ary); } $result = $db->sql_query($sql); $row = $db->sql_fetchrow($result); diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 3d64a2acda..24f6cbbcbf 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -394,6 +394,10 @@ class acp_icons { // skip images where add wasn't checked } + else if (!file_exists($phpbb_root_path . $img_path . '/' . $image)) + { + $errors[$image] = 'SMILIE_NO_FILE'; + } else { if ($image_width[$image] == 0 || $image_height[$image] == 0) diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index c2cb2f9c11..598b390302 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -1055,14 +1055,14 @@ class acp_language $iso_src .= htmlspecialchars_decode($row['lang_author']); $compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt'); - // index.html files - $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.html'); - $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.html'); - $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.html'); + // index.htm files + $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.htm'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.htm'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.htm'); if (sizeof($mod_files)) { - $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.html'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.htm'); } $compress->close(); @@ -1217,7 +1217,7 @@ $lang = array_merge($lang, array( '; // Language files in language root directory - $this->main_files = array("common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); + $this->main_files = array("captcha_qa.$phpEx", "captcha_recaptcha.$phpEx", "common.$phpEx", "groups.$phpEx", "install.$phpEx", "mcp.$phpEx", "memberlist.$phpEx", "posting.$phpEx", "search.$phpEx", "ucp.$phpEx", "viewforum.$phpEx", "viewtopic.$phpEx", "help_bbcode.$phpEx", "help_faq.$phpEx"); } /** diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php index b8712b2a3d..60cebe3c08 100644 --- a/phpBB/includes/acp/acp_main.php +++ b/phpBB/includes/acp/acp_main.php @@ -529,7 +529,7 @@ class acp_main ); $log_data = array(); - $log_count = 0; + $log_count = false; if ($auth->acl_get('a_viewlogs')) { diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 2288a0728b..2e43b0545a 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -512,7 +512,7 @@ class acp_profile else if ($field_type == FIELD_INT && $key == 'field_default_value') { // Permit an empty string - if (request_var('field_default_value', '') === '') + if ($action == 'create' && request_var('field_default_value', '') === '') { $var = ''; } diff --git a/phpBB/includes/acp/acp_search.php b/phpBB/includes/acp/acp_search.php index 930c8d2a26..0cd67b1c34 100644 --- a/phpBB/includes/acp/acp_search.php +++ b/phpBB/includes/acp/acp_search.php @@ -392,7 +392,18 @@ class acp_search AND post_id <= ' . (int) ($post_counter + $this->batch_size); $result = $db->sql_query($sql); - while ($row = $db->sql_fetchrow($result)) + $buffer = $db->sql_buffer_nested_transactions(); + + if ($buffer) + { + $rows = $db->sql_fetchrowset($result); + $rows[] = false; // indicate end of array for while loop below + + $db->sql_freeresult($result); + } + + $i = 0; + while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result))) { // Indexing enabled for this forum or global announcement? // Global announcements get indexed by default. @@ -402,7 +413,10 @@ class acp_search } $row_count++; } - $db->sql_freeresult($result); + if (!$buffer) + { + $db->sql_freeresult($result); + } $post_counter += $this->batch_size; } diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 2ccc728031..37cf8d1f72 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -716,7 +716,7 @@ parse_css_file = {PARSE_CSS_FILE} $save_changes = (isset($_POST['save'])) ? true : false; // make sure template_file path doesn't go upwards - $template_file = str_replace('..', '.', $template_file); + $template_file = preg_replace('#\.{2,}#', '.', $template_file); // Retrieve some information about the template $sql = 'SELECT template_storedb, template_path, template_name @@ -1587,23 +1587,23 @@ parse_css_file = {PARSE_CSS_FILE} { case 'style': $sql_from = STYLES_TABLE; - $sql_select = 'style_name'; + $sql_select = 'style_id, style_name, template_id, theme_id, imageset_id'; $sql_where = 'AND style_active = 1'; break; case 'template': $sql_from = STYLES_TEMPLATE_TABLE; - $sql_select = 'template_name, template_path, template_storedb'; + $sql_select = 'template_id, template_name, template_path, template_storedb'; break; case 'theme': $sql_from = STYLES_THEME_TABLE; - $sql_select = 'theme_name, theme_path, theme_storedb'; + $sql_select = 'theme_id, theme_name, theme_path, theme_storedb'; break; case 'imageset': $sql_from = STYLES_IMAGESET_TABLE; - $sql_select = 'imageset_name, imageset_path'; + $sql_select = 'imageset_id, imageset_name, imageset_path'; break; } @@ -1633,37 +1633,14 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); } - $sql = "SELECT {$mode}_id, {$mode}_name - FROM $sql_from - WHERE {$mode}_id <> $style_id - $sql_where - ORDER BY {$mode}_name ASC"; - $result = $db->sql_query($sql); - - $s_options = ''; - - if ($row = $db->sql_fetchrow($result)) - { - do - { - $s_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; - } - while ($row = $db->sql_fetchrow($result)); - } - else - { - trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); - } - $db->sql_freeresult($result); - if ($update) { - $sql = "DELETE FROM $sql_from - WHERE {$mode}_id = $style_id"; - $db->sql_query($sql); - if ($mode == 'style') { + $sql = "DELETE FROM $sql_from + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + $sql = 'UPDATE ' . USERS_TABLE . " SET user_style = $new_id WHERE user_style = $style_id"; @@ -1678,19 +1655,19 @@ parse_css_file = {PARSE_CSS_FILE} { set_config('default_style', $new_id); } + + // Remove the components + $components = array('template', 'theme', 'imageset'); + foreach ($components as $component) + { + $new_id = request_var('new_' . $component . '_id', 0); + $component_id = $style_row[$component . '_id']; + $this->remove_component($component, $component_id, $new_id, $style_id); + } } else { - if ($mode == 'imageset') - { - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " - WHERE imageset_id = $style_id"; - $db->sql_query($sql); - } - $sql = 'UPDATE ' . STYLES_TABLE . " - SET {$mode}_id = $new_id - WHERE {$mode}_id = $style_id"; - $db->sql_query($sql); + $this->remove_component($mode, $style_id, $new_id); } $cache->destroy('sql', STYLES_TABLE); @@ -1700,11 +1677,12 @@ parse_css_file = {PARSE_CSS_FILE} trigger_error($user->lang[$message] . adm_back_link($this->u_action)); } + $this->display_component_options($mode, $style_row[$mode . '_id'], $style_row); + $this->page_title = 'DELETE_' . $l_prefix; $template->assign_vars(array( 'S_DELETE' => true, - 'S_REPLACE_OPTIONS' => $s_options, 'L_TITLE' => $user->lang[$this->page_title], 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], @@ -1718,6 +1696,202 @@ parse_css_file = {PARSE_CSS_FILE} 'NAME' => $style_row[$mode . '_name'], ) ); + + if ($mode == 'style') + { + $template->assign_vars(array( + 'S_DELETE_STYLE' => true, + )); + } + } + + /** + * Remove template/theme/imageset entry from the database + */ + function remove_component($component, $component_id, $new_id, $style_id = false) + { + global $db; + + if (($new_id == 0) || ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id)))) + { + // We can not delete the template, as the user wants to keep the component or an other template is inheriting from this one. + return; + } + + $component_in_use = array(); + if ($component != 'style') + { + $component_in_use = $this->component_in_use($component, $component_id, $style_id); + } + + if (($new_id == -1) && !empty($component_in_use)) + { + // We can not delete the component, as it is still in use + return; + } + + if ($component == 'imageset') + { + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $component_id"; + $db->sql_query($sql); + } + + switch ($component) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE;; + break; + } + + $sql = "DELETE FROM $sql_from + WHERE {$component}_id = $component_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . STYLES_TABLE . " + SET {$component}_id = $new_id + WHERE {$component}_id = $component_id"; + $db->sql_query($sql); + } + + /** + * Display the options which can be used to replace a style/template/theme/imageset + */ + function display_component_options($component, $component_id, $style_row = false, $style_id = false) + { + global $db, $template, $user; + + $component_in_use = array(); + if ($component != 'style') + { + $component_in_use = $this->component_in_use($component, $component_id, $style_id); + } + + $sql_where = ''; + switch ($component) + { + case 'style': + $sql_from = STYLES_TABLE; + $sql_where = 'WHERE style_active = 1'; + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + $sql_where = 'WHERE template_inherits_id <> ' . $component_id; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $s_options = ''; + if (($component != 'style') && empty($component_in_use)) + { + $sql = "SELECT {$component}_id, {$component}_name + FROM $sql_from + WHERE {$component}_id = {$component_id}"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $s_options .= '<option value="-1" selected="selected">' . $user->lang['DELETE_' . strtoupper($component)] . '</option>'; + $s_options .= '<option value="0">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; + } + else + { + $sql = "SELECT {$component}_id, {$component}_name + FROM $sql_from + $sql_where + ORDER BY {$component}_name ASC"; + $result = $db->sql_query($sql); + + $s_keep_option = $s_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + if ($row[$component . '_id'] != $component_id) + { + $s_options .= '<option value="' . $row[$component . '_id'] . '">' . sprintf($user->lang['REPLACE_WITH_OPTION'], $row[$component . '_name']) . '</option>'; + } + else if ($component != 'style') + { + $s_keep_option = '<option value="0" selected="selected">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>'; + } + } + $db->sql_freeresult($result); + $s_options = $s_keep_option . $s_options; + } + + if (!$style_row) + { + $template->assign_var('S_REPLACE_' . strtoupper($component) . '_OPTIONS', $s_options); + } + else + { + $template->assign_var('S_REPLACE_OPTIONS', $s_options); + if ($component == 'style') + { + $components = array('template', 'theme', 'imageset'); + foreach ($components as $component) + { + $this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true); + } + } + } + } + + /** + * Check whether the component is still used by another style or component + */ + function component_in_use($component, $component_id, $style_id = false) + { + global $db; + + $component_in_use = array(); + + if ($style_id) + { + $sql = 'SELECT style_id, style_name + FROM ' . STYLES_TABLE . " + WHERE {$component}_id = {$component_id} + AND style_id <> {$style_id} + ORDER BY style_name ASC"; + } + else + { + $sql = 'SELECT style_id, style_name + FROM ' . STYLES_TABLE . " + WHERE {$component}_id = {$component_id} + ORDER BY style_name ASC"; + } + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $component_in_use[] = $row['style_name']; + } + $db->sql_freeresult($result); + + if ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id))) + { + foreach ($conflicts as $temp_id => $conflict_data) + { + $component_in_use[] = $conflict_data['template_name']; + } + } + + return $component_in_use; } /** diff --git a/phpBB/includes/acp/acp_words.php b/phpBB/includes/acp/acp_words.php index 1cb9545967..88c5bbe592 100644 --- a/phpBB/includes/acp/acp_words.php +++ b/phpBB/includes/acp/acp_words.php @@ -95,6 +95,9 @@ class acp_words trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); } + // Replace multiple consecutive asterisks with single one as those are not needed + $word = preg_replace('#\*{2,}#', '*', $word); + $sql_ary = array( 'word' => $word, 'replacement' => $replacement diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth.php index 02819f9e78..8324cb4977 100644 --- a/phpBB/includes/auth.php +++ b/phpBB/includes/auth.php @@ -109,6 +109,7 @@ class auth */ function _fill_acl($user_permissions) { + $seq_cache = array(); $this->acl = array(); $user_permissions = explode("\n", $user_permissions); @@ -125,8 +126,17 @@ class auth while ($subseq = substr($seq, $i, 6)) { + if (isset($seq_cache[$subseq])) + { + $converted = $seq_cache[$subseq]; + } + else + { + $converted = $seq_cache[$subseq] = str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT); + } + // We put the original bitstring into the acl array - $this->acl[$f] .= str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT); + $this->acl[$f] .= $converted; $i += 6; } } diff --git a/phpBB/includes/cache.php b/phpBB/includes/cache.php index b50fab4ca2..612adcca4f 100644 --- a/phpBB/includes/cache.php +++ b/phpBB/includes/cache.php @@ -82,26 +82,9 @@ class cache extends acm $result = $db->sql_query($sql); $censors = array(); - $unicode = ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) ? true : false; - while ($row = $db->sql_fetchrow($result)) { - if ($unicode) - { - // Unescape the asterisk to simplify further conversions - $row['word'] = str_replace('\*', '*', preg_quote($row['word'], '#')); - - // Replace the asterisk inside the pattern, at the start and at the end of it with regexes - $row['word'] = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*(?=[\p{Nd}\p{L}_])#iu', '#^\*#', '#\*$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $row['word']); - - // Generate the final substitution - $censors['match'][] = '#(?<![\p{Nd}\p{L}_-])(' . $row['word'] . ')(?![\p{Nd}\p{L}_-])#iu'; - } - else - { - $censors['match'][] = '#(?<!\S)(' . str_replace('\*', '\S*?', preg_quote($row['word'], '#')) . ')(?!\S)#iu'; - } - + $censors['match'][] = get_censor_preg_expression($row['word']); $censors['replace'][] = $row['replacement']; } $db->sql_freeresult($result); diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php index 96e39af85b..5f24618aab 100644 --- a/phpBB/includes/captcha/captcha_gd.php +++ b/phpBB/includes/captcha/captcha_gd.php @@ -112,7 +112,7 @@ class captcha $noise_bitmaps = $this->captcha_noise_bg_bitmaps(); for ($i = 0; $i < $code_len; ++$i) { - $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, count($noise_bitmaps['data']))); + $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, sizeof($noise_bitmaps['data']))); list($min, $max) = $noise[$i]->range(); //$box = $noise[$i]->dimensions($sizes[$i]); @@ -1669,32 +1669,32 @@ class captcha 'height' => 15, 'data' => array( - 'A' => $chars['A'][mt_rand(0, min(count($chars['A']), $config['captcha_gd_fonts']) -1)], - 'B' => $chars['B'][mt_rand(0, min(count($chars['B']), $config['captcha_gd_fonts']) -1)], - 'C' => $chars['C'][mt_rand(0, min(count($chars['C']), $config['captcha_gd_fonts']) -1)], - 'D' => $chars['D'][mt_rand(0, min(count($chars['D']), $config['captcha_gd_fonts']) -1)], - 'E' => $chars['E'][mt_rand(0, min(count($chars['E']), $config['captcha_gd_fonts']) -1)], - 'F' => $chars['F'][mt_rand(0, min(count($chars['F']), $config['captcha_gd_fonts']) -1)], - 'G' => $chars['G'][mt_rand(0, min(count($chars['G']), $config['captcha_gd_fonts']) -1)], - 'H' => $chars['H'][mt_rand(0, min(count($chars['H']), $config['captcha_gd_fonts']) -1)], - 'I' => $chars['I'][mt_rand(0, min(count($chars['I']), $config['captcha_gd_fonts']) -1)], - 'J' => $chars['J'][mt_rand(0, min(count($chars['J']), $config['captcha_gd_fonts']) -1)], - 'K' => $chars['K'][mt_rand(0, min(count($chars['K']), $config['captcha_gd_fonts']) -1)], - 'L' => $chars['L'][mt_rand(0, min(count($chars['L']), $config['captcha_gd_fonts']) -1)], - 'M' => $chars['M'][mt_rand(0, min(count($chars['M']), $config['captcha_gd_fonts']) -1)], - 'N' => $chars['N'][mt_rand(0, min(count($chars['N']), $config['captcha_gd_fonts']) -1)], - 'O' => $chars['O'][mt_rand(0, min(count($chars['O']), $config['captcha_gd_fonts']) -1)], - 'P' => $chars['P'][mt_rand(0, min(count($chars['P']), $config['captcha_gd_fonts']) -1)], - 'Q' => $chars['Q'][mt_rand(0, min(count($chars['Q']), $config['captcha_gd_fonts']) -1)], - 'R' => $chars['R'][mt_rand(0, min(count($chars['R']), $config['captcha_gd_fonts']) -1)], - 'S' => $chars['S'][mt_rand(0, min(count($chars['S']), $config['captcha_gd_fonts']) -1)], - 'T' => $chars['T'][mt_rand(0, min(count($chars['T']), $config['captcha_gd_fonts']) -1)], - 'U' => $chars['U'][mt_rand(0, min(count($chars['U']), $config['captcha_gd_fonts']) -1)], - 'V' => $chars['V'][mt_rand(0, min(count($chars['V']), $config['captcha_gd_fonts']) -1)], - 'W' => $chars['W'][mt_rand(0, min(count($chars['W']), $config['captcha_gd_fonts']) -1)], - 'X' => $chars['X'][mt_rand(0, min(count($chars['X']), $config['captcha_gd_fonts']) -1)], - 'Y' => $chars['Y'][mt_rand(0, min(count($chars['Y']), $config['captcha_gd_fonts']) -1)], - 'Z' => $chars['Z'][mt_rand(0, min(count($chars['Z']), $config['captcha_gd_fonts']) -1)], + 'A' => $chars['A'][mt_rand(0, min(sizeof($chars['A']), $config['captcha_gd_fonts']) -1)], + 'B' => $chars['B'][mt_rand(0, min(sizeof($chars['B']), $config['captcha_gd_fonts']) -1)], + 'C' => $chars['C'][mt_rand(0, min(sizeof($chars['C']), $config['captcha_gd_fonts']) -1)], + 'D' => $chars['D'][mt_rand(0, min(sizeof($chars['D']), $config['captcha_gd_fonts']) -1)], + 'E' => $chars['E'][mt_rand(0, min(sizeof($chars['E']), $config['captcha_gd_fonts']) -1)], + 'F' => $chars['F'][mt_rand(0, min(sizeof($chars['F']), $config['captcha_gd_fonts']) -1)], + 'G' => $chars['G'][mt_rand(0, min(sizeof($chars['G']), $config['captcha_gd_fonts']) -1)], + 'H' => $chars['H'][mt_rand(0, min(sizeof($chars['H']), $config['captcha_gd_fonts']) -1)], + 'I' => $chars['I'][mt_rand(0, min(sizeof($chars['I']), $config['captcha_gd_fonts']) -1)], + 'J' => $chars['J'][mt_rand(0, min(sizeof($chars['J']), $config['captcha_gd_fonts']) -1)], + 'K' => $chars['K'][mt_rand(0, min(sizeof($chars['K']), $config['captcha_gd_fonts']) -1)], + 'L' => $chars['L'][mt_rand(0, min(sizeof($chars['L']), $config['captcha_gd_fonts']) -1)], + 'M' => $chars['M'][mt_rand(0, min(sizeof($chars['M']), $config['captcha_gd_fonts']) -1)], + 'N' => $chars['N'][mt_rand(0, min(sizeof($chars['N']), $config['captcha_gd_fonts']) -1)], + 'O' => $chars['O'][mt_rand(0, min(sizeof($chars['O']), $config['captcha_gd_fonts']) -1)], + 'P' => $chars['P'][mt_rand(0, min(sizeof($chars['P']), $config['captcha_gd_fonts']) -1)], + 'Q' => $chars['Q'][mt_rand(0, min(sizeof($chars['Q']), $config['captcha_gd_fonts']) -1)], + 'R' => $chars['R'][mt_rand(0, min(sizeof($chars['R']), $config['captcha_gd_fonts']) -1)], + 'S' => $chars['S'][mt_rand(0, min(sizeof($chars['S']), $config['captcha_gd_fonts']) -1)], + 'T' => $chars['T'][mt_rand(0, min(sizeof($chars['T']), $config['captcha_gd_fonts']) -1)], + 'U' => $chars['U'][mt_rand(0, min(sizeof($chars['U']), $config['captcha_gd_fonts']) -1)], + 'V' => $chars['V'][mt_rand(0, min(sizeof($chars['V']), $config['captcha_gd_fonts']) -1)], + 'W' => $chars['W'][mt_rand(0, min(sizeof($chars['W']), $config['captcha_gd_fonts']) -1)], + 'X' => $chars['X'][mt_rand(0, min(sizeof($chars['X']), $config['captcha_gd_fonts']) -1)], + 'Y' => $chars['Y'][mt_rand(0, min(sizeof($chars['Y']), $config['captcha_gd_fonts']) -1)], + 'Z' => $chars['Z'][mt_rand(0, min(sizeof($chars['Z']), $config['captcha_gd_fonts']) -1)], '1' => array( array(0,0,0,1,1,0,0,0,0), diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/includes/captcha/captcha_gd_wave.php index f706c98d43..27422513d9 100644 --- a/phpBB/includes/captcha/captcha_gd_wave.php +++ b/phpBB/includes/captcha/captcha_gd_wave.php @@ -62,8 +62,8 @@ class captcha 'y' => mt_rand(10, 17) ), 'lower_left' => array( - 'x' => mt_rand($img_x - 5, $img_x - 45), - 'y' => mt_rand($img_y - 0, $img_y - 15) + 'x' => mt_rand($img_x - 45, $img_x - 5), + 'y' => mt_rand($img_y - 15, $img_y - 0), ), ); diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 90440f74b8..ea34eb8e81 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -173,6 +173,9 @@ define('BBCODE_UID_LEN', 8); // Number of core BBCodes define('NUM_CORE_BBCODES', 12); +// BBCode hard limit +define('BBCODE_LIMIT', 1511); + // Smiley hard limit define('SMILEY_LIMIT', 1000); diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index eeddf1f41b..d7860fc8bc 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -242,6 +242,16 @@ class dbal } /** + * Returns whether results of a query need to be buffered to run a transaction while iterating over them. + * + * @return bool Whether buffering is required. + */ + function sql_buffer_nested_transaction() + { + return false; + } + + /** * SQL Transaction * @access private */ @@ -767,7 +777,7 @@ class dbal </div> </div> <div id="page-footer"> - Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> + Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group </div> </div> </body> diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php index 6f60dd5dad..7e3f15ed1d 100644 --- a/phpBB/includes/db/firebird.php +++ b/phpBB/includes/db/firebird.php @@ -28,6 +28,7 @@ class dbal_firebird extends dbal var $last_query_text = ''; var $service_handle = false; var $affected_rows = 0; + var $connect_error = ''; /** * Connect to server @@ -53,9 +54,35 @@ class dbal_firebird extends dbal $use_database = $this->server . ':' . $this->dbname; } - $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3) : @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); + if ($this->persistency) + { + if (!function_exists('ibase_pconnect')) + { + $this->connect_error = 'ibase_pconnect function does not exist, is interbase extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @ibase_pconnect($use_database, $this->user, $sqlpassword, false, false, 3); + } + else + { + if (!function_exists('ibase_connect')) + { + $this->connect_error = 'ibase_connect function does not exist, is interbase extension installed?'; + return $this->sql_error(''); + } + $this->db_connect_id = @ibase_connect($use_database, $this->user, $sqlpassword, false, false, 3); + } - $this->service_handle = (function_exists('ibase_service_attach') && $this->server) ? @ibase_service_attach($this->server, $this->user, $sqlpassword) : false; + // Do not call ibase_service_attach if connection failed, + // otherwise error message from ibase_(p)connect call will be clobbered. + if ($this->db_connect_id && function_exists('ibase_service_attach') && $this->server) + { + $this->service_handle = @ibase_service_attach($this->server, $this->user, $sqlpassword); + } + else + { + $this->service_handle = false; + } return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); } @@ -471,8 +498,24 @@ class dbal_firebird extends dbal */ function _sql_error() { + // Need special handling here because ibase_errmsg returns + // connection errors, however if the interbase extension + // is not installed then ibase_errmsg does not exist and + // we cannot call it. + if (function_exists('ibase_errmsg')) + { + $msg = @ibase_errmsg(); + if (!$msg) + { + $msg = $this->connect_error; + } + } + else + { + $msg = $this->connect_error; + } return array( - 'message' => @ibase_errmsg(), + 'message' => $msg, 'code' => (@function_exists('ibase_errcode') ? @ibase_errcode() : '') ); } diff --git a/phpBB/includes/db/mssqlnative.php b/phpBB/includes/db/mssqlnative.php index 7ed4146f27..e057e7fe74 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -50,7 +50,7 @@ class result_mssqlnative } } - $this->m_row_count = count($this->m_rows); + $this->m_row_count = sizeof($this->m_rows); } private function array_to_obj($array, &$obj) @@ -259,6 +259,14 @@ class dbal_mssqlnative extends dbal } /** + * {@inheritDoc} + */ + function sql_buffer_nested_transaction() + { + return true; + } + + /** * SQL Transaction * @access private */ @@ -628,7 +636,7 @@ class dbal_mssqlnative extends dbal return false; } } - + /** * Allows setting mssqlnative specific query options passed to sqlsrv_query as 4th parameter. */ diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index c8a9a5f604..62b36aa8bf 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -269,11 +269,12 @@ class dbal_oracle extends dbal { $cols = explode(', ', $regs[2]); + preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); + /* The code inside this comment block breaks clob handling, but does allow the database restore script to work. If you want to allow no posts longer than 4KB and/or need the db restore script, uncomment this. - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); if (sizeof($cols) !== sizeof($vals)) { diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php index 4360c790a1..bb116e0763 100644 --- a/phpBB/includes/db/postgres.php +++ b/phpBB/includes/db/postgres.php @@ -18,6 +18,11 @@ if (!defined('IN_PHPBB')) include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); +if (!class_exists('phpbb_error_collector')) +{ + include($phpbb_root_path . 'includes/error_collector.' . $phpEx); +} + /** * PostgreSQL Database Abstraction Layer * Minimum Requirement is Version 7.3+ @@ -26,6 +31,7 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx); class dbal_postgres extends dbal { var $last_query_text = ''; + var $connect_error = ''; /** * Connect to server @@ -81,13 +87,29 @@ class dbal_postgres extends dbal if ($this->persistency) { + if (!function_exists('pg_pconnect')) + { + $this->connect_error = 'pg_pconnect function does not exist, is pgsql extension installed?'; + return $this->sql_error(''); + } + $collector = new phpbb_error_collector; + $collector->install(); $this->db_connect_id = (!$new_link) ? @pg_pconnect($connect_string) : @pg_pconnect($connect_string, PGSQL_CONNECT_FORCE_NEW); } else { + if (!function_exists('pg_connect')) + { + $this->connect_error = 'pg_connect function does not exist, is pgsql extension installed?'; + return $this->sql_error(''); + } + $collector = new phpbb_error_collector; + $collector->install(); $this->db_connect_id = (!$new_link) ? @pg_connect($connect_string) : @pg_connect($connect_string, PGSQL_CONNECT_FORCE_NEW); } + $collector->uninstall(); + if ($this->db_connect_id) { if (version_compare($this->sql_server_info(true), '8.2', '>=')) @@ -102,6 +124,7 @@ class dbal_postgres extends dbal return $this->db_connect_id; } + $this->connect_error = $collector->format_errors(); return $this->sql_error(''); } @@ -371,8 +394,19 @@ class dbal_postgres extends dbal */ function _sql_error() { + // pg_last_error only works when there is an established connection. + // Connection errors have to be tracked by us manually. + if ($this->db_connect_id) + { + $message = @pg_last_error($this->db_connect_id); + } + else + { + $message = $this->connect_error; + } + return array( - 'message' => (!$this->db_connect_id) ? @pg_last_error() : @pg_last_error($this->db_connect_id), + 'message' => $message, 'code' => '' ); } diff --git a/phpBB/includes/error_collector.php b/phpBB/includes/error_collector.php new file mode 100644 index 0000000000..55834f354c --- /dev/null +++ b/phpBB/includes/error_collector.php @@ -0,0 +1,61 @@ +<?php +/** +* +* @package phpBB +* @version $Id$ +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +class phpbb_error_collector +{ + var $errors; + + function phpbb_error_collector() + { + $this->errors = array(); + } + + function install() + { + set_error_handler(array(&$this, 'error_handler')); + } + + function uninstall() + { + restore_error_handler(); + } + + function error_handler($errno, $msg_text, $errfile, $errline) + { + $this->errors[] = array($errno, $msg_text, $errfile, $errline); + } + + function format_errors() + { + $text = ''; + foreach ($this->errors as $error) + { + if (!empty($text)) + { + $text .= "<br />\n"; + } + list($errno, $msg_text, $errfile, $errline) = $error; + $text .= "Errno $errno: $msg_text"; + if (defined('DEBUG_EXTRA') || defined('IN_INSTALL')) + { + $text .= " at $errfile line $errline"; + } + } + return $text; + } +} diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index c7f19b709d..b8ea80ad4a 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -175,10 +175,14 @@ function set_config_count($config_name, $increment, $is_dynamic = false) switch ($db->sql_layer) { case 'firebird': - case 'postgres': $sql_update = 'CAST(CAST(config_value as DECIMAL(255, 0)) + ' . (int) $increment . ' as VARCHAR(255))'; break; + case 'postgres': + // Need to cast to text first for PostgreSQL 7.x + $sql_update = 'CAST(CAST(config_value::text as DECIMAL(255, 0)) + ' . (int) $increment . ' as VARCHAR(255))'; + break; + // MySQL, SQlite, mssql, mssql_odbc, oracle default: $sql_update = 'config_value + ' . (int) $increment; @@ -236,8 +240,8 @@ function unique_id($extra = 'c') if ($dss_seeded !== true && ($config['rand_seed_last_update'] < time() - rand(1,10))) { - set_config('rand_seed', $config['rand_seed'], true); set_config('rand_seed_last_update', time(), true); + set_config('rand_seed', $config['rand_seed'], true); $dss_seeded = true; } @@ -512,7 +516,7 @@ function _hash_crypt_private($password, $setting, &$itoa64) $output = '*'; // Check for correct hash - if (substr($setting, 0, 3) != '$H$') + if (substr($setting, 0, 3) != '$H$' && substr($setting, 0, 3) != '$P$') { return $output; } @@ -1698,7 +1702,7 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s if ($config['load_db_lastread'] && $user->data['is_registered']) { // Get list of the unread topics - $last_mark = $user->data['user_lastmark']; + $last_mark = (int) $user->data['user_lastmark']; $sql_array = array( 'SELECT' => 't.topic_id, t.topic_last_post_time, tt.mark_time as topic_mark_time, ft.mark_time as forum_mark_time', @@ -1717,10 +1721,11 @@ function get_unread_topics($user_id = false, $sql_extra = '', $sql_sort = '', $s ), 'WHERE' => " + t.topic_last_post_time > $last_mark AND ( (tt.mark_time IS NOT NULL AND t.topic_last_post_time > tt.mark_time) OR (tt.mark_time IS NULL AND ft.mark_time IS NOT NULL AND t.topic_last_post_time > ft.mark_time) OR - (tt.mark_time IS NULL AND ft.mark_time IS NULL AND t.topic_last_post_time > $last_mark) + (tt.mark_time IS NULL AND ft.mark_time IS NULL) ) $sql_extra $sql_sort", @@ -2248,7 +2253,10 @@ function append_sid($url, $params = false, $is_amp = true, $session_id = false) /** * Generate board url (example: http://www.example.com/phpBB) +* * @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com) +* +* @return string the generated board url */ function generate_board_url($without_script_path = false) { @@ -2630,8 +2638,14 @@ function send_status_line($code, $message) } else { - if (isset($_SERVER['HTTP_VERSION'])) + if (!empty($_SERVER['SERVER_PROTOCOL'])) { + $version = $_SERVER['SERVER_PROTOCOL']; + } + else if (!empty($_SERVER['HTTP_VERSION'])) + { + // I cannot remember where I got this from. + // This code path may never be reachable in reality. $version = $_SERVER['HTTP_VERSION']; } else @@ -3429,6 +3443,48 @@ function get_preg_expression($mode) } /** +* Generate regexp for naughty words censoring +* Depends on whether installed PHP version supports unicode properties +* +* @param string $word word template to be replaced +* @param bool $use_unicode whether or not to take advantage of PCRE supporting unicode +* +* @return string $preg_expr regex to use with word censor +*/ +function get_censor_preg_expression($word, $use_unicode = true) +{ + static $unicode_support = null; + + // Check whether PHP version supports unicode properties + if (is_null($unicode_support)) + { + $unicode_support = ((version_compare(PHP_VERSION, '5.1.0', '>=') || (version_compare(PHP_VERSION, '5.0.0-dev', '<=') && version_compare(PHP_VERSION, '4.4.0', '>='))) && @preg_match('/\p{L}/u', 'a') !== false) ? true : false; + } + + // Unescape the asterisk to simplify further conversions + $word = str_replace('\*', '*', preg_quote($word, '#')); + + if ($use_unicode && $unicode_support) + { + // Replace asterisk(s) inside the pattern, at the start and at the end of it with regexes + $word = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*+(?=[\p{Nd}\p{L}_])#iu', '#^\*+#', '#\*+$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $word); + + // Generate the final substitution + $preg_expr = '#(?<![\p{Nd}\p{L}_-])(' . $word . ')(?![\p{Nd}\p{L}_-])#iu'; + } + else + { + // Replace the asterisk inside the pattern, at the start and at the end of it with regexes + $word = preg_replace(array('#(?<=\S)\*+(?=\S)#iu', '#^\*+#', '#\*+$#'), array('(\x20*?\S*?)', '\S*?', '\S*?'), $word); + + // Generate the final substitution + $preg_expr = '#(?<!\S)(' . $word . ')(?!\S)#iu'; + } + + return $preg_expr; +} + +/** * Returns the first block of the specified IPv6 address and as many additional * ones as specified in the length paramater. * If length is zero, then an empty string is returned. @@ -3792,7 +3848,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) echo ' </div>'; echo ' </div>'; echo ' <div id="page-footer">'; - echo ' Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>'; + echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group'; echo ' </div>'; echo '</div>'; echo '</body>'; @@ -4208,7 +4264,7 @@ function phpbb_http_login($param) if (!is_null($username) && is_null($password) && strpos($username, 'Basic ') === 0) { list($username, $password) = explode(':', base64_decode(substr($username, 6)), 2); - } + } if (!is_null($username) && !is_null($password)) { @@ -4558,7 +4614,7 @@ function page_footer($run_cron = true) // Call cron-type script $call_cron = false; - if (!defined('IN_CRON') && $run_cron && !$config['board_disable']) + if (!defined('IN_CRON') && $run_cron && !$config['board_disable'] && !$user->data['is_bot']) { $call_cron = true; $time_now = (!empty($user->time_now) && is_int($user->time_now)) ? $user->time_now : time(); diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php index 2aa12adb2e..cb0cf34e69 100644 --- a/phpBB/includes/functions_admin.php +++ b/phpBB/includes/functions_admin.php @@ -2506,6 +2506,7 @@ function cache_moderators() /** * View log +* If $log_count is set to false, we will skip counting all entries in the database. */ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC', $keywords = '') { @@ -2761,16 +2762,19 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id } } - $sql = 'SELECT COUNT(l.log_id) AS total_entries - FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u - WHERE l.log_type = $log_type - AND l.user_id = u.user_id - AND l.log_time >= $limit_days - $sql_keywords - $sql_forum"; - $result = $db->sql_query($sql); - $log_count = (int) $db->sql_fetchfield('total_entries'); - $db->sql_freeresult($result); + if ($log_count !== false) + { + $sql = 'SELECT COUNT(l.log_id) AS total_entries + FROM ' . LOG_TABLE . ' l, ' . USERS_TABLE . " u + WHERE l.log_type = $log_type + AND l.user_id = u.user_id + AND l.log_time >= $limit_days + $sql_keywords + $sql_forum"; + $result = $db->sql_query($sql); + $log_count = (int) $db->sql_fetchfield('total_entries'); + $db->sql_freeresult($result); + } return; } diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 2de7e1b169..acaef49fe8 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -456,7 +456,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod 'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false, 'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false, 'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false, - 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options'])) ? true : false, + 'S_FEED_ENABLED' => ($config['feed_forum'] && !phpbb_optionget(FORUM_OPTION_FEED_EXCLUDE, $row['forum_options']) && $row['forum_type'] == FORUM_POST) ? true : false, 'FORUM_ID' => $row['forum_id'], 'FORUM_NAME' => $row['forum_name'], diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 6fd87db663..271039f415 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -388,7 +388,7 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); $upload = new fileupload(); - if ($config['check_attachment_content']) + if ($config['check_attachment_content'] && isset($config['mime_triggers'])) { $upload->set_disallowed_content(explode('|', $config['mime_triggers'])); } @@ -1479,7 +1479,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) break; case 'delete_first_post': - $sql = 'SELECT p.post_id, p.poster_id, p.post_username, u.username, u.user_colour + $sql = 'SELECT p.post_id, p.poster_id, p.post_time, p.post_username, u.username, u.user_colour FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u WHERE p.topic_id = $topic_id AND p.poster_id = u.user_id @@ -1493,7 +1493,7 @@ function delete_post($forum_id, $topic_id, $post_id, &$data) $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; } - $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "'"; + $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . $db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? $db->sql_escape($row['post_username']) : $db->sql_escape($row['username'])) . "', topic_time = " . (int) $row['post_time']; // Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply" $sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); diff --git a/phpBB/includes/functions_template.php b/phpBB/includes/functions_template.php index 1d3a4d74f8..8636dfe010 100644 --- a/phpBB/includes/functions_template.php +++ b/phpBB/includes/functions_template.php @@ -322,7 +322,7 @@ class template_compile // Is the designer wanting to call another loop in a loop? if (strpos($tag_args, '!') === 0) { - // Count the number if ! occurrences (not allowed in vars) + // Count the number of ! occurrences (not allowed in vars) $no_nesting = substr_count($tag_args, '!'); $tag_args = substr($tag_args, $no_nesting); } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index 7f09cc1640..d5bbd80242 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -458,7 +458,7 @@ class fileerror extends filespec class fileupload { var $allowed_extensions = array(); - var $disallowed_content = array(); + var $disallowed_content = array('body', 'head', 'html', 'img', 'plaintext', 'a href', 'pre', 'script', 'table', 'title'); var $max_filesize = 0; var $min_width = 0; var $min_height = 0; @@ -539,7 +539,7 @@ class fileupload { if ($disallowed_content !== false && is_array($disallowed_content)) { - $this->disallowed_content = $disallowed_content; + $this->disallowed_content = array_diff($disallowed_content, array('')); } } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index f2c80705ba..6b5cca8abb 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -482,44 +482,6 @@ function user_delete($mode, $user_id, $post_username = false) include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); } - $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts - FROM ' . POSTS_TABLE . " - WHERE poster_id = $user_id - GROUP BY topic_id"; - $result = $db->sql_query($sql); - - $topic_id_ary = array(); - while ($row = $db->sql_fetchrow($result)) - { - $topic_id_ary[$row['topic_id']] = $row['total_posts']; - } - $db->sql_freeresult($result); - - if (sizeof($topic_id_ary)) - { - $sql = 'SELECT topic_id, topic_replies, topic_replies_real - FROM ' . TOPICS_TABLE . ' - WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); - $result = $db->sql_query($sql); - - $del_topic_ary = array(); - while ($row = $db->sql_fetchrow($result)) - { - if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) - { - $del_topic_ary[] = $row['topic_id']; - } - } - $db->sql_freeresult($result); - - if (sizeof($del_topic_ary)) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . $db->sql_in_set('topic_id', $del_topic_ary); - $db->sql_query($sql); - } - } - // Delete posts, attachments, etc. delete_posts('poster_id', $user_id); @@ -771,7 +733,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas } else { - trigger_error('LENGTH_BAN_INVALID'); + trigger_error('LENGTH_BAN_INVALID', E_USER_WARNING); } } } @@ -831,7 +793,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas // Make sure we have been given someone to ban if (!sizeof($sql_usernames)) { - trigger_error('NO_USER_SPECIFIED'); + trigger_error('NO_USER_SPECIFIED', E_USER_WARNING); } $sql = 'SELECT user_id @@ -862,7 +824,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas else { $db->sql_freeresult($result); - trigger_error('NO_USERS'); + trigger_error('NO_USERS', E_USER_WARNING); } $db->sql_freeresult($result); break; @@ -964,7 +926,7 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas if (empty($banlist_ary)) { - trigger_error('NO_IPS_DEFINED'); + trigger_error('NO_IPS_DEFINED', E_USER_WARNING); } } break; @@ -992,12 +954,12 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas if (sizeof($ban_list) == 0) { - trigger_error('NO_EMAILS_DEFINED'); + trigger_error('NO_EMAILS_DEFINED', E_USER_WARNING); } break; default: - trigger_error('NO_MODE'); + trigger_error('NO_MODE', E_USER_WARNING); break; } @@ -1460,6 +1422,31 @@ function validate_match($string, $optional = false, $match = '') } /** +* Validate Language Pack ISO Name +* +* Tests whether a language name is valid and installed +* +* @param string $lang_iso The language string to test +* +* @return bool|string Either false if validation succeeded or +* a string which will be used as the error message +* (with the variable name appended) +*/ +function validate_language_iso_name($lang_iso) +{ + global $db; + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'"; + $result = $db->sql_query($sql); + $lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + return ($lang_id) ? false : 'WRONG_DATA'; +} + +/** * Check to see if the username has been taken, or if it is disallowed. * Also checks if it includes the " character, which we don't allow in usernames. * Used for registering, changing names, and posting anonymously with a username @@ -1618,8 +1605,9 @@ function validate_password($password) { global $config, $db, $user; - if (!$password) + if ($password === '' || $config['pass_complex'] === 'PASS_TYPE_ANY') { + // Password empty or no password complexity required. return false; } @@ -1630,7 +1618,6 @@ function validate_password($password) { $upp = '\p{Lu}'; $low = '\p{Ll}'; - $let = '\p{L}'; $num = '\p{N}'; $sym = '[^\p{Lu}\p{Ll}\p{N}]'; $pcre = true; @@ -1640,7 +1627,6 @@ function validate_password($password) mb_regex_encoding('UTF-8'); $upp = '[[:upper:]]'; $low = '[[:lower:]]'; - $let = '[[:lower:][:upper:]]'; $num = '[[:digit:]]'; $sym = '[^[:upper:][:lower:][:digit:]]'; $mbstring = true; @@ -1649,7 +1635,6 @@ function validate_password($password) { $upp = '[A-Z]'; $low = '[a-z]'; - $let = '[a-zA-Z]'; $num = '[0-9]'; $sym = '[^A-Za-z0-9]'; $pcre = true; @@ -1659,22 +1644,22 @@ function validate_password($password) switch ($config['pass_complex']) { - case 'PASS_TYPE_CASE': - $chars[] = $low; - $chars[] = $upp; - break; + // No break statements below ... + // We require strong passwords in case pass_complex is not set or is invalid + default: + + // Require mixed case letters, numbers and symbols + case 'PASS_TYPE_SYMBOL': + $chars[] = $sym; + // Require mixed case letters and numbers case 'PASS_TYPE_ALPHA': - $chars[] = $let; $chars[] = $num; - break; - case 'PASS_TYPE_SYMBOL': + // Require mixed case letters + case 'PASS_TYPE_CASE': $chars[] = $low; $chars[] = $upp; - $chars[] = $num; - $chars[] = $sym; - break; } if ($pcre) @@ -2080,7 +2065,7 @@ function avatar_upload($data, &$error) // Init upload class include_once($phpbb_root_path . 'includes/functions_upload.' . $phpEx); - $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), $config['avatar_filesize'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], explode('|', $config['mime_triggers'])); + $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), $config['avatar_filesize'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], (isset($config['mime_triggers']) ? explode('|', $config['mime_triggers']) : false)); if (!empty($_FILES['uploadfile']['name'])) { diff --git a/phpBB/includes/mcp/mcp_front.php b/phpBB/includes/mcp/mcp_front.php index 50e14b9336..af262baa29 100644 --- a/phpBB/includes/mcp/mcp_front.php +++ b/phpBB/includes/mcp/mcp_front.php @@ -350,7 +350,7 @@ function mcp_front_view($id, $mode, $action) // Add forum_id 0 for global announcements $forum_list[] = 0; - $log_count = 0; + $log_count = false; $log = array(); view_log('mod', $log, $log_count, 5, 0, $forum_list); diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index d5551f5114..ad10a52705 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -1048,37 +1048,38 @@ function mcp_fork_topic($topic_ids) $total_posts = 0; $new_topic_id_list = array(); - if ($topic_data['enable_indexing']) - { - // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = basename($config['search_type']); - if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) + foreach ($topic_data as $topic_id => $topic_row) + { + if (!isset($search_type) && $topic_row['enable_indexing']) { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } + // Select the search method and do some additional checks to ensure it can actually be utilised + $search_type = basename($config['search_type']); - if (!class_exists($search_type)) - { - include("{$phpbb_root_path}includes/search/$search_type.$phpEx"); - } + if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx)) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + + if (!class_exists($search_type)) + { + include("{$phpbb_root_path}includes/search/$search_type.$phpEx"); + } - $error = false; - $search = new $search_type($error); - $search_mode = 'post'; + $error = false; + $search = new $search_type($error); + $search_mode = 'post'; - if ($error) + if ($error) + { + trigger_error($error); + } + } + else if (!isset($search_type) && !$topic_row['enable_indexing']) { - trigger_error($error); + $search_type = false; } - } - else - { - $search_type = false; - } - foreach ($topic_data as $topic_id => $topic_row) - { $sql_ary = array( 'forum_id' => (int) $to_forum_id, 'icon_id' => (int) $topic_row['icon_id'], @@ -1187,9 +1188,9 @@ function mcp_fork_topic($topic_ids) // Copy whether the topic is dotted markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']); - if ($search_type) + if (!empty($search_type)) { - $search->index($search_mode, $sql_ary['post_id'], $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id); + $search->index($search_mode, $new_post_id, $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id); $search_mode = 'reply'; // After one we index replies } diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 7098b4bbce..de7f3e63ee 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -227,10 +227,10 @@ function mcp_post_details($id, $mode, $action) // Get User Notes $log_data = array(); - $log_count = 0; + $log_count = false; view_log('user', $log_data, $log_count, $config['posts_per_page'], 0, 0, 0, $post_info['user_id']); - if ($log_count) + if (!empty($log_data)) { $template->assign_var('S_USER_NOTES', true); diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index b2d0b6c566..6951dcf820 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -110,19 +110,19 @@ class bbcode_firstpass extends bbcode // order, so it is important to keep [code] in first position and // [quote] in second position. $this->bbcodes = array( - 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")), - 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#ise' => "\$this->bbcode_quote('\$0')")), - 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#ise' => "\$this->bbcode_attachment('\$1', '\$2')")), - 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#ise' => "\$this->bbcode_strong('\$1')")), - 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#ise' => "\$this->bbcode_italic('\$1')")), - 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")), - 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#iUe' => "\$this->bbcode_img('\$1')")), - 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")), - 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#ise' => "\$this->bbcode_underline('\$1')")), - 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#ise' => "\$this->bbcode_parse_list('\$0')")), - 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#ise' => "\$this->validate_email('\$1', '\$2')")), - 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')")) + 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#uise' => "\$this->bbcode_code('\$1', '\$2')")), + 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#uise' => "\$this->bbcode_quote('\$0')")), + 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#uise' => "\$this->bbcode_attachment('\$1', '\$2')")), + 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#uise' => "\$this->bbcode_strong('\$1')")), + 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#uise' => "\$this->bbcode_italic('\$1')")), + 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#uiUe' => "\$this->validate_url('\$2', '\$3')")), + 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#uiUe' => "\$this->bbcode_img('\$1')")), + 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#uise' => "\$this->bbcode_size('\$1', '\$2')")), + 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!uise' => "\$this->bbcode_color('\$1', '\$2')")), + 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#uise' => "\$this->bbcode_underline('\$1')")), + 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#uise' => "\$this->bbcode_parse_list('\$0')")), + 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#uise' => "\$this->validate_email('\$1', '\$2')")), + 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#uie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')")) ); // Zero the parsed items array @@ -1332,7 +1332,9 @@ class parse_message extends bbcode_firstpass { if ($max_smilies) { - $num_matches = preg_match_all('#(?<=^|[\n .])(?:' . implode('|', $match) . ')(?![^<>]*>)#', $this->message, $matches); + // 'u' modifier has been added to correctly parse smilies within unicode strings + // For details: http://tracker.phpbb.com/browse/PHPBB3-10117 + $num_matches = preg_match_all('#(?<=^|[\n .])(?:' . implode('|', $match) . ')(?![^<>]*>)#u', $this->message, $matches); unset($matches); if ($num_matches !== false && $num_matches > $max_smilies) @@ -1343,7 +1345,10 @@ class parse_message extends bbcode_firstpass } // Make sure the delimiter # is added in front and at the end of every element within $match - $this->message = trim(preg_replace(explode(chr(0), '#(?<=^|[\n .])' . implode('(?![^<>]*>)#' . chr(0) . '#(?<=^|[\n .])', $match) . '(?![^<>]*>)#'), $replace, $this->message)); + // 'u' modifier has been added to correctly parse smilies within unicode strings + // For details: http://tracker.phpbb.com/browse/PHPBB3-10117 + + $this->message = trim(preg_replace(explode(chr(0), '#(?<=^|[\n .])' . implode('(?![^<>]*>)#u' . chr(0) . '#(?<=^|[\n .])', $match) . '(?![^<>]*>)#u'), $replace, $this->message)); } } diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 5f5b39fe27..d803f8d799 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -583,6 +583,13 @@ class session $bot = false; } + // 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 ($bot && isset($_GET['sid'])) + { + redirect(build_url(array('sid'))); + } + // If no data was returned one or more of the following occurred: // Key didn't match one in the DB // User does not exist @@ -619,12 +626,6 @@ 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; } @@ -1966,6 +1967,7 @@ class user extends session $key_found = $num; } + break; } } diff --git a/phpBB/includes/template.php b/phpBB/includes/template.php index 6347633b14..9ac395344f 100644 --- a/phpBB/includes/template.php +++ b/phpBB/includes/template.php @@ -276,7 +276,7 @@ class template $this->files_template[$handle] = (isset($user->theme['template_id'])) ? $user->theme['template_id'] : 0; $recompile = false; - if (!file_exists($filename) || @filesize($filename) === 0) + if (!file_exists($filename) || @filesize($filename) === 0 || defined('DEBUG_EXTRA')) { $recompile = true; } diff --git a/phpBB/includes/ucp/ucp_activate.php b/phpBB/includes/ucp/ucp_activate.php index 8debaabf31..b00c1b9f52 100644 --- a/phpBB/includes/ucp/ucp_activate.php +++ b/phpBB/includes/ucp/ucp_activate.php @@ -98,6 +98,13 @@ class ucp_activate SET user_actkey = '' WHERE user_id = {$user_row['user_id']}"; $db->sql_query($sql); + + // Create the correct logs + add_log('user', $user_row['user_id'], 'LOG_USER_ACTIVE_USER'); + if ($auth->acl_get('a_user')) + { + add_log('admin', 'LOG_USER_ACTIVE', $user_row['username']); + } } if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password) diff --git a/phpBB/includes/ucp/ucp_pm_viewfolder.php b/phpBB/includes/ucp/ucp_pm_viewfolder.php index 6b7172ca2b..bd7bf89854 100644 --- a/phpBB/includes/ucp/ucp_pm_viewfolder.php +++ b/phpBB/includes/ucp/ucp_pm_viewfolder.php @@ -169,6 +169,7 @@ function view_folder($id, $mode, $folder_id, $folder) 'PM_IMG' => ($row_indicator) ? $user->img('pm_' . $row_indicator, '') : '', 'ATTACH_ICON_IMG' => ($auth->acl_get('u_pm_download') && $row['message_attachment'] && $config['allow_pm_attach']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'S_PM_UNREAD' => ($row['pm_unread']) ? true : false, 'S_PM_DELETED' => ($row['pm_deleted']) ? true : false, 'S_PM_REPORTED' => (isset($row['report_id'])) ? true : false, 'S_AUTHOR_DELETED' => ($row['author_id'] == ANONYMOUS) ? true : false, diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index b91636a9c8..d0cfa1ffd2 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -208,7 +208,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=pm&mode=compose&u=' . $author_id) : '', 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', - 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/webmsg.php?to=' . urlencode($user_info['user_icq']) : '', + 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people' . urlencode($user_info['user_icq']) . '/' : '', 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $author_id) : '', 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $author_id) : '', diff --git a/phpBB/includes/ucp/ucp_prefs.php b/phpBB/includes/ucp/ucp_prefs.php index cc8565e69d..13167b2b3d 100644 --- a/phpBB/includes/ucp/ucp_prefs.php +++ b/phpBB/includes/ucp/ucp_prefs.php @@ -65,7 +65,7 @@ class ucp_prefs $error = validate_data($data, array( 'dateformat' => array('string', false, 1, 30), - 'lang' => array('match', false, '#^[a-z0-9_\-]{2,}$#i'), + 'lang' => array('language_iso_name'), 'tz' => array('num', false, -14, 14), )); diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 7fd99da55a..13b9945851 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -56,7 +56,7 @@ class ucp_register { $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); - if (file_exists($user->lang_path . $use_lang . '/')) + if (!validate_language_iso_name($use_lang)) { if ($change_lang) { @@ -210,7 +210,7 @@ class ucp_register array('email')), 'email_confirm' => array('string', false, 6, 60), 'tz' => array('num', false, -14, 14), - 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), + 'lang' => array('language_iso_name'), )); if (!check_form_key('ucp_register')) diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index efe2bc2962..b6eee8d621 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -134,7 +134,7 @@ $config_schema = array( 'avatar_filesize' => 'avatar_filesize', 'avatar_max_width' => 'avatar_max_width', 'avatar_max_height' => 'avatar_max_height', - 'default_dateformat' => 'default_dateformat', + 'default_dateformat' => 'phpbb_set_encoding(default_dateformat)', 'board_timezone' => 'board_timezone', 'allow_privmsg' => 'not(privmsg_disable)', 'gzip_compress' => 'gzip_compress', diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 10308826e0..01048520d2 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -227,7 +227,7 @@ if (empty($config['dbms_version'])) set_config('dbms_version', $db->sql_server_info(true)); } -// Firebird update from Firebord 2.0 to 2.1+ required? +// Firebird update from Firebird 2.0 to 2.1+ required? if ($db->sql_layer == 'firebird') { // We do not trust any PHP5 function enabled, we will simply test for a function new in 2.1 @@ -511,7 +511,7 @@ function _print_footer() </div> <div id="page-footer"> - Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> + Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group </div> </div> @@ -916,6 +916,15 @@ function database_update_info() '3.0.7-PL1' => array(), // No changes from 3.0.8-RC1 to 3.0.8 '3.0.8-RC1' => array(), + + // Changes from 3.0.8 to 3.0.9-RC1 + '3.0.8' => array( + 'change_columns' => array( + BBCODES_TABLE => array( + 'bbcode_id' => array('USINT', 0), + ), + ), + ), ); } @@ -1858,6 +1867,30 @@ function change_database_data(&$no_updates, $version) // No changes from 3.0.8-RC1 to 3.0.8 case '3.0.8-RC1': break; + + // Changes from 3.0.8 to 3.0.9-RC1 + case '3.0.8': + // Update file extension group names to use language strings, again. + $sql = 'SELECT group_id, group_name + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE group_name ' . $db->sql_like_expression('EXT_GROUP_' . $db->any_char); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary = array( + 'group_name' => substr($row['group_name'], 10), // Strip off 'EXT_GROUP_' + ); + + $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE group_id = ' . $row['group_id']; + _sql($sql, $errored, $error_ary); + } + $db->sql_freeresult($result); + + $no_updates = false; + break; } } diff --git a/phpBB/install/index.php b/phpBB/install/index.php index eb51ca5fb2..49c99da0d7 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -652,7 +652,7 @@ class module echo ' </div>'; echo ' </div>'; echo ' <div id="page-footer">'; - echo ' Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>'; + echo ' Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group'; echo ' </div>'; echo '</div>'; echo '</body>'; diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 2dd58584f4..9fe0c8aed5 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -1882,7 +1882,7 @@ class install_install extends module if (!$user_id) { - // If we can't insert this user then continue to the next one to avoid inconsistant data + // If we can't insert this user then continue to the next one to avoid inconsistent data $this->p_master->db_error('Unable to insert bot into users table', $db->sql_error_sql, __LINE__, __FILE__, true); continue; } diff --git a/phpBB/install/schemas/mysql_40_schema.sql b/phpBB/install/schemas/mysql_40_schema.sql index 19b1b4f0f7..eeaec4ccf6 100644 --- a/phpBB/install/schemas/mysql_40_schema.sql +++ b/phpBB/install/schemas/mysql_40_schema.sql @@ -110,7 +110,7 @@ CREATE TABLE phpbb_banlist ( # Table: 'phpbb_bbcodes' CREATE TABLE phpbb_bbcodes ( - bbcode_id tinyint(3) DEFAULT '0' NOT NULL, + bbcode_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, bbcode_tag varbinary(16) DEFAULT '' NOT NULL, bbcode_helpline blob NOT NULL, display_on_posting tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/mysql_41_schema.sql b/phpBB/install/schemas/mysql_41_schema.sql index 3b70630a9e..3a3b4ab2fd 100644 --- a/phpBB/install/schemas/mysql_41_schema.sql +++ b/phpBB/install/schemas/mysql_41_schema.sql @@ -110,7 +110,7 @@ CREATE TABLE phpbb_banlist ( # Table: 'phpbb_bbcodes' CREATE TABLE phpbb_bbcodes ( - bbcode_id tinyint(3) DEFAULT '0' NOT NULL, + bbcode_id smallint(4) UNSIGNED DEFAULT '0' NOT NULL, bbcode_tag varchar(16) DEFAULT '' NOT NULL, bbcode_helpline varchar(255) DEFAULT '' NOT NULL, display_on_posting tinyint(1) UNSIGNED DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/oracle_schema.sql b/phpBB/install/schemas/oracle_schema.sql index d577fce46c..9c25af2512 100644 --- a/phpBB/install/schemas/oracle_schema.sql +++ b/phpBB/install/schemas/oracle_schema.sql @@ -254,7 +254,7 @@ END; Table: 'phpbb_bbcodes' */ CREATE TABLE phpbb_bbcodes ( - bbcode_id number(3) DEFAULT '0' NOT NULL, + bbcode_id number(4) DEFAULT '0' NOT NULL, bbcode_tag varchar2(16) DEFAULT '' , bbcode_helpline varchar2(765) DEFAULT '' , display_on_posting number(1) DEFAULT '0' NOT NULL, diff --git a/phpBB/install/schemas/postgres_schema.sql b/phpBB/install/schemas/postgres_schema.sql index 50b3979adb..a2d4dc3e0b 100644 --- a/phpBB/install/schemas/postgres_schema.sql +++ b/phpBB/install/schemas/postgres_schema.sql @@ -213,7 +213,7 @@ CREATE INDEX phpbb_banlist_ban_ip ON phpbb_banlist (ban_ip, ban_exclude); Table: 'phpbb_bbcodes' */ CREATE TABLE phpbb_bbcodes ( - bbcode_id INT2 DEFAULT '0' NOT NULL, + bbcode_id INT2 DEFAULT '0' NOT NULL CHECK (bbcode_id >= 0), bbcode_tag varchar(16) DEFAULT '' NOT NULL, bbcode_helpline varchar(255) DEFAULT '' NOT NULL, display_on_posting INT2 DEFAULT '0' NOT NULL CHECK (display_on_posting >= 0), diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 700d4d63d1..ea4157d6a3 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -743,15 +743,15 @@ INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_orde INSERT INTO phpbb_reports_reasons (reason_title, reason_description, reason_order) VALUES ('other', '{L_REPORT_OTHER}', 4); # -- extension_groups -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_IMAGES}', 1, 1, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_ARCHIVES}', 0, 1, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_PLAIN_TEXT}', 0, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_DOCUMENTS}', 0, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_REAL_MEDIA}', 3, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_WINDOWS_MEDIA}', 2, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_FLASH_FILES}', 5, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_QUICKTIME_MEDIA}', 6, 0, 1, '', 0, ''); -INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('{L_EXT_GROUP_DOWNLOADABLE_FILES}', 0, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('IMAGES', 1, 1, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('ARCHIVES', 0, 1, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('PLAIN_TEXT', 0, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOCUMENTS', 0, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('REAL_MEDIA', 3, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('WINDOWS_MEDIA', 2, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('FLASH_FILES', 5, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('QUICKTIME_MEDIA', 6, 0, 1, '', 0, ''); +INSERT INTO phpbb_extension_groups (group_name, cat_id, allow_group, download_mode, upload_icon, max_filesize, allowed_forums) VALUES ('DOWNLOADABLE_FILES', 0, 0, 1, '', 0, ''); # -- extensions INSERT INTO phpbb_extensions (group_id, extension) VALUES (1, 'gif'); diff --git a/phpBB/install/schemas/sqlite_schema.sql b/phpBB/install/schemas/sqlite_schema.sql index 7ee821d395..8661bb7578 100644 --- a/phpBB/install/schemas/sqlite_schema.sql +++ b/phpBB/install/schemas/sqlite_schema.sql @@ -108,7 +108,7 @@ CREATE INDEX phpbb_banlist_ban_ip ON phpbb_banlist (ban_ip, ban_exclude); # Table: 'phpbb_bbcodes' CREATE TABLE phpbb_bbcodes ( - bbcode_id tinyint(3) NOT NULL DEFAULT '0', + bbcode_id INTEGER UNSIGNED NOT NULL DEFAULT '0', bbcode_tag varchar(16) NOT NULL DEFAULT '', bbcode_helpline varchar(255) NOT NULL DEFAULT '', display_on_posting INTEGER UNSIGNED NOT NULL DEFAULT '0', diff --git a/phpBB/language/en/acp/email.php b/phpBB/language/en/acp/email.php index 4427bfff01..38c9f19c27 100644 --- a/phpBB/language/en/acp/email.php +++ b/phpBB/language/en/acp/email.php @@ -52,14 +52,16 @@ $lang = array_merge($lang, array( 'SEND_TO_GROUP' => 'Send to group', 'SEND_TO_USERS' => 'Send to users', 'SEND_TO_USERS_EXPLAIN' => 'Entering names here will override any group selected above. Enter each username on a new line.', - + + 'MAIL_BANNED' => 'Mail banned users', + 'MAIL_BANNED_EXPLAIN' => 'When sending a mass e-mail to a group you can select here whether banned users will also receive the e-mail.', 'MAIL_HIGH_PRIORITY' => 'High', 'MAIL_LOW_PRIORITY' => 'Low', 'MAIL_NORMAL_PRIORITY' => 'Normal', 'MAIL_PRIORITY' => 'Mail priority', 'MASS_MESSAGE' => 'Your message', 'MASS_MESSAGE_EXPLAIN' => 'Please note that you may enter only plain text. All markup will be removed before sending.', - + 'NO_EMAIL_MESSAGE' => 'You must enter a message.', 'NO_EMAIL_SUBJECT' => 'You must specify a subject for your message.', )); diff --git a/phpBB/language/en/acp/posting.php b/phpBB/language/en/acp/posting.php index 443f4a3ea2..9719287c2a 100644 --- a/phpBB/language/en/acp/posting.php +++ b/phpBB/language/en/acp/posting.php @@ -168,8 +168,9 @@ $lang = array_merge($lang, array( 'SMILIES_CONFIG' => 'Smiley configuration', 'SMILIES_DELETED' => 'The smiley has been removed successfully.', 'SMILIES_EDIT' => 'Edit smiley', - 'SMILIE_NO_CODE' => 'The smilie “%s” was ignored, as there was no code entered.', - 'SMILIE_NO_EMOTION' => 'The smilie “%s” was ignored, as there was no emotion entered.', + 'SMILIE_NO_CODE' => 'The smiley “%s” was ignored, as there was no code entered.', + 'SMILIE_NO_EMOTION' => 'The smiley “%s” was ignored, as there was no emotion entered.', + 'SMILIE_NO_FILE' => 'The smiley “%s” was ignored, as the file is missing.', 'SMILIES_NONE_EDITED' => 'No smilies were updated.', 'SMILIES_ONE_EDITED' => 'The smiley has been updated successfully.', 'SMILIES_EDITED' => 'The smilies have been updated successfully.', @@ -233,13 +234,13 @@ $lang = array_merge($lang, array( // Disallow Usernames $lang = array_merge($lang, array( - 'ACP_DISALLOW_EXPLAIN' => 'Here you can control usernames which will not be allowed to be used. Disallowed usernames are allowed to contain a wildcard character of *. Please note that you will not be allowed to specify any username that has already been registered, you must first delete that name then disallow it.', + 'ACP_DISALLOW_EXPLAIN' => 'Here you can control usernames which will not be allowed to be used. Disallowed usernames are allowed to contain a wildcard character of *.', 'ADD_DISALLOW_EXPLAIN' => 'You can disallow a username using the wildcard character * to match any character.', 'ADD_DISALLOW_TITLE' => 'Add a disallowed username', 'DELETE_DISALLOW_EXPLAIN' => 'You can remove a disallowed username by selecting the username from this list and clicking submit.', 'DELETE_DISALLOW_TITLE' => 'Remove a disallowed username', - 'DISALLOWED_ALREADY' => 'The name you entered could not be disallowed. It either already exists in the list, exists in the word censor list, or a matching username is present.', + 'DISALLOWED_ALREADY' => 'The name you entered is already disallowed.', 'DISALLOWED_DELETED' => 'The disallowed username has been successfully removed.', 'DISALLOW_SUCCESSFUL' => 'The disallowed username has been successfully added.', diff --git a/phpBB/language/en/acp/styles.php b/phpBB/language/en/acp/styles.php index f161a7e6e6..8f65b3ef5f 100644 --- a/phpBB/language/en/acp/styles.php +++ b/phpBB/language/en/acp/styles.php @@ -78,7 +78,7 @@ $lang = array_merge($lang, array( 'DELETE_IMAGESET' => 'Delete imageset', 'DELETE_IMAGESET_EXPLAIN' => 'Here you can remove the selected imageset from the database. Please note that there is no undo capability. It is recommended that you first export your set for possible future use.', 'DELETE_STYLE' => 'Delete style', - 'DELETE_STYLE_EXPLAIN' => 'Here you can remove the selected style. You cannot remove all the style elements from here. These must be deleted individually via their respective forms. Take care when deleting styles, there is no undo facility.', + 'DELETE_STYLE_EXPLAIN' => 'Here you can remove the selected style. Take care in deleting styles, there is no undo capability.', 'DELETE_TEMPLATE' => 'Delete template', 'DELETE_TEMPLATE_EXPLAIN' => 'Here you can remove the selected template set from the database. Please note that there is no undo capability. It is recommended that you first export your set for possible future use.', 'DELETE_THEME' => 'Delete theme', @@ -285,11 +285,14 @@ $lang = array_merge($lang, array( 'INSTALLED_TEMPLATE' => 'Installed templates', 'INSTALLED_THEME' => 'Installed themes', + 'KEEP_IMAGESET' => 'Keep "%s" imageset', + 'KEEP_TEMPLATE' => 'Keep "%s" template', + 'KEEP_THEME' => 'Keep "%s" theme', + 'LINE_SPACING' => 'Line spacing', 'LOCALISED_IMAGES' => 'Localised', 'LOCATION_DISABLED_EXPLAIN' => 'This setting is inherited and cannot be changed.', - 'NO_CLASS' => 'Cannot find class in stylesheet.', 'NO_IMAGESET' => 'Cannot find imageset on filesystem.', 'NO_IMAGE' => 'No image', @@ -322,6 +325,7 @@ $lang = array_merge($lang, array( 'REPLACE_TEMPLATE_EXPLAIN' => 'This template set will replace the one you are deleting in any styles that use it.', 'REPLACE_THEME' => 'Replace theme with', 'REPLACE_THEME_EXPLAIN' => 'This theme will replace the one you are deleting in any styles that use it.', + 'REPLACE_WITH_OPTION' => 'Replace with "%s"', 'REQUIRES_IMAGESET' => 'This style requires the %s imageset to be installed.', 'REQUIRES_TEMPLATE' => 'This style requires the %s template set to be installed.', 'REQUIRES_THEME' => 'This style requires the %s theme to be installed.', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index db60cbf227..731f674120 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -190,7 +190,7 @@ $lang = array_merge($lang, array( 'FORM_INVALID' => 'The submitted form was invalid. Try submitting again.', 'FORUM' => 'Forum', 'FORUMS' => 'Forums', - 'FORUMS_MARKED' => 'All forums have been marked read.', + 'FORUMS_MARKED' => 'The selected forums have been marked read.', 'FORUM_CAT' => 'Forum category', 'FORUM_INDEX' => 'Board index', 'FORUM_LINK' => 'Forum link', @@ -322,6 +322,7 @@ $lang = array_merge($lang, array( 'MARK' => 'Mark', 'MARK_ALL' => 'Mark all', 'MARK_FORUMS_READ' => 'Mark forums read', + 'MARK_SUBFORUMS_READ' => 'Mark subforums read', 'MB' => 'MB', 'MIB' => 'MiB', 'MCP' => 'Moderator Control Panel', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 91ecb10848..37147cc6a0 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -128,7 +128,7 @@ $lang = array_merge($lang, array( 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing <var>query_first</var>, %s (“%s”).', 'DB_ERR_SELECT' => 'Error while running <code>SELECT</code> query.', 'DB_HOST' => 'Database server hostname or DSN', - 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP.', + 'DB_HOST_EXPLAIN' => 'DSN stands for Data Source Name and is relevant only for ODBC installs. On PostgreSQL, use localhost to connect to the local server via UNIX domain socket and 127.0.0.1 to connect via TCP. For SQLite, enter the full path to your database file.', 'DB_NAME' => 'Database name', 'DB_PASSWORD' => 'Database password', 'DB_PORT' => 'Database server port', @@ -302,7 +302,7 @@ $lang = array_merge($lang, array( 'PHP_SETTINGS' => 'PHP version and settings', 'PHP_SETTINGS_EXPLAIN' => '<strong>Required</strong> - You must be running at least version 4.3.3 of PHP in order to install phpBB. If <var>safe mode</var> is displayed below your PHP installation is running in that mode. This will impose limitations on remote administration and similar features.', 'PHP_URL_FOPEN_SUPPORT' => 'PHP setting <var>allow_url_fopen</var> is enabled', - 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => '<strong>Optional</strong> - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it. ', + 'PHP_URL_FOPEN_SUPPORT_EXPLAIN' => '<strong>Optional</strong> - This setting is optional, however certain phpBB functions like off-site avatars will not work properly without it.', 'PHP_VERSION_REQD' => 'PHP version >= 4.3.3', 'POST_ID' => 'Post ID', 'PREFIX_FOUND' => 'A scan of your tables has shown a valid installation using <strong>%s</strong> as table prefix.', diff --git a/phpBB/memberlist.php b/phpBB/memberlist.php index 2fa2d11ee1..589877305f 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -1069,8 +1069,32 @@ switch ($mode) $sql_where .= ($msn) ? ' AND u.user_msnm ' . $db->sql_like_expression(str_replace('*', $db->any_char, $msn)) . ' ' : ''; $sql_where .= ($jabber) ? ' AND u.user_jabber ' . $db->sql_like_expression(str_replace('*', $db->any_char, $jabber)) . ' ' : ''; $sql_where .= (is_numeric($count) && isset($find_key_match[$count_select])) ? ' AND u.user_posts ' . $find_key_match[$count_select] . ' ' . (int) $count . ' ' : ''; - $sql_where .= (sizeof($joined) > 1 && isset($find_key_match[$joined_select])) ? " AND u.user_regdate " . $find_key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, intval($joined[1]), intval($joined[2]), intval($joined[0])) : ''; - $sql_where .= ($auth->acl_get('u_viewonline') && sizeof($active) > 1 && isset($find_key_match[$active_select])) ? " AND u.user_lastvisit " . $find_key_match[$active_select] . ' ' . gmmktime(0, 0, 0, $active[1], intval($active[2]), intval($active[0])) : ''; + + if (isset($find_key_match[$joined_select]) && sizeof($joined) == 3) + { + // Before PHP 5.1 an error value -1 can be returned instead of false. + // Theoretically gmmktime() can also legitimately return -1 as an actual timestamp. + // But since we do not pass the $second parameter to gmmktime(), + // an actual unix timestamp -1 cannot be returned in this case. + // Thus we can check whether it is -1 and treat -1 as an error. + $joined_time = gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]); + + if ($joined_time !== false && $joined_time !== -1) + { + $sql_where .= " AND u.user_regdate " . $find_key_match[$joined_select] . ' ' . $joined_time; + } + } + + if (isset($find_key_match[$active_select]) && sizeof($active) == 3 && $auth->acl_get('u_viewonline')) + { + $active_time = gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); + + if ($active_time !== false && $active_time !== -1) + { + $sql_where .= " AND u.user_lastvisit " . $find_key_match[$active_select] . ' ' . $active_time; + } + } + $sql_where .= ($search_group_id) ? " AND u.user_id = ug.user_id AND ug.group_id = $search_group_id AND ug.user_pending = 0 " : ''; if ($search_group_id) @@ -1692,7 +1716,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f 'U_EMAIL' => $email, 'U_WWW' => (!empty($data['user_website'])) ? $data['user_website'] : '', 'U_SHORT_WWW' => (!empty($data['user_website'])) ? ((strlen($data['user_website']) > 55) ? substr($data['user_website'], 0, 39) . ' ... ' . substr($data['user_website'], -10) : $data['user_website']) : '', - 'U_ICQ' => ($data['user_icq']) ? 'http://www.icq.com/people/webmsg.php?to=' . urlencode($data['user_icq']) : '', + 'U_ICQ' => ($data['user_icq']) ? 'http://www.icq.com/people/' . urlencode($data['user_icq']) . '/' : '', 'U_AIM' => ($data['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=aim&u=' . $user_id) : '', 'U_YIM' => ($data['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($data['user_yim']) . '&.src=pg' : '', 'U_MSN' => ($data['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=contact&action=msnm&u=' . $user_id) : '', diff --git a/phpBB/posting.php b/phpBB/posting.php index 7368026136..d05abc6a0e 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -1360,8 +1360,8 @@ $lock_post_checked = (isset($post_lock)) ? $post_lock : $post_data['post_edit_lo $notify_set = ($mode != 'edit' && $config['allow_topic_notify'] && $user->data['is_registered'] && !$post_data['notify_set']) ? $user->data['user_notify'] : $post_data['notify_set']; $notify_checked = (isset($notify)) ? $notify : (($mode == 'post') ? $user->data['user_notify'] : $notify_set); -// Page title & action URL, include session_id for security purpose -$s_action = append_sid("{$phpbb_root_path}posting.$phpEx", "mode=$mode&f=$forum_id", true, $user->session_id); +// Page title & action URL +$s_action = append_sid("{$phpbb_root_path}posting.$phpEx", "mode=$mode&f=$forum_id"); $s_action .= ($topic_id) ? "&t=$topic_id" : ''; $s_action .= ($post_id) ? "&p=$post_id" : ''; diff --git a/phpBB/styles/prosilver/template/attachment.html b/phpBB/styles/prosilver/template/attachment.html index cc5aacff2f..4c0a326f1e 100644 --- a/phpBB/styles/prosilver/template/attachment.html +++ b/phpBB/styles/prosilver/template/attachment.html @@ -70,12 +70,12 @@ <embed src="{_file.U_VIEW_LINK}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{_file.WIDTH}" height="{_file.HEIGHT}" play="true" loop="true" quality="high" allowscriptaccess="never" allownetworking="internal"></embed> </object> <!-- ELSEIF _file.S_QUICKTIME_FILE --> - <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="0" height="16"> + <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="320" height="285"> <param name="src" value="{_file.U_DOWNLOAD_LINK}" /> <param name="controller" value="true" /> <param name="autoplay" value="false" /> <param name="type" value="video/quicktime" /> - <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="0" height="16" type="video/quicktime" autoplay="false"></embed> + <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false"></embed> </object> <!-- ELSEIF _file.S_RM_FILE --> <object id="rmstream_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="200" height="50"> diff --git a/phpBB/styles/prosilver/template/login_body.html b/phpBB/styles/prosilver/template/login_body.html index 26e425a1d0..36c2eae349 100644 --- a/phpBB/styles/prosilver/template/login_body.html +++ b/phpBB/styles/prosilver/template/login_body.html @@ -2,7 +2,7 @@ <script type="text/javascript"> // <![CDATA[ - onload_functions.push('document.getElementById("{USERNAME_CREDENTIAL}").focus();'); + onload_functions.push('document.getElementById("<!-- IF S_ADMIN_AUTH -->{PASSWORD_CREDENTIAL}<!-- ELSE -->{USERNAME_CREDENTIAL}<!-- ENDIF -->").focus();'); // ]]> </script> diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index 04e24cd1f9..9d4997e576 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -72,8 +72,8 @@ <form method="post" id="mcp_approve" action="{U_APPROVE_ACTION}"> <p class="rules"> - <input class="button1" type="submit" value="{L_APPROVE}" name="action[approve]" /> - <input class="button2" type="submit" value="{L_DISAPPROVE}" name="action[disapprove]" /> + <input class="button2" type="submit" value="{L_DISAPPROVE}" name="action[disapprove]" /> + <input class="button1" type="submit" value="{L_APPROVE}" name="action[approve]" /> <input type="hidden" name="post_id_list[]" value="{POST_ID}" /> {S_FORM_TOKEN} </p> diff --git a/phpBB/styles/prosilver/template/memberlist_im.html b/phpBB/styles/prosilver/template/memberlist_im.html index acc7ec359b..49de3b2596 100644 --- a/phpBB/styles/prosilver/template/memberlist_im.html +++ b/phpBB/styles/prosilver/template/memberlist_im.html @@ -39,7 +39,7 @@ <dt> </dt> <dd><a href="{U_AIM_CONTACT}">{L_IM_ADD_CONTACT}</a></dd> <dd><a href="{U_AIM_MESSAGE}">{L_IM_SEND_MESSAGE}</a></dd> - <dd><a href="http://www.aim.com/download.adp">{L_IM_DOWNLOAD_APP}</a> | <a href="http://aimexpress.oscar.aol.com/aimexpress/launch.adp?Brand=AIM">{L_IM_AIM_EXPRESS}</a></dd> + <dd><a href="http://www.aim.com">{L_IM_DOWNLOAD_APP}</a> | <a href="http://www.aim.com/products/express">{L_IM_AIM_EXPRESS}</a></dd> </dl> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/memberlist_search.html b/phpBB/styles/prosilver/template/memberlist_search.html index b95185a6f2..9df648f644 100644 --- a/phpBB/styles/prosilver/template/memberlist_search.html +++ b/phpBB/styles/prosilver/template/memberlist_search.html @@ -37,7 +37,7 @@ function insert_single(user) } // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/forum_fn.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/forum_fn.js"></script> <!-- ENDIF --> <h2 class="solo">{L_FIND_USERNAME}</h2> diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 4da1308e14..1a044b0ca1 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -19,18 +19,7 @@ <span class="corners-bottom"><span></span></span></div> </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -//--> - - <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group + <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> <!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF --> <!-- IF U_ACP --><br /><strong><a href="{U_ACP}">{L_ACP}</a></strong><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/overall_header.html b/phpBB/styles/prosilver/template/overall_header.html index 44857dbc41..51fff0735a 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -8,7 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="" /> <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9" /> @@ -47,12 +46,9 @@ var onload_functions = new Array(); var onunload_functions = new Array(); - <!-- IF S_USER_PM_POPUP --> - if ({S_NEW_PM}) - { - var url = '{UA_POPUP_PM}'; - window.open(url.replace(/&/g, '&'), '_phpbbprivmsg', 'height=225,resizable=yes,scrollbars=yes, width=400'); - } + <!-- IF S_USER_PM_POPUP and S_NEW_PM --> + var url = '{UA_POPUP_PM}'; + window.open(url.replace(/&/g, '&'), '_phpbbprivmsg', 'height=225,resizable=yes,scrollbars=yes, width=400'); <!-- ENDIF --> /** @@ -85,8 +81,8 @@ // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/styleswitcher.js"></script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/forum_fn.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/styleswitcher.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/forum_fn.js"></script> <link href="{T_THEME_PATH}/print.css" rel="stylesheet" type="text/css" media="print" title="printonly" /> <link href="{T_STYLESHEET_LINK}" rel="stylesheet" type="text/css" media="screen, projection" /> diff --git a/phpBB/styles/prosilver/template/posting_buttons.html b/phpBB/styles/prosilver/template/posting_buttons.html index 5d21229611..19d55d1a4a 100644 --- a/phpBB/styles/prosilver/template/posting_buttons.html +++ b/phpBB/styles/prosilver/template/posting_buttons.html @@ -38,7 +38,7 @@ // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/editor.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/editor.js"></script> <!-- IF S_BBCODE_ALLOWED --> <div id="colour_palette" style="display: none;"> diff --git a/phpBB/styles/prosilver/template/posting_smilies.html b/phpBB/styles/prosilver/template/posting_smilies.html index fdd0d7ada1..86ac24aa53 100644 --- a/phpBB/styles/prosilver/template/posting_smilies.html +++ b/phpBB/styles/prosilver/template/posting_smilies.html @@ -6,7 +6,7 @@ var text_name = 'message'; // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/editor.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/editor.js"></script> <h2>{L_SMILIES}</h2> <div class="panel"> diff --git a/phpBB/styles/prosilver/template/simple_footer.html b/phpBB/styles/prosilver/template/simple_footer.html index e64e209368..daeb786fcb 100644 --- a/phpBB/styles/prosilver/template/simple_footer.html +++ b/phpBB/styles/prosilver/template/simple_footer.html @@ -1,16 +1,6 @@ </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - The phpBB Group : 2006 -//--> - - <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group + <div class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> <!-- IF DEBUG_OUTPUT --><br />{DEBUG_OUTPUT}<!-- ENDIF --> </div> diff --git a/phpBB/styles/prosilver/template/simple_header.html b/phpBB/styles/prosilver/template/simple_header.html index 0e2409586c..9cc8060762 100644 --- a/phpBB/styles/prosilver/template/simple_header.html +++ b/phpBB/styles/prosilver/template/simple_header.html @@ -8,7 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="" /> {META} @@ -47,8 +46,8 @@ // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/styleswitcher.js"></script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/forum_fn.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/styleswitcher.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/forum_fn.js"></script> <link href="{T_THEME_PATH}/print.css" rel="stylesheet" type="text/css" media="print" title="printonly" /> <link href="{T_STYLESHEET_LINK}" rel="stylesheet" type="text/css" media="screen, projection" /> diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html index 2171250621..bce31431cb 100644 --- a/phpBB/styles/prosilver/template/ucp_groups_manage.html +++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html @@ -118,7 +118,7 @@ </thead> <tbody> <!-- ELSEIF member.S_APPROVED --> - <!-- IF member.S_PENDING_SET --> + <!-- IF S_PENDING_SET --> </tbody> </table> <!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index 45ee6d1fae..c69bb82382 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -105,16 +105,6 @@ hr.sep { </table> <hr width="85%" /> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -//--> <table width="85%" cellspacing="3" cellpadding="0" border="0" align="center"> <tr> @@ -122,7 +112,7 @@ hr.sep { <td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td> </tr> <tr> - <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group<br />http://www.phpbb.com/</span></td> + <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © phpBB Group<br />http://www.phpbb.com/</span></td> </tr> </table> diff --git a/phpBB/styles/prosilver/template/viewforum_body.html b/phpBB/styles/prosilver/template/viewforum_body.html index 12073a39d2..f4e80fd625 100644 --- a/phpBB/styles/prosilver/template/viewforum_body.html +++ b/phpBB/styles/prosilver/template/viewforum_body.html @@ -28,7 +28,7 @@ <!-- IF S_HAS_SUBFORUM --> <!-- IF not S_IS_BOT and U_MARK_FORUMS --> <ul class="linklist"> - <li class="rightside"><a href="{U_MARK_FORUMS}">{L_MARK_FORUMS_READ}</a></li> + <li class="rightside"><a href="{U_MARK_FORUMS}">{L_MARK_SUBFORUMS_READ}</a></li> </ul> <!-- ENDIF --> <!-- INCLUDE forumlist_body.html --> diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 03102dd351..541c48a53d 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -8,7 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="" /> <meta name="robots" content="noindex" /> @@ -43,19 +42,9 @@ <!-- END postrow --> </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -//--> <div id="page-footer"> <div class="page-number">{S_TIMEZONE}<br />{PAGE_NUMBER}</div> - <div class="copyright">Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group<br />http://www.phpbb.com/</div> + <div class="copyright">Powered by phpBB © phpBB Group<br />http://www.phpbb.com/</div> </div> </div> diff --git a/phpBB/styles/prosilver/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 5d74ff9d8f..f7747ba73c 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -171,7 +171,7 @@ dl.details dd { border-color: #4692BF; } -.pagination span a, .pagination span a:link, .pagination span a:visited, .pagination span a:active { +.pagination span a, .pagination span a:link, .pagination span a:visited { color: #5C758C; background-color: #ECEDEE; border-color: #B4BAC0; @@ -183,6 +183,12 @@ dl.details dd { color: #FFF; } +.pagination span a:active { + color: #5C758C; + background-color: #ECEDEE; + border-color: #B4BAC0; +} + /* Pagination in viewforum for multipage topics */ .row .pagination { background-image: url("{T_THEME_PATH}/images/icon_pages.gif"); @@ -304,12 +310,12 @@ a.topictitle:active { color: #0D4473; } -.signature a, .signature a:visited, .signature a:active, .signature a:hover { +.signature a, .signature a:visited, .signature a:hover, .signature a:active { background-color: transparent; } /* Profile links */ -.postprofile a:link, .postprofile a:active, .postprofile a:visited, .postprofile dt.author a { +.postprofile a:link, .postprofile a:visited, .postprofile dt.author a { color: #105289; } @@ -317,6 +323,10 @@ a.topictitle:active { color: #D31141; } +.postprofile a:active { + color: #105289; +} + /* Profile searchresults */ .search .postprofile a { color: #105289; @@ -642,7 +652,7 @@ fieldset.polls dd div { } .online { - background-image: url("{T_IMAGESET_LANG_PATH}/icon_user_online.gif"); + background-image: url("{IMG_ICON_USER_ONLINE_SRC}"); } /* diff --git a/phpBB/styles/prosilver/theme/links.css b/phpBB/styles/prosilver/theme/links.css index ea9ca8f4b1..a406114054 100644 --- a/phpBB/styles/prosilver/theme/links.css +++ b/phpBB/styles/prosilver/theme/links.css @@ -103,14 +103,14 @@ a.topictitle:active { color: #404040; } -.signature a, .signature a:visited, .signature a:active, .signature a:hover { +.signature a, .signature a:visited, .signature a:hover, .signature a:active { border: none; text-decoration: underline; background-color: transparent; } /* Profile links */ -.postprofile a:link, .postprofile a:active, .postprofile a:visited, .postprofile dt.author a { +.postprofile a:link, .postprofile a:visited, .postprofile dt.author a { font-weight: bold; color: #898989; text-decoration: none; @@ -121,6 +121,14 @@ a.topictitle:active { color: #d3d3d3; } +/* CSS spec requires a:link, a:visited, a:hover and a:active rules to be specified in this order. */ +/* See http://www.phpbb.com/bugs/phpbb3/59685 */ +.postprofile a:active { + font-weight: bold; + color: #898989; + text-decoration: none; +} + /* Profile searchresults */ .search .postprofile a { diff --git a/phpBB/styles/prosilver/theme/print.css b/phpBB/styles/prosilver/theme/print.css index 68600b030b..2cfcd4da20 100644 --- a/phpBB/styles/prosilver/theme/print.css +++ b/phpBB/styles/prosilver/theme/print.css @@ -60,7 +60,7 @@ h3 { font-size: 14pt; margin-top: 1em; } } /* CSS2 Print tip from: http://www.alistapart.com/articles/goingtoprint/ */ -.postbody a:link, .postbody a:visited, .postbody a:active, .postbody a:hover { +.postbody a:link, .postbody a:visited, .postbody a:hover, .postbody a:active { text-decoration: underline; padding: 0.1em 0.2em; margin: -0.1em -0.2em; @@ -141,4 +141,4 @@ div.spacer { clear: both; } /* Accessibility tweaks: Mozilla.org */ .skip_link { display: none; } -dl.codebox dt { display: none; }
\ No newline at end of file +dl.codebox dt { display: none; } diff --git a/phpBB/styles/prosilver/theme/tweaks.css b/phpBB/styles/prosilver/theme/tweaks.css index 782e682b9d..30fe5fb986 100644 --- a/phpBB/styles/prosilver/theme/tweaks.css +++ b/phpBB/styles/prosilver/theme/tweaks.css @@ -90,3 +90,12 @@ dl.icon { * html .forumbg table.table1 { margin: 0 -2px 0px -1px; } + +/* Headerbar height fix for IE7 and below */ +* html #site-description p { + margin-bottom: 1.0em; +} + +*:first-child+html #site-description p { + margin-bottom: 1.0em; +}
\ No newline at end of file diff --git a/phpBB/styles/subsilver2/template/attachment.html b/phpBB/styles/subsilver2/template/attachment.html index 833bd4d55f..b5b547b2e6 100644 --- a/phpBB/styles/subsilver2/template/attachment.html +++ b/phpBB/styles/subsilver2/template/attachment.html @@ -67,12 +67,12 @@ <embed src="{_file.U_VIEW_LINK}" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash" width="{_file.WIDTH}" height="{_file.HEIGHT}" play="true" loop="true" quality="high" allowscriptaccess="never" allownetworking="internal"></embed> </object> <!-- ELSEIF _file.S_QUICKTIME_FILE --> - <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="0" height="16"> + <object id="qtstream_{_file.ATTACH_ID}" classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" width="320" height="285"> <param name="src" value="{_file.U_DOWNLOAD_LINK}"> <param name="controller" value="true"> <param name="autoplay" value="false" /> <param name="type" value="video/quicktime"> - <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="0" height="16" type="video/quicktime" autoplay="false"> + <embed name="qtstream_{_file.ATTACH_ID}" src="{_file.U_DOWNLOAD_LINK}" pluginspage="http://www.apple.com/quicktime/download/" enablejavascript="true" controller="true" width="320" height="285" type="video/quicktime" autoplay="false"> </object> <!-- ELSEIF _file.S_RM_FILE --> <object id="rmstream_{_file.ATTACH_ID}" classid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="200" height="50"> diff --git a/phpBB/styles/subsilver2/template/login_body.html b/phpBB/styles/subsilver2/template/login_body.html index 90bbf8c139..262341e0c0 100644 --- a/phpBB/styles/subsilver2/template/login_body.html +++ b/phpBB/styles/subsilver2/template/login_body.html @@ -92,7 +92,7 @@ // <![CDATA[ (function() { - var elements = document.getElementsByName("{USERNAME_CREDENTIAL}"); + var elements = document.getElementsByName("<!-- IF S_ADMIN_AUTH -->{PASSWORD_CREDENTIAL}<!-- ELSE -->{USERNAME_CREDENTIAL}<!-- ENDIF -->"); for (var i = 0; i < elements.length; ++i) { if (elements[i].tagName.toLowerCase() == 'input') diff --git a/phpBB/styles/subsilver2/template/memberlist_im.html b/phpBB/styles/subsilver2/template/memberlist_im.html index e8d86128c7..0a92fd2ba0 100644 --- a/phpBB/styles/subsilver2/template/memberlist_im.html +++ b/phpBB/styles/subsilver2/template/memberlist_im.html @@ -19,7 +19,7 @@ <!-- IF S_SEND_AIM --> <tr> - <td class="row1" colspan="2" align="center"><br /><a class="gen" href="{U_AIM_CONTACT}">{L_IM_ADD_CONTACT}</a><br /><a class="gen" href="{U_AIM_MESSAGE}">{L_IM_SEND_MESSAGE}</a><br /><br /><a class="gensmall" href="http://www.aim.com/download.adp">{L_IM_DOWNLOAD_APP}</a> | <a class="gensmall" href="http://aimexpress.oscar.aol.com/aimexpress/launch.adp?Brand=AIM">{L_IM_AIM_EXPRESS}</a> </td> + <td class="row1" colspan="2" align="center"><br /><a class="gen" href="{U_AIM_CONTACT}">{L_IM_ADD_CONTACT}</a><br /><a class="gen" href="{U_AIM_MESSAGE}">{L_IM_SEND_MESSAGE}</a><br /><br /><a class="gensmall" href="http://www.aim.com">{L_IM_DOWNLOAD_APP}</a> | <a class="gensmall" href="http://www.aim.com/products/express">{L_IM_AIM_EXPRESS}</a> </td> </tr> <tr> <td class="cat" colspan="2" align="center"> </td> diff --git a/phpBB/styles/subsilver2/template/overall_footer.html b/phpBB/styles/subsilver2/template/overall_footer.html index 64201ff2b9..b53fff9f7f 100644 --- a/phpBB/styles/subsilver2/template/overall_footer.html +++ b/phpBB/styles/subsilver2/template/overall_footer.html @@ -1,20 +1,9 @@ <!-- IF not S_IS_BOT -->{RUN_CRON_TASK}<!-- ENDIF --> </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -//--> - <div id="wrapfooter"> <!-- IF U_ACP --><span class="gensmall">[ <a href="{U_ACP}">{L_ACP}</a> ]</span><br /><br /><!-- ENDIF --> - <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group + <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group <!-- IF TRANSLATION_INFO --><br />{TRANSLATION_INFO}<!-- ENDIF --> <!-- IF DEBUG_OUTPUT --><br /><bdo dir="ltr">[ {DEBUG_OUTPUT} ]</bdo><!-- ENDIF --></span> </div> diff --git a/phpBB/styles/subsilver2/template/overall_header.html b/phpBB/styles/subsilver2/template/overall_header.html index 874beb8e2b..be4c7b5b4c 100644 --- a/phpBB/styles/subsilver2/template/overall_header.html +++ b/phpBB/styles/subsilver2/template/overall_header.html @@ -8,7 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="" /> <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7; IE=EmulateIE9" /> @@ -29,11 +28,8 @@ <script type="text/javascript"> // <![CDATA[ -<!-- IF S_USER_PM_POPUP --> - if ({S_NEW_PM}) - { - popup('{UA_POPUP_PM}', 400, 225, '_phpbbprivmsg'); - } +<!-- IF S_USER_PM_POPUP and S_NEW_PM --> + popup('{UA_POPUP_PM}', 400, 225, '_phpbbprivmsg'); <!-- ENDIF --> function popup(url, width, height, name) diff --git a/phpBB/styles/subsilver2/template/posting_buttons.html b/phpBB/styles/subsilver2/template/posting_buttons.html index 621fa87fd4..92b4bd3e39 100644 --- a/phpBB/styles/subsilver2/template/posting_buttons.html +++ b/phpBB/styles/subsilver2/template/posting_buttons.html @@ -33,7 +33,7 @@ // ]]> </script> - <script type="text/javascript" src="{T_TEMPLATE_PATH}/editor.js"></script> + <script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/editor.js"></script> <!-- IF S_BBCODE_ALLOWED --> <input type="button" class="btnbbcode" accesskey="b" name="addbbcode0" value=" B " style="font-weight:bold; width: 30px;" onclick="bbstyle(0)" onmouseover="helpline('b')" onmouseout="helpline('tip')" /> diff --git a/phpBB/styles/subsilver2/template/posting_smilies.html b/phpBB/styles/subsilver2/template/posting_smilies.html index 2586530e55..fcab578bd9 100644 --- a/phpBB/styles/subsilver2/template/posting_smilies.html +++ b/phpBB/styles/subsilver2/template/posting_smilies.html @@ -6,7 +6,7 @@ var text_name = 'message'; // ]]> </script> -<script type="text/javascript" src="{T_TEMPLATE_PATH}/editor.js"></script> +<script type="text/javascript" src="{T_SUPER_TEMPLATE_PATH}/editor.js"></script> <table width="100%" cellspacing="1" cellpadding="4" border="0"> <tr> diff --git a/phpBB/styles/subsilver2/template/simple_footer.html b/phpBB/styles/subsilver2/template/simple_footer.html index c8b69dd5ad..1bd146b599 100644 --- a/phpBB/styles/subsilver2/template/simple_footer.html +++ b/phpBB/styles/subsilver2/template/simple_footer.html @@ -1,19 +1,8 @@ </div> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line, with - "phpBB" linked to www.phpbb.com. If you refuse to include even this then support on our - forums may be affected. - - The phpBB Group : 2006 -//--> - <div id="wrapfooter"> - <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © 2000, 2002, 2005, 2007 phpBB Group</span> + <span class="copyright">Powered by <a href="http://www.phpbb.com/">phpBB</a> © phpBB Group</span> </div> </body> diff --git a/phpBB/styles/subsilver2/template/simple_header.html b/phpBB/styles/subsilver2/template/simple_header.html index bcef9a7059..b0dc908bc6 100644 --- a/phpBB/styles/subsilver2/template/simple_header.html +++ b/phpBB/styles/subsilver2/template/simple_header.html @@ -8,7 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="copyright" content="2000, 2002, 2005, 2007 phpBB Group" /> <meta name="keywords" content="" /> <meta name="description" content="" /> {META} diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html index f1c59df1c8..eff4a2a7dd 100644 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html @@ -107,15 +107,6 @@ hr.sep { </table> <hr width="85%" /> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line. If you - refuse to include even this then support on our forums may be affected. - - The phpBB Group : 2006 -// --> <table width="85%" cellspacing="3" cellpadding="0" border="0" align="center"> <tr> @@ -123,7 +114,7 @@ hr.sep { <td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td> </tr> <tr> - <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group<br />http://www.phpbb.com/</span></td> + <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © phpBB Group<br />http://www.phpbb.com/</span></td> </tr> </table> diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html index cfd78b6fc7..38ec10fad8 100644 --- a/phpBB/styles/subsilver2/template/viewtopic_print.html +++ b/phpBB/styles/subsilver2/template/viewtopic_print.html @@ -121,15 +121,6 @@ hr.sep { <!-- END postrow --> <hr width="85%" /> -<!-- - We request you retain the full copyright notice below including the link to www.phpbb.com. - This not only gives respect to the large amount of time given freely by the developers - but also helps build interest, traffic and use of phpBB3. If you (honestly) cannot retain - the full copyright we ask you at least leave in place the "Powered by phpBB" line. If you - refuse to include even this then support on our forums may be affected. - - The phpBB Group : 2006 -// --> <table width="85%" cellspacing="3" cellpadding="0" border="0" align="center"> <tr> @@ -137,7 +128,7 @@ hr.sep { <td align="{S_CONTENT_FLOW_END}"><span class="gensmall">{S_TIMEZONE}</span></td> </tr> <tr> - <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group<br />http://www.phpbb.com/</span></td> + <td colspan="2" align="center"><span class="gensmall">Powered by phpBB © phpBB Group<br />http://www.phpbb.com/</span></td> </tr> </table> diff --git a/phpBB/styles/subsilver2/theme/stylesheet.css b/phpBB/styles/subsilver2/theme/stylesheet.css index 726efdca0a..c2b6718d87 100644 --- a/phpBB/styles/subsilver2/theme/stylesheet.css +++ b/phpBB/styles/subsilver2/theme/stylesheet.css @@ -210,13 +210,13 @@ p.topicdetails { margin: 1px 0; } -.postreported, .postreported a:visited, .postreported a:hover, .postreported a:link, .postreported a:active { +.postreported, .postreported a:link, .postreported a:visited, .postreported a:hover, .postreported a:active { margin: 1px 0; color: red; font-weight:bold; } -.postapprove, .postapprove a:visited, .postapprove a:hover, .postapprove a:link, .postapprove a:active { +.postapprove, .postapprove a:link, .postapprove a:visited, .postapprove a:hover, .postapprove a:active { color: green; font-weight:bold; } @@ -386,12 +386,13 @@ hr { unicode-bidi: embed; } +/* CSS spec requires a:link, a:visited, a:hover and a:active rules to be specified in this order. */ +/* See http://www.phpbb.com/bugs/phpbb3/59685 */ a:link { color: #006597; text-decoration: none; } -a:active, a:visited { color: #005784; text-decoration: none; @@ -402,6 +403,11 @@ a:hover { text-decoration: underline; } +a:active { + color: #005784; + text-decoration: none; +} + a.forumlink { color: #069; font-weight: bold; @@ -667,4 +673,4 @@ pre { .username-coloured { font-weight: bold; -}
\ No newline at end of file +} diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 498088c5c8..53da7f539f 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -1157,7 +1157,7 @@ while ($row = $db->sql_fetchrow($result)) if (!empty($row['user_icq'])) { - $user_cache[$poster_id]['icq'] = 'http://www.icq.com/people/webmsg.php?to=' . $row['user_icq']; + $user_cache[$poster_id]['icq'] = 'http://www.icq.com/people/' . urlencode($row['user_icq']) . '/'; $user_cache[$poster_id]['icq_status_img'] = '<img src="http://web.icq.com/whitepages/online?icq=' . $row['user_icq'] . '&img=5" width="18" height="18" alt="" />'; } else @@ -1547,6 +1547,7 @@ for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) 'U_WARN' => ($auth->acl_get('m_warn') && $poster_id != $user->data['user_id'] && $poster_id != ANONYMOUS) ? append_sid("{$phpbb_root_path}mcp.$phpEx", 'i=warn&mode=warn_post&f=' . $forum_id . '&p=' . $row['post_id'], true, $user->session_id) : '', 'POST_ID' => $row['post_id'], + 'POST_NUMBER' => $i + $start + 1, 'POSTER_ID' => $poster_id, 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, diff --git a/phpunit.xml.all b/phpunit.xml.all new file mode 100644 index 0000000000..1be2830729 --- /dev/null +++ b/phpunit.xml.all @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit backupGlobals="true" + backupStaticAttributes="true" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + syntaxCheck="false" + bootstrap="tests/bootstrap.php" +> + <testsuites> + <testsuite name="phpBB Test Suite"> + <directory suffix="_test.php">./tests/</directory> + </testsuite> + </testsuites> + + <filter> + <blacklist> + <directory>./tests/</directory> + </blacklist> + </filter> +</phpunit> diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000000..de8134da8e --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit backupGlobals="true" + backupStaticAttributes="true" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + processIsolation="false" + stopOnFailure="false" + syntaxCheck="false" + bootstrap="tests/bootstrap.php" +> + <testsuites> + <testsuite name="phpBB Test Suite"> + <directory suffix="_test.php">./tests/</directory> + </testsuite> + </testsuites> + + <groups> + <exclude> + <group>slow</group> + </exclude> + </groups> + + <filter> + <blacklist> + <directory>./tests/</directory> + </blacklist> + </filter> +</phpunit> diff --git a/tests/RUNNING_TESTS.txt b/tests/RUNNING_TESTS.txt index 74a0635c1a..59197acc0f 100644 --- a/tests/RUNNING_TESTS.txt +++ b/tests/RUNNING_TESTS.txt @@ -7,7 +7,7 @@ Prerequisites PHPUnit ------- -phpBB unit tests use PHPUnit framework. Version 3.3 or better is required +phpBB unit tests use PHPUnit framework. Version 3.5 or better is required to run the tests. PHPUnit prefers to be installed via PEAR; refer to http://www.phpunit.de/ for more information. @@ -41,14 +41,23 @@ will run phpunit with the same parameters as in the shown test_config.php file: $ PHPBB_TEST_DBMS='mysqli' PHPBB_TEST_DBHOST='localhost' \ PHPBB_TEST_DBNAME='database' PHPBB_TEST_DBUSER='user' \ - PHPBB_TEST_DBPASSWD='password' phpunit all_tests.php + PHPBB_TEST_DBPASSWD='password' phpunit Running ======= -Once the prerequisites are installed, run the tests from tests directory: +Once the prerequisites are installed, run the tests from the project root directory (above phpBB): - $ phpunit all_tests.php + $ phpunit + +Slow tests +-------------- +Certain tests, such as the UTF-8 normalizer or the DNS tests tend to be slow. +Thus these tests are in the `slow` group, which is excluded by default. You can +enable slow tests by copying the phpunit.xml.all file to phpunit.xml. If you only +want the slow tests, run: + + $ phpunit --group slow More Information ================ diff --git a/tests/all_tests.php b/tests/all_tests.php deleted file mode 100644 index d1d711c4d7..0000000000 --- a/tests/all_tests.php +++ /dev/null @@ -1,69 +0,0 @@ -<?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'; -require_once 'regex/all_tests.php'; -require_once 'network/all_tests.php'; -require_once 'random/all_tests.php'; - -// exclude the test directory from code coverage reports -if (version_compare(PHPUnit_Runner_Version::id(), '3.5.0') >= 0) -{ - PHP_CodeCoverage_Filter::getInstance()->addDirectoryToBlacklist('./'); -} -else -{ - 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()); - $suite->addTest(phpbb_regex_all_tests::suite()); - $suite->addTest(phpbb_network_all_tests::suite()); - $suite->addTest(phpbb_random_all_tests::suite()); - - return $suite; - } -} - -if (PHPUnit_MAIN_METHOD == 'phpbb_all_tests::main') -{ - phpbb_all_tests::main(); -} - diff --git a/tests/test_framework/framework.php b/tests/bootstrap.php index 3a11cc6df9..6f3c93a374 100644 --- a/tests/test_framework/framework.php +++ b/tests/bootstrap.php @@ -8,9 +8,15 @@ */ define('IN_PHPBB', true); -$phpbb_root_path = '../phpBB/'; +$phpbb_root_path = 'phpBB/'; $phpEx = 'php'; -$table_prefix = ''; +$table_prefix = 'phpbb_'; + +if (!defined('E_DEPRECATED')) +{ + define('E_DEPRECATED', 8192); +} +error_reporting(E_ALL & ~E_DEPRECATED); // If we are on PHP >= 6.0.0 we do not need some code if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) @@ -25,19 +31,7 @@ else 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'); -} - -if (version_compare(PHPUnit_Runner_Version::id(), '3.5.0', '<')) -{ - 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'; +require_once 'test_framework/phpbb_database_test_connection_manager.php'; diff --git a/tests/dbal/all_tests.php b/tests/dbal/all_tests.php deleted file mode 100644 index cfa8176246..0000000000 --- a/tests/dbal/all_tests.php +++ /dev/null @@ -1,42 +0,0 @@ -<?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/select.php'; -require_once 'dbal/write.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_select_test'); - $suite->addTestSuite('phpbb_dbal_write_test'); - - return $suite; - } -} - -if (PHPUnit_MAIN_METHOD == 'phpbb_dbal_all_tests::main') -{ - phpbb_dbal_all_tests::main(); -} diff --git a/tests/dbal/select.php b/tests/dbal/select_test.php index 70f27549d2..533416f14b 100644 --- a/tests/dbal/select.php +++ b/tests/dbal/select_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_dbal_select_test extends phpbb_database_test_case { diff --git a/tests/dbal/write.php b/tests/dbal/write_test.php index 01deacda69..4709d45fa5 100644 --- a/tests/dbal/write.php +++ b/tests/dbal/write_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_dbal_write_test extends phpbb_database_test_case { diff --git a/tests/mock/cache.php b/tests/mock/cache.php new file mode 100644 index 0000000000..11e525ff79 --- /dev/null +++ b/tests/mock/cache.php @@ -0,0 +1,73 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +class phpbb_mock_cache +{ + public function __construct($data = array()) + { + $this->data = $data; + + if (!isset($this->data['_bots'])) + { + $this->data['_bots'] = array(); + } + } + + public function get($var_name) + { + if (isset($this->data[$var_name])) + { + return $this->data[$var_name]; + } + + return false; + } + + public function put($var_name, $var, $ttl = 0) + { + $this->data[$var_name] = $var; + } + + /** + * Obtain active bots + */ + public function obtain_bots() + { + return $this->data['_bots']; + } + + public function set_bots($bots) + { + $this->data['_bots'] = $bots; + } + + public function checkVar(PHPUnit_Framework_Assert $test, $var_name, $data) + { + $test->assertTrue(isset($this->data[$var_name])); + $test->assertEquals($data, $this->data[$var_name]); + } + + public function check(PHPUnit_Framework_Assert $test, $data, $ignore_db_info = true) + { + $cache_data = $this->data; + + if ($ignore_db_info) + { + unset($cache_data['mssqlodbc_version']); + unset($cache_data['mssql_version']); + unset($cache_data['mysql_version']); + unset($cache_data['mysqli_version']); + unset($cache_data['pgsql_version']); + unset($cache_data['sqlite_version']); + } + + $test->assertEquals($data, $cache_data); + } +} + diff --git a/tests/mock/session_testable.php b/tests/mock/session_testable.php new file mode 100644 index 0000000000..47089cb94b --- /dev/null +++ b/tests/mock/session_testable.php @@ -0,0 +1,63 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; + +/** +* Extends the session class to overwrite the setting of cookies. +* +* The session class directly writes cookie headers making it impossible to +* test it without warnings about sent headers. This class only stores cookie +* data for later verification. +*/ +class phpbb_mock_session_testable extends session +{ + private $_cookies = array(); + + public function set_cookie($name, $data, $time) + { + $this->_cookies[$name] = array($data, $time); + } + + /** + * Checks if the cookies were set correctly. + * + * @param PHPUnit_Framework_Assert test The test from which this is called + * @param array(string => mixed) cookies The cookie data to check against. + * The keys are cookie names, the values can either be null to + * check only the existance of the cookie, or an array(d, t), + * where d is the cookie data to check, or null to skip the + * check and t is the cookie time to check, or null to skip. + */ + public function check_cookies(PHPUnit_Framework_Assert $test, $cookies) + { + $test->assertEquals(array_keys($cookies), array_keys($this->_cookies), 'Incorrect cookies were set'); + + foreach ($cookies as $name => $cookie) + { + if (!is_null($cookie)) + { + $data = $cookie[0]; + $time = $cookie[1]; + + if (!is_null($data)) + { + $test->assertEquals($data, $this->_cookies[$name][0], "Cookie $name contains incorrect data"); + } + + if (!is_null($time)) + { + $test->assertEquals($time, $this->_cookies[$name][1], "Cookie $name expires at the wrong time"); + } + } + } + } +} + diff --git a/tests/network/all_tests.php b/tests/network/all_tests.php deleted file mode 100644 index b500647f81..0000000000 --- a/tests/network/all_tests.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** -* -* @package testing -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -if (!defined('PHPUnit_MAIN_METHOD')) -{ - define('PHPUnit_MAIN_METHOD', 'phpbb_network_all_tests::main'); -} - -require_once 'test_framework/framework.php'; -require_once 'PHPUnit/TextUI/TestRunner.php'; - -require_once 'network/checkdnsrr.php'; - -class phpbb_network_all_tests -{ - public static function main() - { - PHPUnit_TextUI_TestRunner::run(self::suite()); - } - - public static function suite() - { - $suite = new PHPUnit_Framework_TestSuite('phpBB Network Functions'); - - $suite->addTestSuite('phpbb_network_checkdnsrr_test'); - - return $suite; - } -} - -if (PHPUnit_MAIN_METHOD == 'phpbb_network_all_tests::main') -{ - phpbb_network_all_tests::main(); -} diff --git a/tests/network/checkdnsrr.php b/tests/network/checkdnsrr_test.php index 57fe2761cc..5a756dcef8 100644 --- a/tests/network/checkdnsrr.php +++ b/tests/network/checkdnsrr_test.php @@ -7,9 +7,11 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +/** +* @group slow +*/ class phpbb_network_checkdnsrr_test extends phpbb_test_case { public function data_provider() diff --git a/tests/random/all_tests.php b/tests/random/all_tests.php deleted file mode 100644 index c6ffe78024..0000000000 --- a/tests/random/all_tests.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php -/** -* -* @package testing -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -if (!defined('PHPUnit_MAIN_METHOD')) -{ - define('PHPUnit_MAIN_METHOD', 'phpbb_random_all_tests::main'); -} - -require_once 'test_framework/framework.php'; -require_once 'PHPUnit/TextUI/TestRunner.php'; - -require_once 'random/gen_rand_string.php'; - -class phpbb_random_all_tests -{ - public static function main() - { - PHPUnit_TextUI_TestRunner::run(self::suite()); - } - - public static function suite() - { - $suite = new PHPUnit_Framework_TestSuite('phpBB Random Functions'); - - $suite->addTestSuite('phpbb_random_gen_rand_string_test'); - - return $suite; - } -} - -if (PHPUnit_MAIN_METHOD == 'phpbb_random_all_tests::main') -{ - phpbb_random_all_tests::main(); -} diff --git a/tests/random/gen_rand_string.php b/tests/random/gen_rand_string_test.php index cd58d14ed3..115c55e4e2 100644 --- a/tests/random/gen_rand_string.php +++ b/tests/random/gen_rand_string_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_random_gen_rand_string_test extends phpbb_test_case { diff --git a/tests/regex/all_tests.php b/tests/regex/all_tests.php deleted file mode 100644 index 316a9d4a58..0000000000 --- a/tests/regex/all_tests.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** -* -* @package testing -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -if (!defined('PHPUnit_MAIN_METHOD')) -{ - define('PHPUnit_MAIN_METHOD', 'phpbb_regex_all_tests::main'); -} - -require_once 'test_framework/framework.php'; -require_once 'PHPUnit/TextUI/TestRunner.php'; - -require_once 'regex/email.php'; -require_once 'regex/ipv4.php'; -require_once 'regex/ipv6.php'; -require_once 'regex/url.php'; - -class phpbb_regex_all_tests -{ - public static function main() - { - PHPUnit_TextUI_TestRunner::run(self::suite()); - } - - public static function suite() - { - $suite = new PHPUnit_Framework_TestSuite('phpBB Regular Expressions'); - - $suite->addTestSuite('phpbb_regex_email_test'); - $suite->addTestSuite('phpbb_regex_ipv4_test'); - $suite->addTestSuite('phpbb_regex_ipv6_test'); - $suite->addTestSuite('phpbb_regex_url_test'); - - return $suite; - } -} - -if (PHPUnit_MAIN_METHOD == 'phpbb_regex_all_tests::main') -{ - phpbb_regex_all_tests::main(); -} diff --git a/tests/regex/censor_test.php b/tests/regex/censor_test.php new file mode 100644 index 0000000000..fa9104e71d --- /dev/null +++ b/tests/regex/censor_test.php @@ -0,0 +1,50 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_regex_censor_test extends phpbb_test_case +{ + public function censor_test_data() + { + return array( + array('bad*word', 'bad word'), + array('bad***word', 'bad word'), + array('bad**word', 'bad word'), + array('*bad*word*', 'bad word'), + array('b*d', 'bad'), + array('*bad*', 'bad'), + array('*b*d*', 'bad'), + array('*b*d*', 'b d'), + array('b*d*word', 'bad word'), + array('**b**d**word**', 'bad word'), + array('**b**d**word**', 'the bad word catched'), + ); + } + + /** + * @dataProvider censor_test_data + */ + public function test_censor_unicode($pattern, $subject) + { + $regex = get_censor_preg_expression($pattern, true); + + $this->assertRegExp($regex, $subject); + } + + /** + * @dataProvider censor_test_data + */ + public function test_censor_no_unicode($pattern, $subject) + { + $regex = get_censor_preg_expression($pattern, false); + + $this->assertRegExp($regex, $subject); + } +}
\ No newline at end of file diff --git a/tests/regex/email.php b/tests/regex/email_test.php index 8658b8af36..0695b801d5 100644 --- a/tests/regex/email.php +++ b/tests/regex/email_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_regex_email_test extends phpbb_test_case { diff --git a/tests/regex/ipv4.php b/tests/regex/ipv4_test.php index 9d131ad0ca..9829547508 100644 --- a/tests/regex/ipv4.php +++ b/tests/regex/ipv4_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_regex_ipv4_test extends phpbb_test_case { diff --git a/tests/regex/ipv6.php b/tests/regex/ipv6_test.php index 3d7a72e492..1b2018403c 100644 --- a/tests/regex/ipv6.php +++ b/tests/regex/ipv6_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_regex_ipv6_test extends phpbb_test_case { diff --git a/tests/regex/password_complexity_test.php b/tests/regex/password_complexity_test.php new file mode 100644 index 0000000000..21e8d12a0a --- /dev/null +++ b/tests/regex/password_complexity_test.php @@ -0,0 +1,81 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_user.php'; + +class phpbb_password_complexity_test extends phpbb_test_case +{ + public function password_complexity_test_data_positive() + { + return array( + array('12345', 'PASS_TYPE_ANY'), + array('qwerty', 'PASS_TYPE_ANY'), + array('QWERTY', 'PASS_TYPE_ANY'), + array('QwerTY', 'PASS_TYPE_ANY'), + array('q$erty', 'PASS_TYPE_ANY'), + array('qW$rty', 'PASS_TYPE_ANY'), + + array('QwerTY', 'PASS_TYPE_CASE'), + array('QwerTY123', 'PASS_TYPE_ALPHA'), + array('QwerTY123$&', 'PASS_TYPE_SYMBOL'), + + array('', 'PASS_TYPE_ANY'), + ); + } + + public function password_complexity_test_data_negative() + { + return array( + array('qwerty', 'PASS_TYPE_CASE'), + array('QWERTY', 'PASS_TYPE_CASE'), + array('123456', 'PASS_TYPE_CASE'), + array('#$&', 'PASS_TYPE_CASE'), + array('QTY123$', 'PASS_TYPE_CASE'), + + array('qwerty', 'PASS_TYPE_ALPHA'), + array('QWERTY', 'PASS_TYPE_ALPHA'), + array('123456', 'PASS_TYPE_ALPHA'), + array('QwertY', 'PASS_TYPE_ALPHA'), + array('qwerty123', 'PASS_TYPE_ALPHA'), + array('QWERTY123', 'PASS_TYPE_ALPHA'), + array('#$&', 'PASS_TYPE_ALPHA'), + array('QTY123$', 'PASS_TYPE_ALPHA'), + + array('qwerty', 'PASS_TYPE_SYMBOL'), + array('QWERTY', 'PASS_TYPE_SYMBOL'), + array('123456', 'PASS_TYPE_SYMBOL'), + array('QwertY', 'PASS_TYPE_SYMBOL'), + array('qwerty123', 'PASS_TYPE_SYMBOL'), + array('QWERTY123', 'PASS_TYPE_SYMBOL'), + array('#$&', 'PASS_TYPE_SYMBOL'), + array('qwerty123$', 'PASS_TYPE_SYMBOL'), + array('QWERTY123$', 'PASS_TYPE_SYMBOL'), + ); + } + + /** + * @dataProvider password_complexity_test_data_positive + */ + public function test_password_complexity_positive($password, $mode) + { + global $config; + $config['pass_complex'] = $mode; + $this->assertFalse(validate_password($password)); + } + + /** + * @dataProvider password_complexity_test_data_negative + */ + public function test_password_complexity_negative($password, $mode) + { + global $config; + $config['pass_complex'] = $mode; + $this->assertEquals('INVALID_CHARS', validate_password($password)); + } +} diff --git a/tests/regex/url.php b/tests/regex/url_test.php index 678b7d108f..c3a336063a 100644 --- a/tests/regex/url.php +++ b/tests/regex/url_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; class phpbb_regex_url_test extends phpbb_test_case { diff --git a/tests/request/all_tests.php b/tests/request/all_tests.php deleted file mode 100644 index 1ee3029b36..0000000000 --- a/tests/request/all_tests.php +++ /dev/null @@ -1,41 +0,0 @@ -<?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_test.php index b1dacef3fd..fa17b1909f 100644 --- a/tests/request/request_var.php +++ b/tests/request/request_var_test.php @@ -7,8 +7,8 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; class phpbb_request_request_var_test extends phpbb_test_case { diff --git a/tests/security/all_tests.php b/tests/security/base.php index 8e3916733f..db9c884cf4 100644 --- a/tests/security/all_tests.php +++ b/tests/security/base.php @@ -7,18 +7,7 @@ * */ -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 +abstract class phpbb_security_test_base extends phpbb_test_case { /** * Set up the required user object and server variables for the suites @@ -62,25 +51,4 @@ class phpbb_security_all_tests extends PHPUnit_Framework_TestSuite 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_test.php index 8c72fe1440..71c7a3a397 100644 --- a/tests/security/extract_current_page.php +++ b/tests/security/extract_current_page_test.php @@ -7,12 +7,12 @@ * */ -require_once 'test_framework/framework.php'; +require_once dirname(__FILE__) . '/base.php'; -require_once '../phpBB/includes/functions.php'; -require_once '../phpBB/includes/session.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; -class phpbb_security_extract_current_page_test extends phpbb_test_case +class phpbb_security_extract_current_page_test extends phpbb_security_test_base { public static function security_variables() { diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php new file mode 100644 index 0000000000..19a3822145 --- /dev/null +++ b/tests/security/hash_test.php @@ -0,0 +1,21 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; + +class phpbb_security_hash_test extends phpbb_test_case +{ + public function test_check_hash_with_phpass() + { + $this->assertTrue(phpbb_check_hash('test', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); + $this->assertTrue(phpbb_check_hash('test', '$P$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); + $this->assertFalse(phpbb_check_hash('foo', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); + } +} + diff --git a/tests/security/redirect.php b/tests/security/redirect_test.php index 37b0a5bb41..70ba8527b1 100644 --- a/tests/security/redirect.php +++ b/tests/security/redirect_test.php @@ -7,12 +7,12 @@ * */ -require_once 'test_framework/framework.php'; +require_once dirname(__FILE__) . '/base.php'; -require_once '../phpBB/includes/functions.php'; -require_once '../phpBB/includes/session.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; -class phpbb_security_redirect_test extends phpbb_test_case +class phpbb_security_redirect_test extends phpbb_security_test_base { public static function provider() { @@ -22,13 +22,15 @@ class phpbb_security_redirect_test extends phpbb_test_case 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('javascript:test', false, 'http://localhost/phpBB/../javascript:test'), array('http://localhost/phpBB/index.php;url=', 'Tried to redirect to potentially insecure url.', false), ); } protected function setUp() { + parent::setUp(); + $GLOBALS['config'] = array( 'force_server_vars' => '0', ); diff --git a/tests/session/continue_test.php b/tests/session/continue_test.php new file mode 100644 index 0000000000..6737562a0a --- /dev/null +++ b/tests/session/continue_test.php @@ -0,0 +1,121 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../mock/cache.php'; +require_once dirname(__FILE__) . '/testable_factory.php'; + +class phpbb_session_continue_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/sessions_full.xml'); + } + + static public function session_begin_attempts() + { + // The session_id field is defined as CHAR(32) in the database schema. + // Thus the data we put in session_id fields has to have a length of 32 characters on stricter DBMSes. + // Thus we fill those strings up with zeroes until they have a string length of 32. + + return array( + array( + 'bar_session000000000000000000000', '4', 'user agent', '127.0.0.1', + array( + array('session_id' => 'anon_session00000000000000000000', 'session_user_id' => 1), + array('session_id' => 'bar_session000000000000000000000', 'session_user_id' => 4), + ), + array(), + 'If a request comes with a valid session id with matching user agent and IP, no new session should be created.', + ), + array( + 'anon_session00000000000000000000', '4', 'user agent', '127.0.0.1', + array( + array('session_id' => '__new_session_id__', 'session_user_id' => 1), // use generated SID + array('session_id' => 'bar_session000000000000000000000', 'session_user_id' => 4), + ), + array( + 'u' => array('1', null), + 'k' => array(null, null), + 'sid' => array('__new_session_id__', null), + ), + 'If a request comes with a valid session id and IP but different user id and user agent, a new anonymous session is created and the session matching the supplied session id is deleted.', + ), + ); + } + + /** + * @dataProvider session_begin_attempts + */ + public function test_session_begin_valid_session($session_id, $user_id, $user_agent, $ip, $expected_sessions, $expected_cookies, $message) + { + $db = $this->new_dbal(); + $session_factory = new phpbb_session_testable_factory; + $session_factory->set_cookies(array( + '_sid' => $session_id, + '_u' => $user_id, + )); + $session_factory->merge_config_data(array( + 'session_length' => time(), // need to do this to allow sessions started at time 0 + )); + $session_factory->merge_server_data(array( + 'HTTP_USER_AGENT' => $user_agent, + 'REMOTE_ADDR' => $ip, + )); + + $session = $session_factory->get_session($db); + $session->page = array('page' => 'page', 'forum' => 0); + + $session->session_begin(); + + $sql = 'SELECT session_id, session_user_id + FROM phpbb_sessions + ORDER BY session_user_id'; + + $expected_sessions = $this->replace_session($expected_sessions, $session->session_id); + $expected_cookies = $this->replace_session($expected_cookies, $session->session_id); + + $this->assertSqlResultEquals( + $expected_sessions, + $sql, + $message + ); + + $session->check_cookies($this, $expected_cookies); + + $session_factory->check($this); + } + + /** + * Replaces recursively the value __new_session_id__ with the given session + * id. + * + * @param array $array An array of data + * @param string $session_id The new session id to use instead of the + * placeholder. + * @return array The input array with all occurances of __new_session_id__ + * replaced. + */ + public function replace_session($array, $session_id) + { + foreach ($array as $key => &$value) + { + if ($value === '__new_session_id__') + { + $value = $session_id; + } + + if (is_array($value)) + { + $value = $this->replace_session($value, $session_id); + } + } + + return $array; + } +} diff --git a/tests/session/fixtures/sessions_empty.xml b/tests/session/fixtures/sessions_empty.xml new file mode 100644 index 0000000000..f94337314e --- /dev/null +++ b/tests/session/fixtures/sessions_empty.xml @@ -0,0 +1,25 @@ +<?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>anonymous</value> + </row> + <row> + <value>3</value> + <value>foo</value> + </row> + <row> + <value>4</value> + <value>bar</value> + </row> + </table> + <table name="phpbb_sessions"> + <column>session_id</column> + <column>session_user_id</column> + <column>session_ip</column> + <column>session_browser</column> + </table> +</dataset> diff --git a/tests/session/fixtures/sessions_full.xml b/tests/session/fixtures/sessions_full.xml new file mode 100644 index 0000000000..bf6fc65997 --- /dev/null +++ b/tests/session/fixtures/sessions_full.xml @@ -0,0 +1,37 @@ +<?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>anonymous</value> + </row> + <row> + <value>3</value> + <value>foo</value> + </row> + <row> + <value>4</value> + <value>bar</value> + </row> + </table> + <table name="phpbb_sessions"> + <column>session_id</column> + <column>session_user_id</column> + <column>session_ip</column> + <column>session_browser</column> + <row> + <value>anon_session00000000000000000000</value> + <value>1</value> + <value>127.0.0.1</value> + <value>anonymous user agent</value> + </row> + <row> + <value>bar_session000000000000000000000</value> + <value>4</value> + <value>127.0.0.1</value> + <value>user agent</value> + </row> + </table> +</dataset> diff --git a/tests/session/init_test.php b/tests/session/init_test.php new file mode 100644 index 0000000000..1181fab636 --- /dev/null +++ b/tests/session/init_test.php @@ -0,0 +1,56 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../mock/cache.php'; +require_once dirname(__FILE__) . '/testable_factory.php'; + +class phpbb_session_init_test extends phpbb_database_test_case +{ + public function getDataSet() + { + return $this->createXMLDataSet(dirname(__FILE__).'/fixtures/sessions_empty.xml'); + } + + // also see security/extract_current_page.php + + public function test_login_session_create() + { + $db = $this->new_dbal(); + $session_factory = new phpbb_session_testable_factory; + + $session = $session_factory->get_session($db); + $session->page = array('page' => 'page', 'forum' => 0); + + $session->session_create(3); + + $sql = 'SELECT session_user_id + FROM phpbb_sessions'; + + $this->assertSqlResultEquals( + array(array('session_user_id' => 3)), + $sql, + 'Check if exacly one session for user id 3 was created' + ); + + $cookie_expire = $session->time_now + 31536000; // default is one year + + $session->check_cookies($this, array( + 'u' => array(null, $cookie_expire), + 'k' => array(null, $cookie_expire), + 'sid' => array($session->session_id, $cookie_expire), + )); + + global $SID, $_SID; + $this->assertEquals($session->session_id, $_SID); + $this->assertEquals('?sid=' . $session->session_id, $SID); + + $session_factory->check($this); + } +} + diff --git a/tests/session/testable_factory.php b/tests/session/testable_factory.php new file mode 100644 index 0000000000..f3ef19a257 --- /dev/null +++ b/tests/session/testable_factory.php @@ -0,0 +1,171 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../mock/session_testable.php'; + +/** +* This class exists to setup an instance of phpbb's session class for testing. +* +* The session class has rather complex dependencies, so in order to make its +* tests more * understandable and to make its dependencies more visible this +* factory class sets up all the necessary global state & variable contents. +*/ +class phpbb_session_testable_factory +{ + protected $config_data; + protected $cache_data; + protected $cookies; + + protected $config; + protected $cache; + + /** + * Initialises the factory with a set of default config and cache values. + */ + public function __construct() + { + // default configuration values + $this->config_data = array( + 'allow_autologin' => false, + 'auth_method' => 'db', + 'forwarded_for_check' => true, + 'active_sessions' => 0, // disable + 'rand_seed' => 'foo', + 'rand_seed_last_update' => 0, + 'max_autologin_time' => 0, + 'session_length' => 100, + 'form_token_lifetime' => 100, + 'cookie_name' => '', + 'limit_load' => 0, + 'limit_search_load' => 0, + 'ip_check' => 3, + 'browser_check' => 1, + ); + + $this->cache_data = array( + '_bots' => array(), + ); + + $this->cookies = array(); + + $this->server_data = $_SERVER; + } + + /** + * Retrieve the configured session class instance + * + * @param dbal $dbal The database connection to use for session data + * @return phpbb_mock_session_testable A session instance + */ + public function get_session(dbal $dbal) + { + // set up all the global variables used by session + global $SID, $_SID, $db, $config, $cache; + + $config = $this->config = $this->get_config_data(); + $db = $dbal; + + $cache = $this->cache = new phpbb_mock_cache($this->get_cache_data()); + $SID = $_SID = null; + + $_COOKIE = $this->cookies; + $_SERVER = $this->server_data; + + $session = new phpbb_mock_session_testable; + return $session; + } + + /** + * Set the cookies which should be present in the request data. + * + * @param array $cookies The cookie data, structured like $_COOKIE contents. + */ + public function set_cookies(array $cookies) + { + $this->cookies = $cookies; + } + + /** + * Check if the cache used for the generated session contains correct data. + * + * @param PHPUnit_Framework_Assert $test The test case to call assert methods + * on + */ + public function check(PHPUnit_Framework_Assert $test) + { + $this->cache->check($test, $this->get_cache_data()); + } + + /** + * Merge config data with the current config data to be supplied to session. + * + * New values overwrite new ones. + * + * @param array $config_data The config data to merge with previous data + */ + public function merge_config_data(array $config_data) + { + $this->config_data = array_merge($this->config_data, $config_data); + } + + /** + * Retrieve the entire config data to be passed to the session. + * + * @return array Configuration + */ + public function get_config_data() + { + return $this->config_data; + } + + /** + * Merge the cache contents with more data. + * + * New values overwrite old ones. + * + * @param array $cache_data The additional cache data + */ + public function merge_cache_data(array $cache_data) + { + $this->cache_data = array_merge($this->cache_data, $cache_data); + } + + /** + * Retrieve the entire cache data to be passed to the session. + * + * @return array Cache contents + */ + public function get_cache_data() + { + return $this->cache_data; + } + + /** + * Merge the current server info ($_SERVER) with more data. + * + * New values overwrite old ones. + * + * @param array $server_data The additional server variables + */ + public function merge_server_data($server_data) + { + return $this->server_data = array_merge($this->server_data, $server_data); + } + + /** + * Retrieve all server variables to be passed to the session. + * + * @return array Server variables + */ + public function get_server_data() + { + return $this->server_data; + } +} + diff --git a/tests/template/all_tests.php b/tests/template/all_tests.php deleted file mode 100644 index ea258c1680..0000000000 --- a/tests/template/all_tests.php +++ /dev/null @@ -1,40 +0,0 @@ -<?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_test.php index 0c2ca8a032..33c82d53ad 100644 --- a/tests/template/template.php +++ b/tests/template/template_test.php @@ -7,9 +7,8 @@ * */ -require_once 'test_framework/framework.php'; - -require_once '../phpBB/includes/template.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/template.php'; class phpbb_template_template_test extends phpbb_test_case { @@ -344,8 +343,7 @@ class phpbb_template_template_test extends phpbb_test_case */ public function test_template($file, array $vars, array $block_vars, array $destroy, $expected) { - global $phpEx; - $cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.' . $phpEx; + $cache_file = $this->template->cachepath . str_replace('/', '.', $file) . '.php'; $this->assertFileNotExists($cache_file); @@ -395,11 +393,9 @@ class phpbb_template_template_test extends phpbb_test_case public function test_php() { - global $phpEx; - $GLOBALS['config']['tpl_allow_php'] = true; - $cache_file = $this->template->cachepath . 'php.html.' . $phpEx; + $cache_file = $this->template->cachepath . 'php.html.php'; $this->assertFileNotExists($cache_file); @@ -410,21 +406,14 @@ class phpbb_template_template_test extends phpbb_test_case 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'); + $cache_file = $this->template->cachepath . 'includephp.html.php'; $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); + $this->assertEquals('testing included php', $this->display('test'), "Testing INCLUDEPHP"); $GLOBALS['config']['tpl_allow_php'] = false; } @@ -438,17 +427,16 @@ class phpbb_template_template_test extends phpbb_test_case 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 +outer - 0 - before +outer - 1 +middle - 0 +middle - 1 +outer - 2 +middle - 0 +middle - 1 +outer - 3 +middle - 0 +middle - 1 EOT , 'Test inserting before on top level block', @@ -459,17 +447,16 @@ EOT 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 +outer - 0 +middle - 0 +middle - 1 +outer - 1 +middle - 0 +middle - 1 +outer - 2 +middle - 0 +middle - 1 +outer - 3 - after EOT , 'Test inserting after on top level block', @@ -480,17 +467,16 @@ EOT 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 +outer - 0 +middle - 0 +middle - 1 +outer - 1 - pos #1 +outer - 2 +middle - 0 +middle - 1 +outer - 3 +middle - 0 +middle - 1 EOT , 'Test inserting at 1 on top level block', @@ -501,172 +487,27 @@ EOT 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 +outer - 0 - pos #1 +middle - 0 +middle - 1 +outer - 1 +middle - 0 +middle - 1 +outer - 2 +middle - 0 +middle - 1 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 @@ -676,12 +517,11 @@ EOT $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->assertEquals("outer - 0\nmiddle - 0\nmiddle - 1\nouter - 1\nmiddle - 0\nmiddle - 1\nouter - 2\nmiddle - 0\nmiddle - 1", $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 deleted file mode 100644 index 1de5dddf59..0000000000 --- a/tests/template/templates/_dummy_include.php +++ /dev/null @@ -1,3 +0,0 @@ -<?php - -echo "testing included php"; diff --git a/tests/template/templates/_dummy_include.php.inc b/tests/template/templates/_dummy_include.php.inc new file mode 100644 index 0000000000..aacb6b2045 --- /dev/null +++ b/tests/template/templates/_dummy_include.php.inc @@ -0,0 +1,3 @@ +<?php +// extension is .php.inc so PHPUnit ignores it +echo "testing included php"; diff --git a/tests/template/templates/includephp.html b/tests/template/templates/includephp.html index 3e13fa33fa..70ebdac0d0 100644 --- a/tests/template/templates/includephp.html +++ b/tests/template/templates/includephp.html @@ -1 +1 @@ -<!-- INCLUDEPHP ../templates/_dummy_include.php --> +<!-- INCLUDEPHP ../tests/template/templates/_dummy_include.php.inc --> diff --git a/tests/template/templates/loop_nested.html b/tests/template/templates/loop_nested.html index 571df97b4c..9b251cd453 100644 --- a/tests/template/templates/loop_nested.html +++ b/tests/template/templates/loop_nested.html @@ -1,8 +1,8 @@ <!-- BEGIN outer --> - {outer.S_BLOCK_NAME} - {outer.S_ROW_NUM}/{outer.S_NUM_ROWS}<!-- IF outer.VARIABLE --> - {outer.VARIABLE}<!-- ENDIF --> + outer - {outer.S_ROW_COUNT}<!-- 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 --> + middle - {middle.S_ROW_COUNT}<!-- IF middle.VARIABLE --> - {middle.VARIABLE}<!-- ENDIF --> <!-- END middle --> <!-- END outer --> diff --git a/tests/test_framework/phpbb_database_test_case.php b/tests/test_framework/phpbb_database_test_case.php index a64bae8c57..e1b368dcea 100644 --- a/tests/test_framework/phpbb_database_test_case.php +++ b/tests/test_framework/phpbb_database_test_case.php @@ -9,10 +9,25 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_TestCase { - private static $already_connected; + static private $already_connected; protected $test_case_helpers; + public function __construct($name = NULL, array $data = array(), $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->backupStaticAttributesBlacklist += array( + 'PHP_CodeCoverage' => array('instance'), + 'PHP_CodeCoverage_Filter' => array('instance'), + 'PHP_CodeCoverage_Util' => array('ignoredLines', 'templateMethods'), + 'PHP_Timer' => array('startTimes',), + 'PHP_Token_Stream' => array('customTokens'), + 'PHP_Token_Stream_CachingFactory' => array('cache'), + + 'phpbb_database_test_case' => array('already_connected'), + ); + } + public function get_test_case_helpers() { if (!$this->test_case_helpers) @@ -23,66 +38,6 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test return $this->test_case_helpers; } - public 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' => 'sqlsrv', - ), - 'oracle' => array( - 'SCHEMA' => 'oracle', - 'DELIM' => '/', - 'PDO' => 'oci', - ), - 'postgres' => array( - 'SCHEMA' => 'postgres', - 'DELIM' => ';', - 'PDO' => 'pgsql', - ), - 'sqlite' => array( - 'SCHEMA' => 'sqlite', - 'DELIM' => ';', - 'PDO' => 'sqlite2', - ), - ); - - if (isset($available_dbms[$dbms])) - { - return $available_dbms[$dbms]; - } - else - { - trigger_error('Database unsupported', E_USER_ERROR); - } - } - public function get_database_config() { if (isset($_SERVER['PHPBB_TEST_DBMS'])) @@ -96,9 +51,9 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test 'dbpasswd' => isset($_SERVER['PHPBB_TEST_DBPASSWD']) ? $_SERVER['PHPBB_TEST_DBPASSWD'] : '', ); } - else if (file_exists('test_config.php')) + else if (file_exists(dirname(__FILE__) . '/../test_config.php')) { - include('test_config.php'); + include(dirname(__FILE__) . '/../test_config.php'); return array( 'dbms' => $dbms, @@ -114,7 +69,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test // Silently use sqlite return array( 'dbms' => 'sqlite', - 'dbhost' => 'phpbb_unit_tests.sqlite2', // filename + 'dbhost' => dirname(__FILE__) . '/../phpbb_unit_tests.sqlite2', // filename 'dbport' => '', 'dbname' => '', 'dbuser' => '', @@ -127,232 +82,26 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test } } - // NOTE: This function is not the same as split_sql_file from functions_install - public function split_sql_file($sql, $dbms) - { - $dbms_data = $this->get_dbms_data($dbms); - - $sql = str_replace("\r" , '', $sql); - $data = preg_split('/' . preg_quote($dbms_data['DELIM'], '/') . '$/m', $sql); - - $data = array_map('trim', $data); - - // The empty case - $end_data = end($data); - - if (empty($end_data)) - { - unset($data[key($data)]); - } - - if ($dbms == 'sqlite') - { - // remove comment lines starting with # - they are not proper sqlite - // syntax and break sqlite2 - foreach ($data as $i => $query) - { - $data[$i] = preg_replace('/^#.*$/m', "\n", $query); - } - } - - return $data; - } - - /** - * Retrieves a list of all tables from the database. - * - * @param PDO $pdo - * @param string $dbms - * @return array(string) - */ - function get_tables($pdo, $dbms) - { - switch ($pdo) - { - case 'mysql': - case 'mysql4': - case 'mysqli': - $sql = 'SHOW TABLES'; - break; - - case 'sqlite': - $sql = 'SELECT name - FROM sqlite_master - WHERE type = "table"'; - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssqlnative': - $sql = "SELECT name - FROM sysobjects - WHERE type='U'"; - break; - - case 'postgres': - $sql = 'SELECT relname - FROM pg_stat_user_tables'; - break; - - case 'firebird': - $sql = 'SELECT rdb$relation_name - FROM rdb$relations - WHERE rdb$view_source is null - AND rdb$system_flag = 0'; - break; - - case 'oracle': - $sql = 'SELECT table_name - FROM USER_TABLES'; - break; - } - - $result = $pdo->query($sql); - - $tables = array(); - while ($row = $result->fetch(PDO::FETCH_NUM)) - { - $tables[] = current($row); - } - - return $tables; - } - - /** - * Returns a PDO connection for the configured database. - * - * @param array $config The database configuration - * @param array $dbms Information on the used DBMS. - * @param bool $use_db Whether the DSN should be tied to a - * particular database making it impossible - * to delete that database. - * @return PDO The PDO database connection. - */ - public function new_pdo($config, $dbms, $use_db) - { - $dsn = $dbms['PDO'] . ':'; - - switch ($dbms['PDO']) - { - case 'sqlite2': - $dsn .= $config['dbhost']; - break; - - case 'sqlsrv': - // prefix the hostname (or DSN) with Server= so using just (local)\SQLExpress - // works for example, further parameters can still be appended using ;x=y - $dsn .= 'Server='; - // no break -> rest like ODBC - case 'odbc': - // for ODBC assume dbhost is a suitable DSN - // e.g. Driver={SQL Server Native Client 10.0};Server=(local)\SQLExpress; - $dsn .= $config['dbhost']; - - if ($use_db) - { - $dsn .= ';Database=' . $config['dbname']; - } - break; - - default: - $dsn .= 'host=' . $config['dbhost']; - - if ($use_db) - { - $dsn .= ';dbname=' . $config['dbname']; - } - break; - } - - $pdo = new PDO($dsn, $config['dbuser'], $config['dbpasswd']);; - - // good for debug - // $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); - - return $pdo; - } - - private function recreate_db($config, $dbms) - { - switch ($config['dbms']) - { - case 'sqlite': - if (file_exists($config['dbhost'])) - { - unlink($config['dbhost']); - } - break; - - default: - $pdo = $this->new_pdo($config, $dbms, false); - - try - { - $pdo->exec('DROP DATABASE ' . $config['dbname']); - } - catch (PDOException $e) - { - // try to delete all tables if dropping the database was not possible. - foreach ($this->get_tables() as $table) - { - try - { - $pdo->exec('DROP TABLE ' . $table); - } - catch (PDOException $e){} // ignore non-existent tables - } - } - - $pdo->exec('CREATE DATABASE ' . $config['dbname']); - break; - } - } - - private function load_schema($pdo, $config, $dbms) - { - if ($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['SCHEMA'] .= '_41'; - } - else - { - $dbms['SCHEMA'] .= '_40'; - } - } - - $sql = $this->split_sql_file(file_get_contents("../phpBB/install/schemas/{$dbms['SCHEMA']}_schema.sql"), $config['dbms']); - - foreach ($sql as $query) - { - $pdo->exec($query); - } - } - public function getConnection() { $config = $this->get_database_config(); - $dbms = $this->get_dbms_data($config['dbms']); + + $manager = $this->create_connection_manager($config); if (!self::$already_connected) { - $this->recreate_db($config, $dbms); + $manager->recreate_db(); } - $pdo = $this->new_pdo($config, $dbms, true); + $manager->connect(); if (!self::$already_connected) { - $this->load_schema($pdo, $config, $dbms); - + $manager->load_schema(); self::$already_connected = true; } - return $this->createDefaultDBConnection($pdo, 'testdb'); + return $this->createDefaultDBConnection($manager->get_pdo(), 'testdb'); } public function new_dbal() @@ -361,7 +110,7 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test $config = $this->get_database_config(); - require_once '../phpBB/includes/db/' . $config['dbms'] . '.php'; + require_once dirname(__FILE__) . '/../../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']); @@ -369,8 +118,24 @@ abstract class phpbb_database_test_case extends PHPUnit_Extensions_Database_Test return $db; } + public function assertSqlResultEquals($expected, $sql, $message = '') + { + $db = $this->new_dbal(); + + $result = $db->sql_query($sql); + $rows = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + $this->assertEquals($expected, $rows, $message); + } + public function setExpectedTriggerError($errno, $message = '') { $this->get_test_case_helpers()->setExpectedTriggerError($errno, $message); } + + protected function create_connection_manager($config) + { + return new phpbb_database_test_connection_manager($config); + } } diff --git a/tests/test_framework/phpbb_database_test_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php new file mode 100644 index 0000000000..a7559e2183 --- /dev/null +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -0,0 +1,346 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +class phpbb_database_test_connection_manager +{ + private $config; + private $dbms; + private $pdo; + + /** + * Constructor + * + * @param array $config Tests database configuration as returned by + * phpbb_database_test_case::get_database_config() + */ + public function __construct($config) + { + $this->config = $config; + $this->dbms = $this->get_dbms_data($this->config['dbms']); + } + + /** + * Return the current PDO instance + */ + public function get_pdo() + { + return $this->pdo; + } + + /** + * Creates a PDO connection for the configured database. + * + * @param bool $use_db Whether the DSN should be tied to a + * particular database making it impossible + * to delete that database. + */ + public function connect($use_db = true) + { + $dsn = $this->dbms['PDO'] . ':'; + + switch ($this->dbms['PDO']) + { + case 'sqlite2': + $dsn .= $this->config['dbhost']; + break; + + case 'sqlsrv': + // prefix the hostname (or DSN) with Server= so using just (local)\SQLExpress + // works for example, further parameters can still be appended using ;x=y + $dsn .= 'Server='; + // no break -> rest like ODBC + case 'odbc': + // for ODBC assume dbhost is a suitable DSN + // e.g. Driver={SQL Server Native Client 10.0};Server=(local)\SQLExpress; + $dsn .= $this->config['dbhost']; + + if ($use_db) + { + $dsn .= ';Database=' . $this->config['dbname']; + } + break; + + default: + $dsn .= 'host=' . $this->config['dbhost']; + + if ($use_db) + { + $dsn .= ';dbname=' . $this->config['dbname']; + } + break; + } + + try + { + $this->pdo = new PDO($dsn, $this->config['dbuser'], $this->config['dbpasswd']); + } + catch (PDOException $e) + { + $cleaned_dsn = str_replace($this->config['dbpasswd'], '*password*', $dsn); + throw new Exception("Unable do connect to $cleaned_dsn using PDO with error: {$e->getMessage()}"); + } + + // good for debug + // $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + } + + /** + * Load the phpBB database schema into the database + */ + public function load_schema() + { + $this->ensure_connected(__METHOD__); + + $directory = dirname(__FILE__) . '/../../phpBB/install/schemas/'; + $this->load_schema_from_file($directory); + } + + /** + * Drop the database if it exists and re-create it + * + * Note: This does not load the schema, and it is suggested + * to re-connect after calling to get use_db isolation. + */ + public function recreate_db() + { + switch ($this->config['dbms']) + { + case 'sqlite': + if (file_exists($this->config['dbhost'])) + { + unlink($this->config['dbhost']); + } + break; + + default: + $this->connect(false); + + try + { + $this->pdo->exec('DROP DATABASE ' . $this->config['dbname']); + } + catch (PDOException $e) + { + // try to delete all tables if dropping the database was not possible. + foreach ($this->get_tables() as $table) + { + $this->pdo->exec('DROP TABLE ' . $table); + } + } + + $this->pdo->exec('CREATE DATABASE ' . $this->config['dbname']); + break; + } + } + + /** + * Retrieves a list of all tables from the database. + * + * @return array(string) + */ + public function get_tables() + { + $this->ensure_connected(__METHOD__); + + switch ($this->config['dbms']) + { + case 'mysql': + case 'mysql4': + case 'mysqli': + $sql = 'SHOW TABLES'; + break; + + case 'sqlite': + $sql = 'SELECT name + FROM sqlite_master + WHERE type = "table"'; + break; + + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $sql = "SELECT name + FROM sysobjects + WHERE type='U'"; + break; + + case 'postgres': + $sql = 'SELECT relname + FROM pg_stat_user_tables'; + break; + + case 'firebird': + $sql = 'SELECT rdb$relation_name + FROM rdb$relations + WHERE rdb$view_source is null + AND rdb$system_flag = 0'; + break; + + case 'oracle': + $sql = 'SELECT table_name + FROM USER_TABLES'; + break; + } + + $result = $this->pdo->query($sql); + + $tables = array(); + while ($row = $result->fetch(PDO::FETCH_NUM)) + { + $tables[] = current($row); + } + + return $tables; + } + + /** + * Throw an exception if not connected + */ + protected function ensure_connected($method_name) + { + if (null === $this->pdo) + { + throw new Exception(sprintf('You must connect before calling %s', $method_name)); + } + } + + /** + * Compile the correct schema filename (as per create_schema_files) and + * load it into the database. + */ + protected function load_schema_from_file($directory) + { + $schema = $this->dbms['SCHEMA']; + + if ($this->config['dbms'] == 'mysql') + { + $sth = $this->pdo->query('SELECT VERSION() AS version'); + $row = $sth->fetch(PDO::FETCH_ASSOC); + + if (version_compare($row['version'], '4.1.3', '>=')) + { + $schema .= '_41'; + } + else + { + $schema .= '_40'; + } + } + + $filename = $directory . $schema . '_schema.sql'; + $sql = $this->split_sql(file_get_contents($filename)); + + foreach ($sql as $query) + { + $this->pdo->exec($query); + } + } + + /** + * Split contents of an SQL file into an array of SQL statements + * + * Note: This method is not the same as split_sql_file from functions_install. + * + * @param string $sql Raw contents of an SQL file + * + * @return Array of runnable SQL statements + */ + protected function split_sql($sql) + { + $sql = str_replace("\r" , '', $sql); + $data = preg_split('/' . preg_quote($this->dbms['DELIM'], '/') . '$/m', $sql); + + $data = array_map('trim', $data); + + // The empty case + $end_data = end($data); + + if (empty($end_data)) + { + unset($data[key($data)]); + } + + if ($this->config['dbms'] == 'sqlite') + { + // remove comment lines starting with # - they are not proper sqlite + // syntax and break sqlite2 + foreach ($data as $i => $query) + { + $data[$i] = preg_replace('/^#.*$/m', "\n", $query); + } + } + + return $data; + } + + /** + * Map a phpBB dbms driver name to dbms data array + */ + protected 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' => 'sqlsrv', + ), + 'oracle' => array( + 'SCHEMA' => 'oracle', + 'DELIM' => '/', + 'PDO' => 'oci', + ), + 'postgres' => array( + 'SCHEMA' => 'postgres', + 'DELIM' => ';', + 'PDO' => 'pgsql', + ), + 'sqlite' => array( + 'SCHEMA' => 'sqlite', + 'DELIM' => ';', + 'PDO' => 'sqlite2', + ), + ); + + if (isset($available_dbms[$dbms])) + { + return $available_dbms[$dbms]; + } + else + { + $message = "Supplied dbms \"$dbms\" is not a valid phpBB dbms, must be one of: "; + $message .= implode(', ', array_keys($available_dbms)); + throw new Exception($message); + } + } +} diff --git a/tests/test_framework/phpbb_test_case.php b/tests/test_framework/phpbb_test_case.php index fe90d321dc..f189da3671 100644 --- a/tests/test_framework/phpbb_test_case.php +++ b/tests/test_framework/phpbb_test_case.php @@ -11,6 +11,21 @@ class phpbb_test_case extends PHPUnit_Framework_TestCase { protected $test_case_helpers; + public function __construct($name = NULL, array $data = array(), $dataName = '') + { + parent::__construct($name, $data, $dataName); + $this->backupStaticAttributesBlacklist += array( + 'PHP_CodeCoverage' => array('instance'), + 'PHP_CodeCoverage_Filter' => array('instance'), + 'PHP_CodeCoverage_Util' => array('ignoredLines', 'templateMethods'), + 'PHP_Timer' => array('startTimes',), + 'PHP_Token_Stream' => array('customTokens'), + 'PHP_Token_Stream_CachingFactory' => array('cache'), + + 'phpbb_database_test_case' => array('already_connected'), + ); + } + public function get_test_case_helpers() { if (!$this->test_case_helpers) diff --git a/tests/text_processing/all_tests.php b/tests/text_processing/all_tests.php deleted file mode 100644 index 5e759c72ee..0000000000 --- a/tests/text_processing/all_tests.php +++ /dev/null @@ -1,41 +0,0 @@ -<?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_test.php index a667dd705e..29b982d709 100644 --- a/tests/text_processing/make_clickable.php +++ b/tests/text_processing/make_clickable_test.php @@ -7,10 +7,8 @@ * */ -require_once 'test_framework/framework.php'; - -require_once '../phpBB/includes/functions.php'; -require_once '../phpBB/includes/functions_content.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_content.php'; class phpbb_text_processing_make_clickable_test extends phpbb_test_case { diff --git a/tests/user/lang_test.php b/tests/user/lang_test.php new file mode 100644 index 0000000000..6c60583a7b --- /dev/null +++ b/tests/user/lang_test.php @@ -0,0 +1,58 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/session.php'; + +class phpbb_user_lang_test extends phpbb_test_case +{ + public function test_user_lang_sprintf() + { + $user = new user; + $user->lang = array( + 'FOO' => 'BAR', + 'BARZ' => 'PENG', + 'EMPTY' => '', + 'ZERO' => '0', + 'STR' => '%d %s, %d topics', + 'STR2' => '%d foos', + 'ARRY' => array( + 0 => 'No posts', // 0 + 1 => '1 post', // 1 + 2 => '%d posts', // 2+ + ), + ); + + // No param + $this->assertEquals($user->lang('FOO'), 'BAR'); + $this->assertEquals($user->lang('EMPTY'), ''); + $this->assertEquals($user->lang('ZERO'), '0'); + + // Invalid index + $this->assertEquals($user->lang('VOID'), 'VOID'); + + // Unnecessary param + $this->assertEquals($user->lang('FOO', 2), 'BAR'); + $this->assertEquals($user->lang('FOO', 2, 3), 'BAR'); + $this->assertEquals($user->lang('FOO', 2, 3, 'BARZ'), 'BAR'); + + // String + $this->assertEquals($user->lang('STR', 24, 'x', 42), '24 x, 42 topics'); + $this->assertEquals($user->lang('STR2', 64), '64 foos'); + + // Array + $this->assertEquals($user->lang('ARRY', 0), 'No posts'); + $this->assertEquals($user->lang('ARRY', 1), '1 post'); + $this->assertEquals($user->lang('ARRY', 2), '2 posts'); + $this->assertEquals($user->lang('ARRY', 123), '123 posts'); + + // Bug PHPBB3-9949 + $this->assertEquals($user->lang('ARRY', 1, 2), '1 post'); + $this->assertEquals($user->lang('ARRY', 1, 's', 2), '1 post'); + } +} diff --git a/tests/utf/all_tests.php b/tests/utf/all_tests.php deleted file mode 100644 index 0d5d44d695..0000000000 --- a/tests/utf/all_tests.php +++ /dev/null @@ -1,43 +0,0 @@ -<?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/data/.gitkeep b/tests/utf/data/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/utf/data/.gitkeep diff --git a/tests/utf/normalizer_test.php b/tests/utf/normalizer_test.php new file mode 100644 index 0000000000..38b4ec1b6b --- /dev/null +++ b/tests/utf/normalizer_test.php @@ -0,0 +1,318 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2011 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_normalizer.php'; + +/** +* @group slow +*/ +class phpbb_utf_normalizer_test extends phpbb_test_case +{ + static public function setUpBeforeClass() + { + self::download('http://www.unicode.org/Public/UNIDATA/NormalizationTest.txt', dirname(__FILE__).'/data'); + self::download('http://www.unicode.org/Public/UNIDATA/UnicodeData.txt', dirname(__FILE__).'/data'); + } + + public function test_normalizer() + { + $test_suite = array( + /** + * NFC + * c2 == NFC(c1) == NFC(c2) == NFC(c3) + * c4 == NFC(c4) == NFC(c5) + */ + 'NFC' => array( + 'c2' => array('c1', 'c2', 'c3'), + 'c4' => array('c4', 'c5') + ), + + /** + * NFD + * c3 == NFD(c1) == NFD(c2) == NFD(c3) + * c5 == NFD(c4) == NFD(c5) + */ + 'NFD' => array( + 'c3' => array('c1', 'c2', 'c3'), + 'c5' => array('c4', 'c5') + ), + + /** + * NFKC + * c4 == NFKC(c1) == NFKC(c2) == NFKC(c3) == NFKC(c4) == NFKC(c5) + */ + 'NFKC' => array( + 'c4' => array('c1', 'c2', 'c3', 'c4', 'c5') + ), + + /** + * NFKD + * c5 == NFKD(c1) == NFKD(c2) == NFKD(c3) == NFKD(c4) == NFKD(c5) + */ + 'NFKD' => array( + 'c5' => array('c1', 'c2', 'c3', 'c4', 'c5') + ) + ); + + $tested_chars = array(); + + $fp = fopen(dirname(__FILE__).'/data/NormalizationTest.txt', 'rb'); + while (!feof($fp)) + { + $line = fgets($fp); + + if ($line[0] == '@') + { + continue; + } + + if (!strpos(' 0123456789ABCDEF', $line[0])) + { + continue; + } + + list($c1, $c2, $c3, $c4, $c5) = explode(';', $line); + + if (!strpos($c1, ' ')) + { + /** + * We are currently testing a single character, we add it to the list of + * characters we have processed so that we can exclude it when testing + * for invariants + */ + $tested_chars[$c1] = 1; + } + + foreach ($test_suite as $form => $serie) + { + foreach ($serie as $expected => $tests) + { + $hex_expected = ${$expected}; + $utf_expected = $this->hexseq_to_utf($hex_expected); + + foreach ($tests as $test) + { + $utf_result = $utf_expected; + call_user_func(array('utf_normalizer', $form), &$utf_result); + + $hex_result = $this->utf_to_hexseq($utf_result); + $this->assertEquals($utf_expected, $utf_result, "$expected == $form($test) ($hex_expected != $hex_result)"); + } + } + } + } + fclose($fp); + + return $tested_chars; + } + + /** + * @depends test_normalizer + */ + public function test_invariants(array $tested_chars) + { + $fp = fopen(dirname(__FILE__).'/data/UnicodeData.txt', 'rb'); + + while (!feof($fp)) + { + $line = fgets($fp, 1024); + + if (!$pos = strpos($line, ';')) + { + continue; + } + + $hex_tested = $hex_expected = substr($line, 0, $pos); + + if (isset($tested_chars[$hex_tested])) + { + continue; + } + + $utf_expected = $this->hex_to_utf($hex_expected); + + if ($utf_expected >= UTF8_SURROGATE_FIRST + && $utf_expected <= UTF8_SURROGATE_LAST) + { + /** + * Surrogates are illegal on their own, we expect the normalizer + * to return a replacement char + */ + $utf_expected = UTF8_REPLACEMENT; + $hex_expected = $this->utf_to_hexseq($utf_expected); + } + + foreach (array('nfc', 'nfkc', 'nfd', 'nfkd') as $form) + { + $utf_result = $utf_expected; + call_user_func(array('utf_normalizer', $form), &$utf_result); + $hex_result = $this->utf_to_hexseq($utf_result); + + $this->assertEquals($utf_expected, $utf_result, "$hex_expected == $form($hex_tested) ($hex_expected != $hex_result)"); + } + } + fclose($fp); + } + + /** + * Convert a UTF string to a sequence of codepoints in hexadecimal + * + * @param string $utf UTF string + * @return integer Unicode codepoints in hex + */ + protected function utf_to_hexseq($str) + { + $pos = 0; + $len = strlen($str); + $ret = array(); + + while ($pos < $len) + { + $c = $str[$pos]; + switch ($c & "\xF0") + { + case "\xC0": + case "\xD0": + $utf_char = substr($str, $pos, 2); + $pos += 2; + break; + + case "\xE0": + $utf_char = substr($str, $pos, 3); + $pos += 3; + break; + + case "\xF0": + $utf_char = substr($str, $pos, 4); + $pos += 4; + break; + + default: + $utf_char = $c; + ++$pos; + } + + $hex = dechex($this->utf_to_cp($utf_char)); + + if (!isset($hex[3])) + { + $hex = substr('000' . $hex, -4); + } + + $ret[] = $hex; + } + + return strtr(implode(' ', $ret), 'abcdef', 'ABCDEF'); + } + + /** + * Convert a UTF-8 char to its codepoint + * + * @param string $utf_char UTF-8 char + * @return integer Unicode codepoint + */ + protected function utf_to_cp($utf_char) + { + switch (strlen($utf_char)) + { + case 1: + return ord($utf_char); + + case 2: + return ((ord($utf_char[0]) & 0x1F) << 6) | (ord($utf_char[1]) & 0x3F); + + case 3: + return ((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F); + + case 4: + return ((ord($utf_char[0]) & 0x07) << 18) | ((ord($utf_char[1]) & 0x3F) << 12) | ((ord($utf_char[2]) & 0x3F) << 6) | (ord($utf_char[3]) & 0x3F); + + default: + throw new RuntimeException('UTF-8 chars can only be 1-4 bytes long'); + } + } + + /** + * Return a UTF string formed from a sequence of codepoints in hexadecimal + * + * @param string $seq Sequence of codepoints, separated with a space + * @return string UTF-8 string + */ + protected function hexseq_to_utf($seq) + { + return implode('', array_map(array($this, 'hex_to_utf'), explode(' ', $seq))); + } + + /** + * Convert a codepoint in hexadecimal to a UTF-8 char + * + * @param string $hex Codepoint, in hexadecimal + * @return string UTF-8 char + */ + protected function hex_to_utf($hex) + { + return $this->cp_to_utf(hexdec($hex)); + } + + /** + * Convert a codepoint to a UTF-8 char + * + * @param integer $cp Unicode codepoint + * @return string UTF-8 string + */ + protected function cp_to_utf($cp) + { + if ($cp > 0xFFFF) + { + return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); + } + else if ($cp > 0x7FF) + { + return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); + } + else if ($cp > 0x7F) + { + return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); + } + else + { + return chr($cp); + } + } + + // chunked download helper + static protected function download($url, $to) + { + $target = $to . '/' . basename($url); + + if (file_exists($target)) + { + return; + } + + if (!$fpr = fopen($url, 'rb')) + { + throw new RuntimeException("Failed to download $url"); + } + + if (!$fpw = fopen($target, 'wb')) + { + throw new RuntimeException("Failed to open $target for writing"); + } + + $chunk = 32768; + + while (!feof($fpr)) + { + fwrite($fpw, fread($fpr, $chunk)); + } + fclose($fpr); + fclose($fpw); + } +} diff --git a/tests/utf/utf8_clean_string_test.php b/tests/utf/utf8_clean_string_test.php index 870ad76fc4..e5a771eafa 100644 --- a/tests/utf/utf8_clean_string_test.php +++ b/tests/utf/utf8_clean_string_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/utf/utf_tools.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; class phpbb_utf_utf8_clean_string_test extends phpbb_test_case { diff --git a/tests/utf/utf8_wordwrap_test.php b/tests/utf/utf8_wordwrap_test.php index ef1165a897..03fa9dc38c 100644 --- a/tests/utf/utf8_wordwrap_test.php +++ b/tests/utf/utf8_wordwrap_test.php @@ -7,8 +7,7 @@ * */ -require_once 'test_framework/framework.php'; -require_once '../phpBB/includes/utf/utf_tools.php'; +require_once dirname(__FILE__) . '/../../phpBB/includes/utf/utf_tools.php'; class phpbb_utf_utf8_wordwrap_test extends phpbb_test_case { |