diff options
63 files changed, 904 insertions, 469 deletions
diff --git a/.gitignore b/.gitignore index c417bf01c1..8298f5a894 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ *~ 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 diff --git a/build/build.xml b/build/build.xml index 724f201eb3..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" /> 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/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_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/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/mysql_upgrader.php b/phpBB/develop/mysql_upgrader.php index 5a7034b45c..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); diff --git a/phpBB/docs/AUTHORS b/phpBB/docs/AUTHORS index 1dfb80141c..83feca009b 100644 --- a/phpBB/docs/AUTHORS +++ b/phpBB/docs/AUTHORS @@ -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/INSTALL.html b/phpBB/docs/INSTALL.html index 4af185beb3..9f635fe50b 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -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> diff --git a/phpBB/docs/coding-guidelines.html b/phpBB/docs/coding-guidelines.html index 7434fa4870..cd3c09f6fb 100644 --- a/phpBB/docs/coding-guidelines.html +++ b/phpBB/docs/coding-guidelines.html @@ -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> diff --git a/phpBB/docs/nginx.sample.conf b/phpBB/docs/nginx.sample.conf index 2a11e057c5..40b6ee76da 100644 --- a/phpBB/docs/nginx.sample.conf +++ 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; @@ -45,8 +60,10 @@ http { # Deny access to internal phpbb files. location ~ /(config\.php|common\.php|includes|cache|files|store|images/avatars/upload) { - internal; 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,8 +77,8 @@ http { # Deny access to version control system directories. location ~ /\.svn|/\.git { - internal; deny all; + internal; } } 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_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_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_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_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 0f157ceff3..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 diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index 5d8d5fbd47..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 */ 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 783c331872..e057e7fe74 100644 --- a/phpBB/includes/db/mssqlnative.php +++ b/phpBB/includes/db/mssqlnative.php @@ -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 398a02380b..585e23b2ee 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; } @@ -4257,7 +4261,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)) { @@ -4607,7 +4611,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_posting.php b/phpBB/includes/functions_posting.php index 72331a73c6..271039f415 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -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_user.php b/phpBB/includes/functions_user.php index 90341cd926..8a204995aa 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); @@ -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 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_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/session.php b/phpBB/includes/session.php index 1dc854caf2..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; } 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_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/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/language/en/acp/posting.php b/phpBB/language/en/acp/posting.php index 443f4a3ea2..25152dd766 100644 --- a/phpBB/language/en/acp/posting.php +++ b/phpBB/language/en/acp/posting.php @@ -233,13 +233,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/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/memberlist.php b/phpBB/memberlist.php index 2fa2d11ee1..599cd0b3e7 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) 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/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_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_header.html b/phpBB/styles/prosilver/template/overall_header.html index 009b514e52..51fff0735a 100644 --- a/phpBB/styles/prosilver/template/overall_header.html +++ b/phpBB/styles/prosilver/template/overall_header.html @@ -81,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_header.html b/phpBB/styles/prosilver/template/simple_header.html index 66aae004a0..9cc8060762 100644 --- a/phpBB/styles/prosilver/template/simple_header.html +++ b/phpBB/styles/prosilver/template/simple_header.html @@ -46,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/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/theme/colours.css b/phpBB/styles/prosilver/theme/colours.css index 3f215def72..f7747ba73c 100644 --- a/phpBB/styles/prosilver/theme/colours.css +++ b/phpBB/styles/prosilver/theme/colours.css @@ -652,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/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/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/viewtopic.php b/phpBB/viewtopic.php index 498088c5c8..bc839066a5 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -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/tests/bootstrap.php b/tests/bootstrap.php index c729c6e2d8..6f3c93a374 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -12,6 +12,10 @@ $phpbb_root_path = 'phpBB/'; $phpEx = 'php'; $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 diff --git a/tests/mock/cache.php b/tests/mock/cache.php index 2ac46f7090..11e525ff79 100644 --- a/tests/mock/cache.php +++ b/tests/mock/cache.php @@ -53,9 +53,21 @@ class phpbb_mock_cache $test->assertEquals($data, $this->data[$var_name]); } - public function check(PHPUnit_Framework_Assert $test, $data) + public function check(PHPUnit_Framework_Assert $test, $data, $ignore_db_info = true) { - $test->assertEquals($data, $this->data); + $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/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/session/continue_test.php b/tests/session/continue_test.php index 06b03f5780..6737562a0a 100644 --- a/tests/session/continue_test.php +++ b/tests/session/continue_test.php @@ -19,27 +19,30 @@ class phpbb_session_continue_test extends phpbb_database_test_case static public function session_begin_attempts() { - global $_SID; + // 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_session', '4', 'user agent', '127.0.0.1', + 'bar_session000000000000000000000', '4', 'user agent', '127.0.0.1', array( - array('session_id' => 'anon_session', 'session_user_id' => 1), - array('session_id' => 'bar_session', 'session_user_id' => 4) + 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_session', '4', 'user agent', '127.0.0.1', + 'anon_session00000000000000000000', '4', 'user agent', '127.0.0.1', array( - array('session_id' => 'bar_session', 'session_user_id' => 4), - array('session_id' => null, 'session_user_id' => 1) // use generated SID + 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($_SID, 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.', ), @@ -71,26 +74,48 @@ class phpbb_session_continue_test extends phpbb_database_test_case $session->session_begin(); $sql = 'SELECT session_id, session_user_id - FROM phpbb_sessions'; + FROM phpbb_sessions + ORDER BY session_user_id'; - // little tickery to allow using a dataProvider with dynamic expected result - foreach ($expected_sessions as $i => $s) - { - if (is_null($s['session_id'])) - { - $expected_sessions[$i]['session_id'] = $session->session_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, - 'Check if no new session was created' + $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_full.xml b/tests/session/fixtures/sessions_full.xml index 4559a08c55..bf6fc65997 100644 --- a/tests/session/fixtures/sessions_full.xml +++ b/tests/session/fixtures/sessions_full.xml @@ -22,13 +22,13 @@ <column>session_ip</column> <column>session_browser</column> <row> - <value>anon_session</value> + <value>anon_session00000000000000000000</value> <value>1</value> <value>127.0.0.1</value> <value>anonymous user agent</value> </row> <row> - <value>bar_session</value> + <value>bar_session000000000000000000000</value> <value>4</value> <value>127.0.0.1</value> <value>user agent</value> diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 1b2f35f210..33c82d53ad 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -343,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); @@ -394,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); @@ -409,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; } @@ -437,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', @@ -458,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', @@ -479,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', @@ -500,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 @@ -675,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/includephp.html b/tests/template/templates/includephp.html index 117d4273f0..70ebdac0d0 100644 --- a/tests/template/templates/includephp.html +++ b/tests/template/templates/includephp.html @@ -1 +1 @@ -<!-- INCLUDEPHP ../templates/_dummy_include.php.inc --> +<!-- 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_connection_manager.php b/tests/test_framework/phpbb_database_test_connection_manager.php index 6c06857fbc..a7559e2183 100644 --- a/tests/test_framework/phpbb_database_test_connection_manager.php +++ b/tests/test_framework/phpbb_database_test_connection_manager.php @@ -123,7 +123,7 @@ class phpbb_database_test_connection_manager try { - $this->pdo->exec('DROP DATABASE ' . $config['dbname']); + $this->pdo->exec('DROP DATABASE ' . $this->config['dbname']); } catch (PDOException $e) { |