diff options
45 files changed, 422 insertions, 2224 deletions
diff --git a/.travis.yml b/.travis.yml index 5e2569dd22..1e5f453c76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,15 +5,16 @@ php: - 5.3 - 5.4 - 5.5 + - 5.6 env: - DB=mysql - - DB=postgres before_script: - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi" - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi" - - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi" + - sh -c "if [ '$DB' = 'mariadb' ]; then travis/setup-mariadb.sh; fi" + - sh -c "if [ '$DB' = 'mysql' -o '$DB' = 'mariadb' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi" - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.2' ]; then pear install --force phpunit/DbUnit; phpenv rehash; fi" - cd phpBB - sh -c "if [ '$TRAVIS_PHP_VERSION' != '5.2' ]; then php ../composer.phar install --dev --no-interaction --prefer-source; fi" @@ -22,10 +23,11 @@ before_script: script: - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.2' ]; then phpunit --configuration travis/phpunit-$DB-travis.xml; else phpBB/vendor/bin/phpunit --configuration travis/phpunit-$DB-travis.xml; fi" - -notifications: - email: - recipients: - - dev-team@phpbb.com - on_success: change - on_failure: change + - sh -c "if [ '$TRAVIS_PHP_VERSION' = '5.5' -a '$DB' = 'mysql' -a '$TRAVIS_PULL_REQUEST' != 'false' ]; then git-tools/commit-msg-hook-range.sh origin/$TRAVIS_BRANCH..FETCH_HEAD; fi" + +matrix: + include: + - php: 5.4 + env: DB=mariadb + - php: 5.4 + env: DB=postgres @@ -18,8 +18,8 @@ Find support and lots more on [phpBB.com](http://www.phpbb.com)! Discuss the dev ## AUTOMATED TESTING We have unit and functional tests in order to prevent regressions. You can view the bamboo continuous integration [here](http://bamboo.phpbb.com) or check our travis build below. -develop - [](http://travis-ci.org/phpbb/phpbb3) -develop-olympus - [](http://travis-ci.org/phpbb/phpbb3) +develop - [](http://travis-ci.org/phpbb/phpbb) +develop-olympus - [](http://travis-ci.org/phpbb/phpbb) ## LICENSE diff --git a/build/build.xml b/build/build.xml index d034c79731..83ddcd29c4 100644 --- a/build/build.xml +++ b/build/build.xml @@ -2,9 +2,9 @@ <project name="phpBB" description="The phpBB forum software" default="all" basedir="../"> <!-- a few settings for the build --> - <property name="newversion" value="3.0.12-RC3" /> - <property name="prevversion" value="3.0.11" /> - <property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.10, 3.0.12-RC1, 3.0.12-RC2" /> + <property name="newversion" value="3.0.13-dev" /> + <property name="prevversion" value="3.0.12" /> + <property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.10, 3.0.11" /> <!-- no configuration should be needed beyond this point --> <property name="oldversions" value="${olderversions}, ${prevversion}" /> @@ -105,7 +105,7 @@ <property name="dir" value="build/old_versions/release-${version}" /> </phingcall> - <exec dir="build/old_versions" command="diff -crNEBwd release-${version} release-${newversion} > + <exec dir="build/old_versions" command="LC_ALL=C diff -crNEBwd release-${version} release-${newversion} > ../new_version/patches/phpBB-${version}_to_${newversion}.patch" escape="false" /> </target> @@ -131,24 +131,52 @@ <target name="package" depends="clean,prepare,prepare-new-version,old-version-diffs"> <exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" /> - <exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" /> - <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/language new_version/phpBB3/language > - save/save_${prevversion}_to_${newversion}/language/phpbb-${prevversion}_to_${newversion}_language.patch" /> + save/phpbb-${prevversion}_to_${newversion}_language.patch" /> <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/styles/prosilver new_version/phpBB3/styles/prosilver > - save/save_${prevversion}_to_${newversion}/prosilver/phpbb-${prevversion}_to_${newversion}_prosilver.patch" /> + save/phpbb-${prevversion}_to_${newversion}_prosilver.patch" /> <exec dir="build" escape="false" command="diff -crNEBwd old_versions/release-${prevversion}/styles/subsilver2 new_version/phpBB3/styles/subsilver2 > - save/save_${prevversion}_to_${newversion}/subsilver2/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" /> + save/phpbb-${prevversion}_to_${newversion}_subsilver2.patch" /> <exec dir="build" escape="false" command="git shortlog --summary --numbered release-${prevversion}...HEAD > - save/save_${prevversion}_to_${newversion}/phpbb-${prevversion}_to_${newversion}_git_shortlog.txt" /> + save/phpbb-${prevversion}_to_${newversion}_git_shortlog.txt" /> <exec dir="build" escape="false" command="git diff --stat release-${prevversion}...HEAD > - save/save_${prevversion}_to_${newversion}/phpbb-${prevversion}_to_${newversion}_git_diffstat.txt" /> + save/phpbb-${prevversion}_to_${newversion}_git_diffstat.txt" /> + + <phingcall target="checksum-dir"> + <property name="dir" value="build/new_version/release_files" /> + </phingcall> + </target> + + <target name="checksum-dir"> + <foreach param="filename" absparam="absfilename" target="checksum-file"> + <fileset dir="${dir}"> + <type type="file" /> + </fileset> + </foreach> + </target> + + <target name="checksum-file"> + <echo msg="Creating checksum file for ${absfilename}" /> + <php function="dirname" returnProperty="dir"><param value="${absfilename}"/></php> + <exec dir="${dir}" command="sha256sum ${filename} > ${filename}.sha256" /> + </target> + + <target name="announcement" depends="prepare"> + <echo msg="Writing download links and checksums for email announcement to save/announcement_email_${newversion}.txt" /> + <exec dir="build" escape="false" + command="php -f build_announcement.php email '${newversion}' 'new_version/release_files' sha256 > + save/announcement_email_${newversion}.txt" /> + + <echo msg="Writing download links and checksums for bbcode announcement to save/announcement_bbcode_${newversion}.txt" /> + <exec dir="build" escape="false" + command="php -f build_announcement.php bbcode '${newversion}' 'new_version/release_files' sha256 > + save/announcement_bbcode_${newversion}.txt" /> </target> <target name="changelog" depends="prepare"> diff --git a/build/build_announcement.php b/build/build_announcement.php new file mode 100755 index 0000000000..3ee96fc67d --- /dev/null +++ b/build/build_announcement.php @@ -0,0 +1,98 @@ +#!/usr/bin/env php +<?php +/** +* +* @package build +* @copyright (c) 2013 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +if (php_sapi_name() !== 'cli' || $_SERVER['argc'] != 5) +{ + echo "Usage (CLI only): build_announcement.php email|bbcode new_version release_files_dir checksum_algorithm\n"; + exit(1); +} + +$mode = $_SERVER['argv'][1]; +$version = $_SERVER['argv'][2]; +$root = $_SERVER['argv'][3]; +$checksum_algorithm = $_SERVER['argv'][4]; + +$series_version = substr($version, 0, 3); +$base_url = "https://download.phpbb.com/pub/release/$series_version"; + +if (strpos($version, 'RC') === false) +{ + // Final release + $install_url = "$base_url/$version"; + $update_url = "$base_url/update/to_$version"; +} +else +{ + $install_url = "$base_url/release_candidates/$version"; + $update_url = "$base_url/release_candidates/update/other_to_$version"; +} + +if ($mode === 'bbcode') +{ + $template = "[url=%1\$s/%2\$s]%2\$s[/url]\n{$checksum_algorithm}sum: %3\$s\n"; +} +else +{ + $template = "%s/%s\n{$checksum_algorithm}sum: %s\n"; +} + +function phpbb_rnatsort($array) +{ + $strrnatcmp = function($a, $b) + { + return strnatcmp($b, $a); + }; + usort($array, $strrnatcmp); + return $array; +} + +function phpbb_string_ends_with($haystack, $needle) +{ + return substr($haystack, -strlen($needle)) === $needle; +} + +function phpbb_is_update_file($filename) +{ + return strpos($filename, '_to_') !== false; +} + +function phpbb_get_checksum($checksum_file) +{ + return array_shift(explode(' ', file_get_contents($checksum_file))); +} + +$install_files = $update_files = array(); +foreach (phpbb_rnatsort(array_diff(scandir($root), array('.', '..'))) as $filename) +{ + if (phpbb_string_ends_with($filename, $checksum_algorithm)) + { + continue; + } + else if (phpbb_is_update_file($filename)) + { + $update_files[] = $filename; + } + else + { + $install_files[] = $filename; + } +} + +foreach ($install_files as $filename) +{ + printf($template, $install_url, $filename, phpbb_get_checksum("$root/$filename.$checksum_algorithm")); +} + +echo "\n"; + +foreach ($update_files as $filename) +{ + printf($template, $update_url, $filename, phpbb_get_checksum("$root/$filename.$checksum_algorithm")); +} diff --git a/build/build_diff.php b/build/build_diff.php deleted file mode 100755 index 0824b53caa..0000000000 --- a/build/build_diff.php +++ /dev/null @@ -1,414 +0,0 @@ -#!/usr/bin/env php -<?php -/** -* -* @package build -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -if ($_SERVER['argc'] != 3) -{ - die("Please specify the previous and current version as arguments (e.g. build_diff.php '1.0.2' '1.0.3')."); -} - -$old_version = trim($_SERVER['argv'][1]); -$new_version = trim($_SERVER['argv'][2]); - -$substitute_old = $old_version; -$substitute_new = $new_version; -$simple_name_old = 'release-' . $old_version; -$simple_name_new = 'release-' . $new_version; -$echo_changes = false; - -// DO NOT EVER USE THE FOLLOWING! Fix the script to generate proper changes, -// do NOT manually create them. - -// Set this to true to just compress the changes and do not build them again -// This should be used for building custom modified txt file. ;) -$package_changed_files = false; - -//$debug_file = 'includes/functions_user.php'; //'styles/prosilver/style.cfg'; -$debug_file = false; - -if ($debug_file !== false) -{ - $echo_changes = false; -} - -$s_name = 'save_' . $substitute_old . '_to_' . $substitute_new; - -$location = dirname(__FILE__); - -if (!$package_changed_files) -{ - if (!$echo_changes) - { - // Create directory... - run_command("mkdir $location/save/{$s_name}"); - run_command("mkdir $location/save/{$s_name}/language"); - run_command("mkdir $location/save/{$s_name}/prosilver"); - run_command("mkdir $location/save/{$s_name}/subsilver2"); - } -} - -// Build code changes and place them into 'save' -if (!$package_changed_files) -{ - build_code_changes('language'); - build_code_changes('prosilver'); - build_code_changes('subsilver2'); -} - -// Package code changes -$code_changes_filename = 'phpBB-' . $substitute_old . '_to_' . $substitute_new . '-codechanges'; - -if (!$echo_changes) -{ - // Now compress the files... - // Build Main phpBB Release - $compress_programs = array( -// 'tar.gz' => 'tar -czf', - 'tar.bz2' => 'tar -cjf', - 'zip' => 'zip -r' - ); - - chdir($location . '/save/' . $s_name); - foreach ($compress_programs as $extension => $compress_command) - { - echo "Packaging code changes for $extension\n"; - run_command("rm ./../../new_version/release_files/{$code_changes_filename}.{$extension}"); - flush(); - - // Build Package - run_command("$compress_command ./../../new_version/release_files/{$code_changes_filename}.{$extension} *"); - - // Build MD5 Sum - run_command("md5sum ./../../new_version/release_files/{$code_changes_filename}.{$extension} > ./../../new_version/release_files/{$code_changes_filename}.{$extension}.md5"); - flush(); - } -} - -/** -* $output_format can be: language, prosilver and subsilver2 -*/ -function build_code_changes($output_format) -{ - global $substitute_new, $substitute_old, $simple_name_old, $simple_name_new, $echo_changes, $package_changed_files, $location, $debug_file, $s_name; - - // Global array holding the data entries - $data = array( - 'header' => array(), - 'diff' => array(), - ); - - // Read diff file and prepare the output filedata... - //$patch_filename = '../new_version/patches/phpBB-' . $substitute_old . '_to_' . $substitute_new . '.patch'; - $release_filename = 'phpbb-' . $substitute_old . '_to_' . $substitute_new . '_' . $output_format . '.txt'; - - if (!$package_changed_files) - { - if (!$echo_changes) - { - $fp = fopen('save/' . $s_name . '/' . $output_format . '/' . $release_filename, 'wb'); - - if (!$fp) - { - die('Unable to create ' . $release_filename); - } - } - } - - include_once($location . '/build_helper.php'); - $package = new build_package(array($substitute_old, $substitute_new), false); - - $titles = array( - 'language' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' Language Pack Changes', - 'prosilver' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' prosilver Changes', - 'subsilver2' => 'phpBB ' . $substitute_old . ' to phpBB ' . $substitute_new . ' subsilver2 Changes', - ); - - $data['header'] = array( - 'title' => $titles[$output_format], - 'intro' => ' - -These are the ' . $titles[$output_format] . ' summed up into a little Mod. These changes are only partial and do not include any code changes, therefore not meant for updating phpBB. - - ', - 'included_files' => array(), - ); - - // We collect the files we want to diff first (ironically we grab this from a diff file) - if (!$echo_changes) - { - echo "\n\nCollecting Filenames:"; - } - - // We re-create the patch file - foreach ($package->old_packages as $_package_name => $dest_package_filename) - { - chdir($package->locations['old_versions']); - - if (!$echo_changes) - { - echo "\n\n" . 'Creating patch/diff files for phpBB-' . $dest_package_filename . $package->get('new_version_number'); - } - - $dest_package_filename = $location . '/save/' . $s_name . '/phpBB-' . $dest_package_filename . $package->get('new_version_number') . '.patch'; - $package->run_command('diff ' . $package->diff_options . ' ' . $_package_name . ' ' . $package->get('simple_name') . ' > ' . $dest_package_filename); - - // Parse this diff to determine file changes from the checked versions and save them - $result = $package->collect_diff_files($dest_package_filename, $_package_name); - $package->run_command('rm ' . $dest_package_filename); - } - - chdir($location); - - $filenames = array(); - foreach ($result['files'] as $filename) - { - if ($debug_file !== false && $filename != $debug_file) - { - continue; - } - - // Decide which files to compare... - switch ($output_format) - { - case 'language': - if (strpos($filename, 'language/en/') !== 0) - { - continue 2; - } - break; - - case 'prosilver': - if (strpos($filename, 'styles/prosilver/') !== 0) - { - continue 2; - } - break; - - case 'subsilver2': - if (strpos($filename, 'styles/subsilver2/') !== 0) - { - continue 2; - } - break; - } - - if (!file_exists($location . '/old_versions/' . $simple_name_old . '/' . $filename)) - { - // New file... include it - $data['header']['included_files'][] = array( - 'old' => $location . '/old_versions/' . $simple_name_old . '/' . $filename, - 'new' => $location . '/old_versions/' . $simple_name_new . '/' . $filename, - 'phpbb_filename' => $filename, - ); - continue; - } - - $filenames[] = array( - 'old' => $location . '/old_versions/' . $simple_name_old . '/' . $filename, - 'new' => $location . '/old_versions/' . $simple_name_new . '/' . $filename, - 'phpbb_filename' => $filename, - ); - } - - // Now let us go through the filenames list and create a more comprehensive diff - if (!$echo_changes) - { - fwrite($fp, build_header($output_format, $filenames, $data['header'])); - } - else - { - //echo build_header('text', $filenames, $data['header']); - } - - // Copy files... - $files_to_copy = array(); - - foreach ($data['header']['included_files'] as $filename) - { - $files_to_copy[] = $filename['phpbb_filename']; - } - - // First step is to copy the new version over (clean structure) - if (!$echo_changes && sizeof($files_to_copy)) - { - foreach ($files_to_copy as $file) - { - // Create directory? - $dirname = dirname($file); - - if ($dirname) - { - $dirname = explode('/', $dirname); - $__dir = array(); - - foreach ($dirname as $i => $dir) - { - $__dir[] = $dir; - run_command("mkdir -p $location/save/" . $s_name . '/' . $output_format . '/' . implode('/', $__dir)); - } - } - - $source_file = $location . '/new_version/phpBB3/' . $file; - $dest_file = $location . '/save/' . $s_name . '/' . $output_format . '/'; - $dest_file .= $file; - - $command = "cp -p $source_file $dest_file"; - $result = trim(`$command`); - echo "- Copied File: " . $source_file . " -> " . $dest_file . "\n"; - } - } - - include_once('diff_class.php'); - - if (!$echo_changes) - { - echo "\n\nDiffing Codebases:"; - } - - foreach ($filenames as $file_ary) - { - if (!file_exists($file_ary['old'])) - { - $lines1 = array(); - } - else - { - $lines1 = file($file_ary['old']); - } - $lines2 = file($file_ary['new']); - - if (!sizeof($lines1)) - { - // New File - } - else - { - $diff = new Diff($lines1, $lines2); - $fmt = new BBCodeDiffFormatter(false, 5, $debug_file); - - if (!$echo_changes) - { - fwrite($fp, $fmt->format_open($file_ary['phpbb_filename'])); - fwrite($fp, $fmt->format($diff, $lines1)); - fwrite($fp, $fmt->format_close($file_ary['phpbb_filename'])); - } - else - { - echo $fmt->format_open($file_ary['phpbb_filename']); - echo $fmt->format($diff, $lines1); - echo $fmt->format_close($file_ary['phpbb_filename']); - } - - if ($debug_file !== false) - { - echo $fmt->format_open($file_ary['phpbb_filename']); - echo $fmt->format($diff, $lines1); - echo $fmt->format_close($file_ary['phpbb_filename']); - exit; - } - } - } - - if (!$echo_changes) - { - fwrite($fp, build_footer($output_format)); - - // Close file - fclose($fp); - - chmod('save/' . $s_name . '/' . $output_format . '/' . $release_filename, 0666); - } - else - { - echo build_footer($output_format); - } -} - -/** -* Build Footer -*/ -function build_footer($mode) -{ - $html = ''; - - $html .= "# \n"; - $html .= "#-----[ SAVE/CLOSE ALL FILES ]------------------------------------------ \n"; - $html .= "# \n"; - $html .= "# EoM"; - - return $html; -} - -/** -* Build Header -*/ -function build_header($mode, $filenames, $header) -{ - global $substitute_old; - - $html = ''; - - $html .= "############################################################## \n"; - $html .= "## Title: " . $header['title'] . "\n"; - $html .= "## Author: naderman < naderman@phpbb.com > (Nils Adermann) http://www.phpbb.com \n"; - $html .= "## Description: \n"; - - $intr = explode("\n", $header['intro']); - $introduction = ''; - foreach ($intr as $_line) - { - $introduction .= wordwrap($_line, 80) . "\n"; - } - $intr = explode("\n", $introduction); - - foreach ($intr as $_line) - { - $html .= "## " . $_line . "\n"; - } - $html .= "## \n"; - $html .= "## Files To Edit: \n"; - - foreach ($filenames as $file_ary) - { - $html .= "## " . $file_ary['phpbb_filename'] . "\n"; - } - $html .= "##\n"; - if (sizeof($header['included_files'])) - { - $html .= "## Included Files: \n"; - foreach ($header['included_files'] as $filename) - { - $html .= "## {$filename['phpbb_filename']}\n"; - } - } - $html .= "## License: http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 \n"; - $html .= "############################################################## \n"; - $html .= "\n"; - - // COPY Statement? - if (sizeof($header['included_files'])) - { - $html .= "#\n#-----[ COPY ]------------------------------------------\n#\n"; - foreach ($header['included_files'] as $filename) - { - $html .= "copy {$filename['phpbb_filename']} to {$filename['phpbb_filename']}\n"; - } - $html .= "\n"; - } - - return $html; -} - -function run_command($command) -{ - $result = trim(`$command`); - echo "\n- Command Run: " . $command . "\n"; -} - -?> diff --git a/build/diff_class.php b/build/diff_class.php deleted file mode 100644 index 2d8555400d..0000000000 --- a/build/diff_class.php +++ /dev/null @@ -1,1710 +0,0 @@ -<?php -/** -* -* @package build -* @copyright (c) 2000 Geoffrey T. Dairiki <dairiki@dairiki.org> -* @copyright (c) 2010 phpBB Group -* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 -* -*/ - -/** -* Class used internally by WikiDiff to actually compute the diffs. -* -* The algorithm used here is mostly lifted from the perl module -* Algorithm::Diff (version 1.06) by Ned Konz, which is available at: -* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip -* -* More ideas are taken from: -* http://www.ics.uci.edu/~eppstein/161/960229.html -* -* Some ideas are (and a bit of code) are from from analyze.c, from GNU -* diffutils-2.7, which can be found at: -* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz -* -* Finally, some ideas (subdivision by NCHUNKS > 2, and some optimizations) -* are my own. -*/ -class _WikiDiffEngine -{ - var $edits; // List of editing operation to convert XV to YV. - var $xv = array(), $yv = array(); - - function _WikiDiffEngine($from_lines, $to_lines) - { - $n_from = sizeof($from_lines); - $n_to = sizeof($to_lines); - - $endskip = 0; - // Ignore trailing and leading matching lines. - while ($n_from > 0 && $n_to > 0) - { - if ($from_lines[$n_from - 1] != $to_lines[$n_to - 1]) - { - break; - } - - $n_from--; - $n_to--; - $endskip++; - } - - for ($skip = 0; $skip < min($n_from, $n_to); $skip++) - { - if ($from_lines[$skip] != $to_lines[$skip]) - { - break; - } - } - $n_from -= $skip; - $n_to -= $skip; - - $xlines = array(); - $ylines = array(); - - // Ignore lines which do not exist in both files. - for ($x = 0; $x < $n_from; $x++) - { - $xhash[$from_lines[$x + $skip]] = 1; - } - - for ($y = 0; $y < $n_to; $y++) - { - $line = $to_lines[$y + $skip]; - $ylines[] = $line; - - if (($this->ychanged[$y] = empty($xhash[$line]))) - { - continue; - } - $yhash[$line] = 1; - $this->yv[] = $line; - $this->yind[] = $y; - } - - for ($x = 0; $x < $n_from; $x++) - { - $line = $from_lines[$x + $skip]; - $xlines[] = $line; - - if (($this->xchanged[$x] = empty($yhash[$line]))) - { - continue; // fixme? what happens to yhash/xhash when - // there are two identical lines?? - } - $this->xv[] = $line; - $this->xind[] = $x; - } - - // Find the LCS. - $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); - - // Merge edits when possible - $this->_shift_boundaries($xlines, $this->xchanged, $this->ychanged); - $this->_shift_boundaries($ylines, $this->ychanged, $this->xchanged); - - // Compute the edit operations. - $this->edits = array(); - - if ($skip) - { - $this->edits[] = $skip; - } - - $x = 0; - $y = 0; - - while ($x < $n_from || $y < $n_to) - { - // Skip matching "snake". - $x0 = $x; - $ncopy = 0; - while ($x < $n_from && $y < $n_to && !$this->xchanged[$x] && !$this->ychanged[$y]) - { - ++$x; - ++$y; - ++$ncopy; - } - - if ($x > $x0) - { - $this->edits[] = $x - $x0; - } - - // Find deletes. - $x0 = $x; - $ndelete = 0; - - while ($x < $n_from && $this->xchanged[$x]) - { - ++$x; - ++$ndelete; - } - - if ($x > $x0) - { - $this->edits[] = -($x - $x0); - } - - // Find adds. - if (isset($this->ychanged[$y]) && $this->ychanged[$y]) - { - $adds = array(); - while ($y < $n_to && $this->ychanged[$y]) - { - $adds[] = $ylines[$y++]; - } - $this->edits[] = $adds; - } - } - - if (!empty($endskip)) - { - $this->edits[] = $endskip; - } - } - - /* Divide the Largest Common Subsequence (LCS) of the sequences - * [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally - * sized segments. - * - * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an - * array of NCHUNKS+1 (X, Y) indexes giving the diving points between - * sub sequences. The first sub-sequence is contained in [X0, X1), - * [Y0, Y1), the second in [X1, X2), [Y1, Y2) and so on. Note - * that (X0, Y0) == (XOFF, YOFF) and - * (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). - * - * This function assumes that the first lines of the specified portions - * of the two files do not match, and likewise that the last lines do not - * match. The caller must trim matching lines from the beginning and end - * of the portions it is going to specify. - */ - function _diag ($xoff, $xlim, $yoff, $ylim, $nchunks) - { - $flip = false; - - if ($xlim - $xoff > $ylim - $yoff) - { - // Things seems faster (I'm not sure I understand why) - // when the shortest sequence in X. - $flip = true; - list ($xoff, $xlim, $yoff, $ylim) = array( $yoff, $ylim, $xoff, $xlim); - } - - if ($flip) - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->xv[$i]][] = $i; - } - } - else - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->yv[$i]][] = $i; - } - } - - $this->lcs = 0; - $this->seq[0]= $yoff - 1; - $this->in_seq = array(); - $ymids[0] = array(); - - $numer = $xlim - $xoff + $nchunks - 1; - $x = $xoff; - - for ($chunk = 0; $chunk < $nchunks; $chunk++) - { - if ($chunk > 0) - { - for ($i = 0; $i <= $this->lcs; $i++) - { - $ymids[$i][$chunk-1] = $this->seq[$i]; - } - } - - $x1 = $xoff + (int)(($numer + ($xlim-$xoff)*$chunk) / $nchunks); - - for ( ; $x < $x1; $x++) - { - $_index = $flip ? $this->yv[$x] : $this->xv[$x]; - $matches = (isset($ymatches[$_index])) ? $ymatches[$_index] : array(); - - if (!$matches) - { - continue; - } - reset($matches); - - while (list ($junk, $y) = each($matches)) - { - if (!isset($this->in_seq[$y]) || !$this->in_seq[$y]) - { - $k = $this->_lcs_pos($y); - //if (!$k) die('assertion "!$k" failed'); - $ymids[$k] = $ymids[$k-1]; - break; - } - } - - while (list ($junk, $y) = each($matches)) - { - if ($y > $this->seq[$k-1]) - { - //if ($y >= $this->seq[$k]) die('assertion failed'); - // Optimization: this is a common case: - // next match is just replacing previous match. - $this->in_seq[$this->seq[$k]] = false; - $this->seq[$k] = $y; - $this->in_seq[$y] = 1; - } - else if (!isset($this->in_seq[$y]) || !$this->in_seq[$y]) - { - $k = $this->_lcs_pos($y); - //if (!$k) die('assertion "!$k" failed'); - $ymids[$k] = $ymids[$k-1]; - } - } - } - } - - $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); - $ymid = $ymids[$this->lcs]; - - for ($n = 0; $n < $nchunks - 1; $n++) - { - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); - $y1 = $ymid[$n] + 1; - $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); - } - $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); - - return array($this->lcs, $seps); - } - - function _lcs_pos ($ypos) - { - $end = $this->lcs; - if ($end == 0 || $ypos > $this->seq[$end]) - { - $this->seq[++$this->lcs] = $ypos; - $this->in_seq[$ypos] = 1; - return $this->lcs; - } - - $beg = 1; - while ($beg < $end) - { - $mid = (int)(($beg + $end) / 2); - - if ($ypos > $this->seq[$mid]) - { - $beg = $mid + 1; - } - else - { - $end = $mid; - } - } - - //if ($ypos == $this->seq[$end]) die("assertion failure"); - - $this->in_seq[$this->seq[$end]] = false; - $this->seq[$end] = $ypos; - $this->in_seq[$ypos] = 1; - return $end; - } - - /* Find LCS of two sequences. - * - * The results are recorded in the vectors $this->{x,y}changed[], by - * storing a 1 in the element for each line that is an insertion - * or deletion (ie. is not in the LCS). - * - * The subsequence of file 0 is [XOFF, XLIM) and likewise for file 1. - * - * Note that XLIM, YLIM are exclusive bounds. - * All line numbers are origin-0 and discarded lines are not counted. - */ - function _compareseq ($xoff, $xlim, $yoff, $ylim) - { - // Slide down the bottom initial diagonal. - while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff]) - { - ++$xoff; - ++$yoff; - } - - // Slide up the top initial diagonal. - while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) - { - --$xlim; - --$ylim; - } - - if ($xoff == $xlim || $yoff == $ylim) - { - $lcs = 0; - } - else - { - // This is ad hoc but seems to work well. - //$nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); - //$nchunks = max(2,min(8,(int)$nchunks)); - $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; - list ($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); - } - - if ($lcs == 0) - { - // X and Y sequences have no common subsequence: - // mark all changed. - while ($yoff < $ylim) - { - $this->ychanged[$this->yind[$yoff++]] = 1; - } - - while ($xoff < $xlim) - { - $this->xchanged[$this->xind[$xoff++]] = 1; - } - } - else - { - // Use the partitions to split this problem into subproblems. - reset($seps); - - $pt1 = $seps[0]; - - while ($pt2 = next($seps)) - { - $this->_compareseq ($pt1[0], $pt2[0], $pt1[1], $pt2[1]); - $pt1 = $pt2; - } - } - } - - /* Adjust inserts/deletes of identical lines to join changes - * as much as possible. - * - * We do something when a run of changed lines include a - * line at one end and have an excluded, identical line at the other. - * We are free to choose which identical line is included. - * `compareseq' usually chooses the one at the beginning, - * but usually it is cleaner to consider the following identical line - * to be the "change". - * - * This is extracted verbatim from analyze.c (GNU diffutils-2.7). - */ - function _shift_boundaries ($lines, &$changed, $other_changed) - { - $i = 0; - $j = 0; - $len = sizeof($lines); - - while (1) - { - /* - * Scan forwards to find beginning of another run of changes. - * Also keep track of the corresponding point in the other file. - */ - - while ($i < $len && $changed[$i] == 0) - { - while ($other_changed[$j++]) - { - continue; - } - $i++; - } - - if ($i == $len) - { - break; - } - - $start = $i; - - // Find the end of this run of changes. - while (isset($changed[++$i])) - { - continue; - } - - while (isset($other_changed[$j]) && $other_changed[$j]) - { - $j++; - } - - do - { - /* - * Record the length of this run of changes, so that - * we can later determine whether the run has grown. - */ - $runlength = $i - $start; - - /* - * Move the changed region back, so long as the - * previous unchanged line matches the last changed one. - * This merges with previous changed regions. - */ - while ($start && $lines[$start - 1] == $lines[$i - 1]) - { - $changed[--$start] = 1; - $changed[--$i] = false; - - while ($changed[$start - 1]) - { - $start--; - } - - while ($other_changed[--$j]) - { - continue; - } - } - - /* - * Set CORRESPONDING to the end of the changed run, at the last - * point where it corresponds to a changed run in the other file. - * CORRESPONDING == LEN means no such point has been found. - */ - $corresponding = empty($other_changed[$j - 1]) ? $len : $i; - - /* - * Move the changed region forward, so long as the - * first changed line matches the following unchanged one. - * This merges with following changed regions. - * Do this second, so that if there are no merges, - * the changed region is moved forward as far as possible. - */ - while ($i != $len && $lines[$start] == $lines[$i]) - { - $changed[$start++] = false; - $changed[$i++] = 1; - - while ($changed[$i]) - { - $i++; - } - - while ($other_changed[++$j]) - { - $corresponding = $i; - } - } - } while ($runlength != $i - $start); - - /* - * If possible, move the fully-merged run of changes - * back to a corresponding run in the other file. - */ - while ($corresponding < $i) - { - $changed[--$start] = 1; - $changed[--$i] = 0; - - while ($other_changed[--$j]) - { - continue; - } - } - } - } -} - -/** -* Class representing a diff between two files. -*/ -class Diff -{ - var $edits; - - /** - * Compute diff between files (or deserialize serialized WikiDiff.) - */ - function Diff($from_lines = false, $to_lines = false) - { - if ($from_lines && $to_lines) - { - $compute = new _WikiDiffEngine($from_lines, $to_lines); - $this->edits = $compute->edits; - } - else if ($from_lines) - { - // $from_lines is not really from_lines, but rather - // a serialized Diff. - $this->edits = unserialize($from_lines); - } - else - { - $this->edits = array(); - } - } - - /** - * Compute reversed Diff. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * $rev = $diff->reverse($lines1); - * - * // reconstruct $lines1 from $lines2: - * $out = $rev->apply($lines2); - */ - function reverse ($from_lines) - { - $x = 0; - $rev = new Diff; - - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (is_array($edit)) - { // Was an add, turn it into a delete. - $nadd = sizeof($edit); - if ($nadd == 0) - { - die("assertion error"); - } - $edit = -$nadd; - } - else if ($edit > 0) - { - // Was a copy --- just pass it through. } - $x += $edit; - } - else if ($edit < 0) - { // Was a delete, turn it into an add. - $ndelete = -$edit; - $edit = array(); - - while ($ndelete-- > 0) - { - $edit[] = $from_lines[$x++]; - } - } - else - { - die("assertion error"); - } - - $rev->edits[] = $edit; - } - - return $rev; - } - - /** - * Compose (concatenate) Diffs. - * - * SYNOPSIS: - * - * $diff1 = new Diff($lines1, $lines2); - * $diff2 = new Diff($lines2, $lines3); - * $comp = $diff1->compose($diff2); - * - * // reconstruct $lines3 from $lines1: - * $out = $comp->apply($lines1); - */ - function compose ($that) - { - reset($this->edits); - reset($that->edits); - - $comp = new Diff; - $left = current($this->edits); - $right = current($that->edits); - - while ($left || $right) - { - if (!is_array($left) && $left < 0) - { // Left op is a delete. - $newop = $left; - $left = next($this->edits); - } - else if (is_array($right)) - { // Right op is an add. - $newop = $right; - $right = next($that->edits); - } - else if (!$left || !$right) - { - die ("assertion error"); - } - else if (!is_array($left) && $left > 0) - { // Left op is a copy. - if ($left <= abs($right)) - { - $newop = $right > 0 ? $left : -$left; - $right -= $newop; - - if ($right == 0) - { - $right = next($that->edits); - } - $left = next($this->edits); - } - else - { - $newop = $right; - $left -= abs($right); - $right = next($that->edits); - } - } - else - { // Left op is an add. - if (!is_array($left)) - { - die('assertion error'); - } - $nleft = sizeof($left); - - if ($nleft <= abs($right)) - { - if ($right > 0) - { // Right op is copy - $newop = $left; - $right -= $nleft; - } - else // Right op is delete - { - $newop = false; - $right += $nleft; - } - - if ($right == 0) - { - $right = next($that->edits); - } - $left = next($this->edits); - } - else - { - unset($newop); - - if ($right > 0) - { - for ($i = 0; $i < $right; $i++) - { - $newop[] = $left[$i]; - } - } - - $tmp = array(); - for ($i = abs($right); $i < $nleft; $i++) - { - $tmp[] = $left[$i]; - } - $left = $tmp; - $right = next($that->edits); - } - } - - if (!$op) - { - $op = $newop; - continue; - } - - if (!$newop) - { - continue; - } - - if (is_array($op) && is_array($newop)) - { - // Both $op and $newop are adds. - for ($i = 0; $i < sizeof($newop); $i++) - { - $op[] = $newop[$i]; - } - } - else if (($op > 0 && $newop > 0) || ($op < 0 && $newop < 0)) - { // $op and $newop are both either deletes or copies. - $op += $newop; - } - else - { - $comp->edits[] = $op; - $op = $newop; - } - } - - if ($op) - { - $comp->edits[] = $op; - } - - return $comp; - } - - /* Debugging only: - function _dump () - { - echo "<ol>"; - for (reset($this->edits); - { - $edit = current($this->edits); - } - next($this->edits)) - { - echo "<li>"; - if ($edit > 0) - echo "Copy $edit"; - else if ($edit < 0) - echo "Delete " . -$edit; - else if (is_array($edit)) - { - echo "Add " . sizeof($edit) . "<ul>"; - for ($i = 0; $i < sizeof($edit); $i++) - echo "<li>" . htmlspecialchars($edit[$i]); - echo "</ul>"; - } - else - die("assertion error"); - } - echo "</ol>"; - } - */ - - /** - * Apply a Diff to a set of lines. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * - * // reconstruct $lines2 from $lines1: - * $out = $diff->apply($lines1); - */ - function apply ($from_lines) - { - $x = 0; - $xlim = sizeof($from_lines); - - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (is_array($edit)) - { - reset($edit); - while (list ($junk, $line) = each($edit)) - { - $output[] = $line; - } - } - else if ($edit > 0) - { - while ($edit--) - { - $output[] = $from_lines[$x++]; - } - } - else - { - $x += -$edit; - } - } - - if ($x != $xlim) - { - die(sprintf("Diff::apply: line count mismatch: %s != %s", $x, $xlim)); - } - - return $output; - } - - /** - * Serialize a Diff. - * - * SYNOPSIS: - * - * $diff = new Diff($lines1, $lines2); - * $string = $diff->serialize; - * - * // recover Diff from serialized version: - * $diff2 = new Diff($string); - */ - function serialize () - { - return serialize($this->edits); - } - - /** - * Return true if two files were equal. - */ - function isEmpty() - { - if (sizeof($this->edits) > 1) - { - return false; - } - - if (sizeof($this->edits) == 0) - { - return true; - } - - // Test for: only edit is a copy. - return !is_array($this->edits[0]) && $this->edits[0] > 0; - } - - /** - * Compute the length of the Longest Common Subsequence (LCS). - * - * This is mostly for diagnostic purposed. - */ - function lcs() - { - $lcs = 0; - for (reset($this->edits); $edit = current($this->edits); next($this->edits)) - { - if (!is_array($edit) && $edit > 0) - { - $lcs += $edit; - } - } - - return $lcs; - } - - /** - * Check a Diff for validity. - * - * This is here only for debugging purposes. - */ - function _check ($from_lines, $to_lines) - { - $test = $this->apply($from_lines); - if (serialize($test) != serialize($to_lines)) - { - die("Diff::_check: failed"); - } - - reset($this->edits); - $prev = current($this->edits); - $prevtype = is_array($prev) ? 'a' : ($prev > 0 ? 'c' : 'd'); - - while ($edit = next($this->edits)) - { - $type = is_array($edit) ? 'a' : ($edit > 0 ? 'c' : 'd'); - if ($prevtype == $type) - { - die("Diff::_check: edit sequence is non-optimal"); - } - $prevtype = $type; - } - $lcs = $this->lcs(); - echo "<strong>Diff Okay: LCS = $lcs</strong>\n"; - } -} - -/** -* A class to format a Diff as HTML. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new DiffFormatter; -* echo $fmt->format($diff, $lines1); // Output HTMLified standard diff. -* -* or to output reverse diff (diff's that would take $lines2 to $lines1): -* -* $fmt = new DiffFormatter(true); -* echo $fmt->format($diff, $lines1); -*/ -class DiffFormatter -{ - var $context_lines; - var $do_reverse_diff; - var $context_prefix, $deletes_prefix, $adds_prefix; - - function DiffFormatter ($reverse = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = 0; - $this->context_prefix = ' '; - $this->deletes_prefix = '< '; - $this->adds_prefix = '> '; - } - - function format ($diff, $from_lines) - { - $html = '<table width="100%" bgcolor="black" cellspacing=2 cellpadding=2 border=0>' . "\n"; - $html .= $this->_format($diff->edits, $from_lines); - $html .= "</table>\n"; - - return $html; - } - - function _format ($edits, $from_lines) - { - $html = ''; - $x = 0; $y = 0; - $xlim = sizeof($from_lines); - - reset($edits); - while ($edit = current($edits)) - { - if (!is_array($edit) && $edit >= 0) - { // Edit op is a copy. - $ncopy = $edit; - } - else - { - $ncopy = 0; - - if (empty($hunk)) - { - // Start of an output hunk. - $xoff = max(0, $x - $this->context_lines); - $yoff = $xoff + $y - $x; - - if ($xoff < $x) - { - // Get leading context. - $context = array(); - - for ($i = $xoff; $i < $x; $i++) - { - $context[] = $from_lines[$i]; - } - $hunk['c'] = $context; - } - } - - if (is_array($edit)) - { - // Edit op is an add. - $y += sizeof($edit); - $hunk[$this->do_reverse_diff ? 'd' : 'a'] = $edit; - } - else - { - // Edit op is a delete - $deletes = array(); - - while ($edit++ < 0) - { - $deletes[] = $from_lines[$x++]; - } - - $hunk[$this->do_reverse_diff ? 'a' : 'd'] = $deletes; - } - } - - $next = next($edits); - - if (!empty($hunk)) - { - // Originally $ncopy > 2 * $this->context_lines, but we need to split as early as we can for creating MOD Text Templates. ;) - if (!$next || $ncopy > $this->context_lines) - { - // End of an output hunk. - $hunks[] = $hunk; - unset($hunk); - - $xend = min($x + $this->context_lines, $xlim); - - if ($x < $xend) - { - // Get trailing context. - $context = array(); - for ($i = $x; $i < $xend; $i++) - { - $context[] = $from_lines[$i]; - } - $hunks[] = array('c' => $context); - } - - $xlen = $xend - $xoff; - $ylen = $xend + $y - $x - $yoff; - $xbeg = $xlen ? $xoff + 1 : $xoff; - $ybeg = $ylen ? $yoff + 1 : $yoff; - - if ($this->do_reverse_diff) - { - list ($xbeg, $xlen, $ybeg, $ylen) = array($ybeg, $ylen, $xbeg, $xlen); - } - - $html .= $this->_emit_diff($xbeg, $xlen, $ybeg, $ylen, $hunks); - unset($hunks); - } - else if ($ncopy) - { - $hunks[] = $hunk; - - // Copy context. - $context = array(); - for ($i = $x; $i < $x + $ncopy; $i++) - { - $context[] = $from_lines[$i]; - } - $hunk = array('c' => $context); - } - } - - $x += $ncopy; - $y += $ncopy; - } - - return $html; - } - - function _emit_lines($lines, $prefix, $color) - { - $html = ''; - reset($lines); - while (list ($junk, $line) = each($lines)) - { - $html .= "<tr bgcolor=\"$color\"><td><tt>$prefix</tt>"; - $html .= "<tt>" . htmlspecialchars($line) . "</tt></td></tr>\n"; - } - return $html; - } - - function _emit_diff ($xbeg,$xlen,$ybeg,$ylen,$hunks) - { - // Save hunk... - $this->diff_hunks[] = $hunks; - - $html = '<tr><td><table width="100%" bgcolor="white" cellspacing="0" border="0" cellpadding="4"> - <tr bgcolor="#cccccc"><td><tt>' . - $this->_diff_header($xbeg, $xlen, $ybeg, $ylen) . ' - </tt></td></tr>\n<tr><td> - <table width="100%" cellspacing="0" border="0" cellpadding="2"> - '; - - $prefix = array('c' => $this->context_prefix, 'a' => $this->adds_prefix, 'd' => $this->deletes_prefix); - $color = array('c' => '#ffffff', 'a' => '#ffcccc', 'd' => '#ccffcc'); - - for (reset($hunks); $hunk = current($hunks); next($hunks)) - { - if (!empty($hunk['c'])) - { - $html .= $this->_emit_lines($hunk['c'], $this->context_prefix, '#ffffff'); - } - - if (!empty($hunk['d'])) - { - $html .= $this->_emit_lines($hunk['d'], $this->deletes_prefix, '#ccffcc'); - } - - if (!empty($hunk['a'])) - { - $html .= $this->_emit_lines($hunk['a'], $this->adds_prefix, '#ffcccc'); - } - } - - $html .= "</table></td></tr></table></td></tr>\n"; - return $html; - } - - function _diff_header ($xbeg,$xlen,$ybeg,$ylen) - { - $what = $xlen ? ($ylen ? 'c' : 'd') : 'a'; - $xlen = $xlen > 1 ? "," . ($xbeg + $xlen - 1) : ''; - $ylen = $ylen > 1 ? "," . ($ybeg + $ylen - 1) : ''; - - return "$xbeg$xlen$what$ybeg$ylen"; - } -} - -/** -* A class to format a Diff as a pretty HTML unified diff. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new UnifiedDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output HTMLified unified diff. -*/ -class UnifiedDiffFormatter extends DiffFormatter -{ - function UnifiedDiffFormatter ($reverse = false, $context_lines = 3) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - } - - function _diff_header ($xbeg,$xlen,$ybeg,$ylen) - { - $xlen = $xlen == 1 ? '' : ",$xlen"; - $ylen = $ylen == 1 ? '' : ",$ylen"; - - return "@@ -$xbeg$xlen +$ybeg$ylen @@"; - } -} - -/** -* A class to format a Diff as MOD Template instuctions. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new BBCodeDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output MOD Actions. -*/ -class BBCodeDiffFormatter extends DiffFormatter -{ - function BBCodeDiffFormatter ($reverse = false, $context_lines = 3, $debug = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - $this->debug = $debug; - } - - function format ($diff, $from_lines) - { - $html = $this->_format($diff->edits, $from_lines); - - return $html; - } - - function skip_lines(&$order_array, &$ordering) - { - if (sizeof($order_array['find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - if (isset($order_array['first_find_c'][0]) && - is_array($order_array['first_find_c'][0]) && - trim(implode('', $order_array['first_find_c'][0])) != '' && - isset($order_array['replace'])) - { - $order_array['add'] = $order_array['replace']; - unset($order_array['replace']); - // this is actually an after add - } - else - { - return true; - } - } - } - - if (isset($order_array['add']) && sizeof($order_array['add'])) - { - $text = implode('', $order_array['add']); - if ($text === "\n" || $text === "\t" || $text === '') - { - return true; - } - } - - if (isset($order_array['replace']) && sizeof($order_array['replace'])) - { - $text = implode('', $order_array['replace']); - if ($text === "\n" || $text === "\t" || $text === '') - { - return true; - } - } - } - - function _emit_lines_bb($ybeg, &$ordering) - { - $html = ''; - - // Now adjust for bbcode display... - foreach ($ordering as $order_array) - { - // Skip useless empty lines... - if ($this->skip_lines($order_array, $ordering)) - { - continue; - } - - // Only include double-finds if the last find has very few code location indications... - if (isset($order_array['first_find_c']) && sizeof($order_array['first_find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - // no real find, use first_find_c if possible! - //var_dump($order_array); - if (is_array($order_array['first_find_c'][0])) - { - $order_array['find_c'] = $order_array['first_find_c'][0]; - } - else - { - if (isset($order_array['replace']) || isset($order_array['add']) || isset($order_array['delete'])) - { - echo "skipped an edit!\n"; - var_dump($order_array); - } - continue; - } - } - else - { - if (strlen(implode('', $order_array['find_c'])) < 50 && is_array($order_array['first_find_c'][0])) - { - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['first_find_c'][0]); - $html .= "\n"; - $ybeg += sizeof($order_array['first_find_c'][0]); - } - } - } - - // still here but nothing to do? what the heck? - if (!isset($order_array['replace']) && !isset($order_array['add']) && !isset($order_array['delete'])) - { - echo "skipped an edit!\n"; - var_dump($order_array); - continue; - } - - if (sizeof($order_array['find_c'])) - { - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['find_c']); - $html .= "\n"; - } - - if (isset($order_array['replace'])) - { - $html .= "#\n#-----[ REPLACE WITH ]---------------------------------------------\n#\n"; - $html .= implode("", $order_array['replace']); - $html .= "\n"; - } - - if (isset($order_array['add'])) - { - $html .= "#\n#-----[ AFTER, ADD ]---------------------------------------------\n#\n"; - $html .= implode("", $order_array['add']); - $html .= "\n"; - } - - // There is no DELETE. :o - // Let's try to adjust it then... - if (isset($order_array['delete'])) - { - $text = implode('', $order_array['delete']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - $ybeg += sizeof($order_array['find_c']); - - $html .= "#\n#-----[ FIND ]---------------------------------------------\n# Around Line {$ybeg}\n"; - $html .= implode("", $order_array['delete']); - $html .= "\n"; - - $html .= "#\n#-----[ REPLACE WITH ]---------------------------------------------\n# Just remove/delete the lines (replacing with an empty line)\n"; - $html .= "\n"; - $html .= "\n"; - } - } - - return $html; - } - - function format_open($filename) - { - $html = ''; - $html .= "#\n#-----[ OPEN ]--------------------------------------------- \n#\n{$filename}\n\n"; - - return $html; - } - - function format_close($filename) - { - return ''; - } - - function _emit_diff ($xbeg, $xlen, $ybeg, $ylen, $hunks) - { - - // Go through the hunks to determine which method we are using (AFTER, ADD; REPLACE WITH or DELETE) - - // Remove the header... - if (sizeof($hunks) <= 2 && !isset($hunks[1]['a']) && !isset($hunks[1]['d'])) - { - $reorder = false; - $orig_hunks = $hunks; - - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['a']) && isset($hunk['d'])) - { - /**/ if (sizeof($hunk['a']) == 1 && sizeof($hunk['d']) == 1) - { - if (preg_match('/\* @version \$Id:.+\$$/', $hunk['a'][0]) && preg_match('/\* @version \$Id:.+\$$/', $hunk['d'][0])) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - }/**/ - - // Compare the add and replace one... - $string_1 = rtrim(trim(implode('', $hunk['a']))); - $string_2 = rtrim(trim(implode('', $hunk['d']))); - - if (strcmp($string_1, $string_2) === 0) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - } - } - - if ($reorder) - { - // Now check if we have no more 'a' and 'd's - $hunks = array_merge($hunks, array()); - } - } - else - { - $reorder = false; - $orig_hunks = $hunks; - - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['a']) && isset($hunk['d'])) - { - /**/ if (sizeof($hunk['a']) == 1 && sizeof($hunk['d']) == 1) - { - if (preg_match('/\* @version \$Id:.+\$$/', $hunk['a'][0]) && preg_match('/\* @version \$Id:.+\$$/', $hunk['d'][0])) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - }/**/ - - // Compare the add and replace one... - $string_1 = rtrim(trim(implode('', $hunk['a']))); - $string_2 = rtrim(trim(implode('', $hunk['d']))); - - if (strcmp($string_1, $string_2) === 0) - { - // Only remove this sole hunk... - unset($hunks[$key]); - $reorder = true; - continue; - } - } - } - - if ($reorder) - { - $hunks = array_merge($hunks, array()); - - if (sizeof($hunks) == 1 && sizeof($hunks[0]) == 1 && isset($hunks[0]['c'])) - { - return; - } - else - { - $hunks = $orig_hunks; - } - } - } - - if (sizeof($hunks) == 1 && sizeof($hunks[0]) == 1 && isset($hunks[0]['c'])) - { - return; - } - - $replace = false; - foreach ($hunks as $key => $hunk) - { - if (isset($hunk['d']) && isset($hunk['a'])) - { - $replace = true; - break; - } - } - - $ordering = array(); - $cur_pos = 0; - - // Replace-block - if ($replace) - { - foreach ($hunks as $hunk) - { - if (!isset($hunk['a']) && !isset($hunk['d'])) - { - continue; - } - - if (!empty($hunk['c'])) - { - if (!isset($ordering[$cur_pos]['find_c'])) - { - $ordering[$cur_pos]['find_c'] = $hunk['c']; - } - else - { - $ordering[$cur_pos]['end_c'] = $hunk['c']; - } - } - - // Make sure we begin fresh... - if (!isset($ordering[$cur_pos]['replace'])) - { - $ordering[$cur_pos]['first_find_c'][] = $ordering[$cur_pos]['find_c']; - $ordering[$cur_pos]['find_c'] = array(); - $ordering[$cur_pos]['replace'] = array(); - } - - // Add the middle part if one exist... - if (isset($ordering[$cur_pos]['end_c'])) - { - $ordering[$cur_pos]['find_c'] = array_merge($ordering[$cur_pos]['find_c'], $ordering[$cur_pos]['end_c']); - $ordering[$cur_pos]['replace'] = array_merge($ordering[$cur_pos]['replace'], $ordering[$cur_pos]['end_c']); - unset($ordering[$cur_pos]['end_c']); - } - - if (isset($hunk['d'])) - { - $ordering[$cur_pos]['find_c'] = array_merge($ordering[$cur_pos]['find_c'], $hunk['d']); - } - - if (isset($hunk['a'])) - { - $ordering[$cur_pos]['replace'] = array_merge($ordering[$cur_pos]['replace'], $hunk['a']); - } - } - } - else - { - foreach ($hunks as $hunk) - { - if (!empty($hunk['c'])) - { - if (!isset($ordering[$cur_pos]['find_c'])) - { - $ordering[$cur_pos]['find_c'] = $hunk['c']; - } - else - { - $ordering[$cur_pos]['end_c'] = $hunk['c']; - } - } - - if (!empty($hunk['a'])) - { - if (isset($ordering[$cur_pos]['delete'])) - { - // If ordering is set with an delete entry, we will actually begin a new ordering array (to seperate delete from add) - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; - } - else - { - if (isset($ordering[$cur_pos]['add'])) - { - // Now, we really need to be quite careful here... - if (isset($ordering[$cur_pos]['end_c']) && isset($hunk['c']) && isset($hunk['a']) && sizeof($hunk) == 2) - { - // There is a new find/add entry we did not catch... let's try to add a new entry then... but first check the hunk[a] contents... - $text = trim(implode("\n", $hunk['c'])); - if ($text == "\n" || !$text) - { - $ordering[$cur_pos]['add'] = array_merge($ordering[$cur_pos]['add'], array("\n"), $hunk['a']); - } - else if (sizeof($hunk['c']) > 2 || strlen(implode('', $hunk['c'])) > 20) - { - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; - } - else - { - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['add'] = $hunk['a']; -/* echo 'FIND STATEMENT TOO TINY'; - echo ";".rawurlencode($text).";"; - var_dump($hunk); - exit;*/ - } - } - else - { - echo 'UNCATCHED ENTRY'; - var_dump($hunks); - exit; - } - } - else - { - $ordering[$cur_pos]['add'] = $hunk['a']; - } - } - } - else if (!empty($hunk['d'])) - { - if (isset($ordering[$cur_pos]['add'])) - { - // If ordering is set with an add entry, we will actually begin a new ordering array (to seperate delete from add) - $cur_pos++; - $ordering[$cur_pos]['find_c'] = $ordering[($cur_pos - 1)]['end_c']; - $ordering[$cur_pos]['delete'] = $hunk['d']; - } - else - { - $ordering[$cur_pos]['delete'] = $hunk['d']; - } - } - } - } - - $html = ''; - - return $this->_emit_lines_bb($ybeg, $ordering); - } - - function _diff_header($xbeg, $xlen, $ybeg, $ylen) - { - } -} - - -/** -* A class to format a Diff as MOD Template instuctions. -* -* Usage: -* -* $diff = new Diff($lines1, $lines2); // compute diff. -* -* $fmt = new BBCodeDiffFormatter; -* echo $fmt->format($diff, $lines1); // Output MOD Actions. -*/ -class MODXDiffFormatter extends BBCodeDiffFormatter -{ - function MODXDiffFormatter ($reverse = false, $context_lines = 3, $debug = false) - { - $this->do_reverse_diff = $reverse; - $this->context_lines = $context_lines; - $this->context_prefix = ' '; - $this->deletes_prefix = '-'; - $this->adds_prefix = '+'; - $this->debug = $debug; - } - - function _emit_lines_bb($ybeg, &$ordering) - { - $html = ''; - - // Now adjust for bbcode display... - foreach ($ordering as $order_array) - { - // Skip useless empty lines... - if ($this->skip_lines($order_array, $ordering)) - { - continue; - } - - // Only include double-finds if the last find has very few code location indications... - if (sizeof($order_array['first_find_c'])) - { - $text = implode('', $order_array['find_c']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - if (strlen(implode('', $order_array['find_c'])) < 50) - { - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - - $html .= ' <comment lang="en">Around Line ' . $ybeg . '</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['first_find_c'][0])) . '</find>' . "\n"; - $ybeg += sizeof($order_array['first_find_c'][0]); - } - } - - if (sizeof($order_array['find_c'])) - { - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - -// $html .= ' <edit>' . "\n"; - $html .= ' <comment lang="en">Around Line ' . $ybeg . '</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['find_c'])) . '</find>' . "\n"; - } - - if (isset($order_array['replace'])) - { - $html .= ' <action type="replace-with">' . htmlspecialchars(implode('', $order_array['replace'])) . '</action>' . "\n"; - $html .= ' </edit>' . "\n"; - } - - if (isset($order_array['add'])) - { - $html .= ' <action type="after-add">' . htmlspecialchars(implode('', $order_array['add'])) . '</action>' . "\n"; - $html .= ' </edit>' . "\n"; - } - - // There is no DELETE. :o - // Let's try to adjust it then... - if (isset($order_array['delete'])) - { - $text = implode('', $order_array['delete']); - if ($text === "\n" || $text === "\t" || $text === '') - { - continue; - } - - $ybeg += sizeof($order_array['find_c']); - - if (substr($html, -8) !== '</find>' . "\n") - { - $html .= ' <edit>' . "\n"; - } - $html .= ' <comment lang="en">Around Line ' . $ybeg . ' / Just remove/delete the lines (replacing with an empty line)</comment>' . "\n"; - $html .= ' <find>' . htmlspecialchars(implode('', $order_array['delete'])) . '</find>' . "\n"; - $html .= ' <action type="replace-with"></action>' . "\n"; - $html .= ' </edit>'; - } - } - - return $html; - } - - function format_open($filename) - { - return '<open src="' . $filename . '">' . "\n"; - } - - function format_close($filename) - { - return '</open>' . "\n"; - } - - function _diff_header($xbeg, $xlen, $ybeg, $ylen) - { - } -} diff --git a/build/package.php b/build/package.php index 48f42b3572..22ea4e52af 100755 --- a/build/package.php +++ b/build/package.php @@ -285,9 +285,6 @@ if (sizeof($package->old_packages)) // Build Package $package->run_command($compress_command . ' ../release_files/' . $package->get('release_filename') . '-patch.' . $extension . ' *'); - - // Build MD5 Sum - $package->run_command('md5sum ../release_files/' . $package->get('release_filename') . '-patch.' . $extension . ' > ../release_files/' . $package->get('release_filename') . '-patch.' . $extension . '.md5'); } // Build Files Package @@ -319,8 +316,6 @@ if (sizeof($package->old_packages)) chdir('./release'); $package->run_command("$compress_command ../../release_files/" . $package->get('release_filename') . '-files.' . $extension . ' *'); - // Build MD5 Sum - $package->run_command('md5sum ../../release_files/' . $package->get('release_filename') . '-files.' . $extension . ' > ../../release_files/' . $package->get('release_filename') . '-files.' . $extension . '.md5'); chdir('..'); $package->run_command('rm -Rv ' . $package->get('files_directory') . '/release'); @@ -363,9 +358,6 @@ if (sizeof($package->old_packages)) // Copy last package over... $package->run_command('rm -v ../release_files/phpBB-' . $last_version . ".$extension"); $package->run_command("$compress_command ../../release_files/phpBB-$last_version.$extension *"); - - // Build MD5 Sum - $package->run_command("md5sum ../../release_files/phpBB-$last_version.$extension > ../../release_files/phpBB-$last_version.$extension.md5"); chdir('..'); } @@ -388,9 +380,6 @@ foreach ($compress_programs as $extension => $compress_command) // Build Package $package->run_command("$compress_command ./release_files/" . $package->get('release_filename') . '.' . $extension . ' ' . $package->get('package_name')); - - // Build MD5 Sum - $package->run_command('md5sum ./release_files/' . $package->get('release_filename') . '.' . $extension . ' > ./release_files/' . $package->get('release_filename') . '.' . $extension . '.md5'); } // Microsoft Web PI packaging @@ -398,7 +387,6 @@ $package->begin_status('Packaging phpBB for Microsoft WebPI'); $file = './release_files/' . $package->get('release_filename') . '.webpi.zip'; $package->run_command('cp -p ./release_files/' . $package->get('release_filename') . ".zip $file"); $package->run_command('cd ./../webpi && ' . $compress_programs['zip'] . " ./../new_version/$file *"); -$package->run_command("md5sum $file > $file.md5"); // verify results chdir($package->locations['root']); diff --git a/git-tools/commit-msg-hook-range.sh b/git-tools/commit-msg-hook-range.sh new file mode 100755 index 0000000000..2b408c3e79 --- /dev/null +++ b/git-tools/commit-msg-hook-range.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# +# @copyright (c) 2014 phpBB Group +# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +# +# Calls the git commit-msg hook on all non-merge commits in a given commit range. +# + +if [ "$#" -ne 1 ]; +then + echo "Expected one argument (commit range, e.g. phpbb/develop..ticket/12345)." + exit +fi + +DIR=$(dirname "$0") +COMMIT_RANGE="$1" +COMMIT_MSG_HOOK_PATH="$DIR/hooks/commit-msg" +COMMIT_MSG_HOOK_FATAL=$(git config --bool phpbb.hooks.commit-msg.fatal 2> /dev/null) +git config phpbb.hooks.commit-msg.fatal true + +EXIT_STATUS=0 +for COMMIT_HASH in $(git rev-list --no-merges "$COMMIT_RANGE") +do + echo "Inspecting commit message of commit $COMMIT_HASH" + + # The git commit-msg hook takes a path to a file containing a commit + # message. So we have to extract the commit message into a file first, + # which then also needs to be deleted after our work is done. + COMMIT_MESSAGE_PATH="$DIR/commit_msg.$COMMIT_HASH" + git log -n 1 --pretty=format:%B "$COMMIT_HASH" > "$COMMIT_MESSAGE_PATH" + + # Invoke hook on commit message file. + "$COMMIT_MSG_HOOK_PATH" "$COMMIT_MESSAGE_PATH" + + # If any commit message hook complains with a non-zero exit status, we + # will send a non-zero exit status upstream. + if [ $? -ne 0 ] + then + EXIT_STATUS=1 + fi + + rm "$COMMIT_MESSAGE_PATH" +done + +# Restore phpbb.hooks.commit-msg.fatal config +if [ -n "$COMMIT_MSG_HOOK_FATAL" ] +then + git config phpbb.hooks.commit-msg.fatal "$COMMIT_MSG_HOOK_FATAL" +fi + +exit $EXIT_STATUS diff --git a/phpBB/adm/style/acp_inactive.html b/phpBB/adm/style/acp_inactive.html index 3b20043dd9..b8e46a6e53 100644 --- a/phpBB/adm/style/acp_inactive.html +++ b/phpBB/adm/style/acp_inactive.html @@ -53,7 +53,7 @@ </table> <fieldset class="display-options"> - {L_DISPLAY_LOG}: {S_LIMIT_DAYS} {L_SORT_BY}: {S_SORT_KEY} {S_SORT_DIR}<!-- IF PAGINATION --> Users per page: <input class="inputbox autowidth" type="text" name="users_per_page" id="users_per_page" size="3" value="{USERS_PER_PAGE}" /><!-- ENDIF --> + {L_DISPLAY_LOG}: {S_LIMIT_DAYS} {L_SORT_BY}: {S_SORT_KEY} {S_SORT_DIR}<!-- IF PAGINATION --> {L_USERS_PER_PAGE}: <input class="inputbox autowidth" type="text" name="users_per_page" id="users_per_page" size="3" value="{USERS_PER_PAGE}" /><!-- ENDIF --> <input class="button2" type="submit" value="{L_GO}" name="sort" /> </fieldset> diff --git a/phpBB/adm/style/editor.js b/phpBB/adm/style/editor.js index 217aa699e2..cad01aa9f2 100644 --- a/phpBB/adm/style/editor.js +++ b/phpBB/adm/style/editor.js @@ -292,7 +292,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/docs/AUTHORS b/phpBB/docs/AUTHORS index 5995bd2ab4..465c4de397 100644 --- a/phpBB/docs/AUTHORS +++ b/phpBB/docs/AUTHORS @@ -23,10 +23,11 @@ involved in phpBB. phpBB Lead Developer: naderman (Nils Adermann) phpBB Developers: bantu (Andreas Fischer) - EXreaction (Nathan Guse) dhruv.goel92 (Dhruv Goel) + EXreaction (Nathan Guse) imkingdavid (David King) nickvergessen (Joas Schilling) + prototech (Cesar Gallegos) Contributions by: leviatan21 (Gabriel Vazquez) Raimon (Raimon Meuldijk) diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index 6d8b39d524..71795f83ac 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -218,6 +218,7 @@ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11368">PHPBB3-11368</a>] - Latest pm reports row count</li> <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11583">PHPBB3-11583</a>] - InnoDB supports FULLTEXT index since MySQL 5.6.4.</li> <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11740">PHPBB3-11740</a>] - Update link in FAQ to Ideas Centre</li> +<li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11873">PHPBB3-11873</a>] - Prevent expensive hash computation in phpbb_check_hash() by rejecting very long passwords</li> </ul> <h4>Sub-task</h4> <ul> diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 3fa0597fc8..74c017ecff 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -139,6 +139,7 @@ <li>A SQL database system, <strong>one of</strong>: <ul> <li>MySQL 3.23 or above (MySQLi supported)</li> + <li>MariaDB 5.1 or above</li> <li>PostgreSQL 7.3+</li> <li>SQLite 2.8.2+ (SQLite 3 is not supported)</li> <li>Firebird 2.1+</li> diff --git a/phpBB/docs/README.html b/phpBB/docs/README.html index 89f573de04..d54c58eca6 100644 --- a/phpBB/docs/README.html +++ b/phpBB/docs/README.html @@ -329,7 +329,7 @@ <p>Please remember that running any application on a development (unstable, e.g. a beta release) version of PHP can lead to strange/unexpected results which may appear to be bugs in the application. Therefore, we recommend you upgrade to the newest stable version of PHP before running phpBB3. If you are running a development version of PHP please check any bugs you find on a system running a stable release before submitting.</p> - <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MSSQL Server 2000, PostgreSQL 7.x, Oracle 8, SQLite 2 and Firebird. Versions of PHP used range from 4.3.3 to 5.4.x without problem. </p> + <p>This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MariaDB 5.x, MSSQL Server 2000, PostgreSQL 7.x, Oracle 8, SQLite 2 and Firebird. Versions of PHP used range from 4.3.3 to 5.4.x without problem. </p> <a name="phpsec"></a><h3>7.i. Notice on PHP security issues</h3> diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php index 50e12a0f15..dc2e6b75fb 100644 --- a/phpBB/includes/acp/acp_forums.php +++ b/phpBB/includes/acp/acp_forums.php @@ -56,7 +56,6 @@ class acp_forums $total = request_var('total', 0); $this->display_progress_bar($start, $total); - exit; break; case 'delete': diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php index 9356e3e9b4..f587e111f3 100644 --- a/phpBB/includes/bbcode.php +++ b/phpBB/includes/bbcode.php @@ -376,7 +376,7 @@ class bbcode } // Replace {L_*} lang strings - $bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl); + $bbcode_tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $bbcode_tpl); if (!empty($rowset[$bbcode_id]['second_pass_replace'])) { @@ -480,7 +480,7 @@ class bbcode 'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2') ); - $tpl = preg_replace('/{L_([A-Z_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl); + $tpl = preg_replace('/{L_([A-Z0-9_]+)}/e', "(!empty(\$user->lang['\$1'])) ? \$user->lang['\$1'] : ucwords(strtolower(str_replace('_', ' ', '\$1')))", $tpl); if (!empty($replacements[$tpl_name])) { diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php index f63ff18cbe..e394b1ffa0 100644 --- a/phpBB/includes/db/db_tools.php +++ b/phpBB/includes/db/db_tools.php @@ -477,7 +477,7 @@ class phpbb_db_tools // here lies an array, filled with information compiled on the column's data $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - if (isset($prepared_column['auto_increment']) && strlen($column_name) > 26) // "${column_name}_gen" + if (isset($prepared_column['auto_increment']) && $prepared_column['auto_increment'] && strlen($column_name) > 26) // "${column_name}_gen" { trigger_error("Index name '${column_name}_gen' on table '$table_name' is too long. The maximum auto increment column length is 26 characters.", E_USER_ERROR); } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index b2b12c1445..eef4ade4e7 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -502,6 +502,13 @@ function phpbb_hash($password) */ function phpbb_check_hash($password, $hash) { + if (strlen($password) > 4096) + { + // If the password is too huge, we will simply reject it + // and not let the server try to hash it. + return false; + } + $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; if (strlen($hash) == 34) { diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index d0e7c8cfc8..bb6913a572 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -436,21 +436,21 @@ class p_master if ($this->active_module === false) { - trigger_error('Module not accessible', E_USER_ERROR); + trigger_error('MODULE_NOT_ACCESS', E_USER_ERROR); } if (!class_exists("{$this->p_class}_$this->p_name")) { if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx")) { - trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR); + trigger_error($user->lang('MODULE_NOT_FIND', "$module_path/{$this->p_class}_$this->p_name.$phpEx"), E_USER_ERROR); } include("$module_path/{$this->p_class}_$this->p_name.$phpEx"); if (!class_exists("{$this->p_class}_$this->p_name")) { - trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR); + trigger_error($user->lang('MODULE_FILE_RIGHT_CLASS', "$module_path/{$this->p_class}_$this->p_name.$phpEx", "{$this->p_class}_$this->p_name"), E_USER_ERROR); } if (!empty($mode)) diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index 8573533c2c..a2c0656ca4 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -532,7 +532,7 @@ class custom_profile switch ($this->profile_types[$field_type]) { case 'int': - if ($value === '' && !$ident_ary['data']['field_show_novalue']) + if (($value === '' || $value === null) && !$ident_ary['data']['field_show_novalue']) { return NULL; } diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php index 7fff83db58..29c5a72874 100644 --- a/phpBB/includes/search/fulltext_native.php +++ b/phpBB/includes/search/fulltext_native.php @@ -231,7 +231,6 @@ class fulltext_native extends search_backend } $db->sql_freeresult($result); } - unset($exact_words); // Handle +, - without preceeding whitespace character $match = array('#(\S)\+#', '#(\S)-#'); @@ -363,39 +362,21 @@ class fulltext_native extends search_backend $this->{$mode . '_ids'}[] = $words[$word]; } } - // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id) + else { if (!isset($common_ids[$word])) { $len = utf8_strlen($word); - if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) - { - trigger_error(sprintf($user->lang['WORD_IN_NO_POST'], $word)); - } - else + if ($len < $this->word_length['min'] || $len > $this->word_length['max']) { $this->common_words[] = $word; } } } - else - { - $len = utf8_strlen($word); - if ($len < $this->word_length['min'] || $len > $this->word_length['max']) - { - $this->common_words[] = $word; - } - } } - // we can't search for negatives only - if (!sizeof($this->must_contain_ids)) - { - return false; - } - - if (!empty($this->search_query)) + // Return true if all words are not common words + if (sizeof($exact_words) - sizeof($this->common_words) > 0) { return true; } @@ -434,6 +415,12 @@ class fulltext_native extends search_backend return false; } + // we can't search for negatives only + if (empty($this->must_contain_ids)) + { + return false; + } + $must_contain_ids = $this->must_contain_ids; $must_not_contain_ids = $this->must_not_contain_ids; $must_exclude_one_ids = $this->must_exclude_one_ids; diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php index 1070b10b18..7c57dfdc1f 100644 --- a/phpBB/install/database_update.php +++ b/phpBB/install/database_update.php @@ -1009,6 +1009,8 @@ function database_update_info() '3.0.12-RC1' => array(), // No changes from 3.0.12-RC2 to 3.0.12-RC3 '3.0.12-RC2' => array(), + // No changes from 3.0.12-RC3 to 3.0.12 + '3.0.12-RC3' => array(), /** @todo DROP LOGIN_ATTEMPT_TABLE.attempt_id in 3.0.13-RC1 */ ); @@ -2248,6 +2250,10 @@ function change_database_data(&$no_updates, $version) // No changes from 3.0.12-RC2 to 3.0.12-RC3 case '3.0.12-RC2': break; + + // No changes from 3.0.12-RC3 to 3.0.12 + case '3.0.12-RC3': + break; } } diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index ccd12fcb6a..f9a40c2bc7 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -44,7 +44,7 @@ $lang = array_merge($lang, array( 'DEFAULT_LANGUAGE' => 'Default language', 'DEFAULT_STYLE' => 'Default style', 'DISABLE_BOARD' => 'Disable board', - 'DISABLE_BOARD_EXPLAIN' => 'This will make the board unavailable to users. You can also enter a short (255 character) message to display if you wish.', + 'DISABLE_BOARD_EXPLAIN' => 'This will make the board unavailable to users who are neither administrators nor moderators. You can also enter a short (255 character) message to display if you wish.', 'OVERRIDE_STYLE' => 'Override user style', 'OVERRIDE_STYLE_EXPLAIN' => 'Replaces user’s style with the default.', 'SITE_DESC' => 'Site description', diff --git a/phpBB/language/en/common.php b/phpBB/language/en/common.php index f37f6d3b30..663369b8fa 100644 --- a/phpBB/language/en/common.php +++ b/phpBB/language/en/common.php @@ -341,6 +341,9 @@ $lang = array_merge($lang, array( 'MODERATE' => 'Moderate', 'MODERATOR' => 'Moderator', 'MODERATORS' => 'Moderators', + 'MODULE_NOT_ACCESS' => 'Module not accessible', + 'MODULE_NOT_FIND' => 'Cannot find module %s', + 'MODULE_FILE_RIGHT_CLASS' => 'Module file %s does not contain correct class [%s]', 'MONTH' => 'Month', 'MOVE' => 'Move', 'MSNM' => 'MSNM/WLM', diff --git a/phpBB/language/en/email/topic_notify.txt b/phpBB/language/en/email/topic_notify.txt index 99865494ac..f52ce9395d 100644 --- a/phpBB/language/en/email/topic_notify.txt +++ b/phpBB/language/en/email/topic_notify.txt @@ -2,7 +2,7 @@ Subject: Topic reply notification - "{TOPIC_TITLE}" Hello {USERNAME}, -You are receiving this notification because you are watching the topic "{TOPIC_TITLE}" at "{SITENAME}". This topic has received a reply<!-- IF AUTHOR_NAME !== '' --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. You can use the following link to view the replies made, no more notifications will be sent until you visit the topic. +You are receiving this notification because you are watching the topic "{TOPIC_TITLE}" at "{SITENAME}". This topic has received a reply<!-- IF AUTHOR_NAME !== '' --> by {AUTHOR_NAME}<!-- ENDIF --> since your last visit. No more notifications will be sent until you visit the topic. If you want to view the newest post made since your last visit, click the following link: {U_NEWEST_POST} @@ -14,7 +14,6 @@ If you want to view the forum, click the following link: {U_FORUM} If you no longer wish to watch this topic you can either click the "Unsubscribe topic" link found at the bottom of the topic above, or by clicking the following link: - {U_STOP_WATCHING_TOPIC} {EMAIL_SIG}
\ No newline at end of file diff --git a/phpBB/language/en/memberlist.php b/phpBB/language/en/memberlist.php index 7dc5e6b74a..f59efd3b95 100644 --- a/phpBB/language/en/memberlist.php +++ b/phpBB/language/en/memberlist.php @@ -138,6 +138,7 @@ $lang = array_merge($lang, array( ), 'USER_ONLINE' => 'Online', 'USER_PRESENCE' => 'Board presence', + 'USERS_PER_PAGE' => 'Users per page', 'VIEWING_PROFILE' => 'Viewing profile - %s', 'VISITED' => 'Last visited', diff --git a/phpBB/search.php b/phpBB/search.php index ad9c371f63..0f13dbbfa0 100644 --- a/phpBB/search.php +++ b/phpBB/search.php @@ -540,12 +540,6 @@ if ($keywords || $author || $author_id || $search_id || $submit) $total_match_count = $search->author_search($show_results, $firstpost_only, $sort_by_sql, $sort_key, $sort_dir, $sort_days, $ex_fid_ary, $m_approve_fid_ary, $topic_id, $author_id_ary, $sql_author_match, $id_ary, $start, $per_page); } - // For some searches we need to print out the "no results" page directly to allow re-sorting/refining the search options. - if (!sizeof($id_ary) && !$search_id) - { - trigger_error('NO_SEARCH_RESULTS'); - } - $sql_where = ''; if (sizeof($id_ary)) diff --git a/phpBB/styles/prosilver/template/editor.js b/phpBB/styles/prosilver/template/editor.js index c16b0ef703..42be70be92 100644 --- a/phpBB/styles/prosilver/template/editor.js +++ b/phpBB/styles/prosilver/template/editor.js @@ -347,7 +347,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/styles/prosilver/template/forum_fn.js b/phpBB/styles/prosilver/template/forum_fn.js index 240fe7e51d..6a65caf6f6 100644 --- a/phpBB/styles/prosilver/template/forum_fn.js +++ b/phpBB/styles/prosilver/template/forum_fn.js @@ -403,7 +403,7 @@ function apply_onkeypress_event() // jQuery code in case jQuery is used if (jquery_present) { - jQuery('form input[type=text], form input[type=password]').live('keypress', function (e) + jQuery('form input[type=text], form input[type=password]').on('keypress', function (e) { var default_button = jQuery(this).parents('form').find('input[type=submit].default-submit-action'); diff --git a/phpBB/styles/prosilver/template/overall_footer.html b/phpBB/styles/prosilver/template/overall_footer.html index 25b60be6e1..fc6a37cbe3 100644 --- a/phpBB/styles/prosilver/template/overall_footer.html +++ b/phpBB/styles/prosilver/template/overall_footer.html @@ -6,7 +6,7 @@ <div class="inner"><span class="corners-top"><span></span></span> <ul class="linklist"> - <li class="icon-home"><a href="{U_INDEX}" accesskey="h">{L_INDEX}</a></li> + <li class="icon-home"><a href="{U_INDEX}">{L_INDEX}</a></li> <!-- IF not S_IS_BOT --> <!-- IF S_WATCH_FORUM_LINK --><li <!-- IF S_WATCHING_FORUM -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{S_WATCH_FORUM_LINK}" title="{S_WATCH_FORUM_TITLE}">{S_WATCH_FORUM_TITLE}</a></li><!-- ENDIF --> <!-- IF U_WATCH_TOPIC --><li <!-- IF S_WATCHING_TOPIC -->class="icon-unsubscribe"<!-- ELSE -->class="icon-subscribe"<!-- ENDIF -->><a href="{U_WATCH_TOPIC}" title="{L_WATCH_TOPIC}">{L_WATCH_TOPIC}</a></li><!-- ENDIF --> diff --git a/phpBB/styles/prosilver/template/ucp_groups_manage.html b/phpBB/styles/prosilver/template/ucp_groups_manage.html index c90461312e..53d2dfffb3 100644 --- a/phpBB/styles/prosilver/template/ucp_groups_manage.html +++ b/phpBB/styles/prosilver/template/ucp_groups_manage.html @@ -54,7 +54,7 @@ <fieldset> <dl> <dt><label for="group_colour">{L_GROUP_COLOR}:</label><br /><span>{L_GROUP_COLOR_EXPLAIN}</span></dt> - <dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" class="inputbox narrow" /> <span style="background-color: {GROUP_COLOUR};"> </span> [ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false;">{L_COLOUR_SWATCH}</a> ]</dd> + <dd><input name="group_colour" type="text" id="group_colour" value="{GROUP_COLOUR}" size="6" maxlength="6" class="inputbox narrow" /> <span style="background-color: #{GROUP_COLOUR};"> </span> [ <a href="{U_SWATCH}" onclick="popup(this.href, 636, 150, '_swatch'); return false;">{L_COLOUR_SWATCH}</a> ]</dd> </dl> <dl> <dt><label for="group_rank">{L_GROUP_RANK}:</label></dt> diff --git a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html index 67e14defc3..91dd4606c8 100644 --- a/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/prosilver/template/ucp_pm_viewmessage_print.html @@ -8,8 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="keywords" content="" /> -<meta name="description" content="" /> <meta name="robots" content="noindex" /> {META} <title>{SITENAME} • {PAGE_TITLE}</title> diff --git a/phpBB/styles/prosilver/template/ucp_profile_reg_details.html b/phpBB/styles/prosilver/template/ucp_profile_reg_details.html index 5eb55dc71c..2f24601645 100644 --- a/phpBB/styles/prosilver/template/ucp_profile_reg_details.html +++ b/phpBB/styles/prosilver/template/ucp_profile_reg_details.html @@ -7,7 +7,7 @@ <div class="inner"><span class="corners-top"><span></span></span> <!-- IF S_FORCE_PASSWORD --> - <p>{L_FORCE_PASSWORD_EXPLAIN}</p> + <p class="error">{L_FORCE_PASSWORD_EXPLAIN}</p> <!-- ENDIF --> <fieldset> @@ -60,4 +60,4 @@ </fieldset> </form> -<!-- INCLUDE ucp_footer.html -->
\ No newline at end of file +<!-- INCLUDE ucp_footer.html --> diff --git a/phpBB/styles/prosilver/template/viewtopic_print.html b/phpBB/styles/prosilver/template/viewtopic_print.html index 39d2d76394..168305a6a4 100644 --- a/phpBB/styles/prosilver/template/viewtopic_print.html +++ b/phpBB/styles/prosilver/template/viewtopic_print.html @@ -8,8 +8,6 @@ <meta http-equiv="imagetoolbar" content="no" /> <meta name="resource-type" content="document" /> <meta name="distribution" content="global" /> -<meta name="keywords" content="" /> -<meta name="description" content="" /> <meta name="robots" content="noindex" /> {META} <title>{SITENAME} • {PAGE_TITLE}</title> diff --git a/phpBB/styles/subsilver2/template/editor.js b/phpBB/styles/subsilver2/template/editor.js index 151cf53ff1..103a271a71 100644 --- a/phpBB/styles/subsilver2/template/editor.js +++ b/phpBB/styles/subsilver2/template/editor.js @@ -351,7 +351,7 @@ function mozWrap(txtarea, open, close) */ function storeCaret(textEl) { - if (textEl.createTextRange) + if (textEl.createTextRange && document.selection) { textEl.caretPos = document.selection.createRange().duplicate(); } diff --git a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html index cd55c16a50..085e26ecd2 100644 --- a/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html +++ b/phpBB/styles/subsilver2/template/ucp_pm_viewmessage_print.html @@ -4,6 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset={S_CONTENT_ENCODING}"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Language" content="{S_USER_LANG}"> +<meta name="robots" content="noindex" /> <title>{SITENAME} :: {PAGE_TITLE}</title> <style type="text/css"> diff --git a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html b/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html index 09f60ad5a7..2eca7a93c8 100644 --- a/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html +++ b/phpBB/styles/subsilver2/template/ucp_profile_reg_details.html @@ -6,7 +6,7 @@ </tr> <!-- IF S_FORCE_PASSWORD --> <tr> - <td class="row3" colspan="2" align="center"><span class="gensmall">{L_FORCE_PASSWORD_EXPLAIN}</span></td> + <td class="row3" colspan="2" align="center"><span class="gensmall error">{L_FORCE_PASSWORD_EXPLAIN}</span></td> </tr> <!-- ENDIF --> <!-- IF ERROR --> @@ -50,4 +50,4 @@ </tr> </table> -<!-- INCLUDE ucp_footer.html -->
\ No newline at end of file +<!-- INCLUDE ucp_footer.html --> diff --git a/phpBB/styles/subsilver2/template/viewtopic_print.html b/phpBB/styles/subsilver2/template/viewtopic_print.html index 1ca1eccc99..47b5bdb28e 100644 --- a/phpBB/styles/subsilver2/template/viewtopic_print.html +++ b/phpBB/styles/subsilver2/template/viewtopic_print.html @@ -4,6 +4,7 @@ <meta http-equiv="Content-Type" content="text/html; charset={S_CONTENT_ENCODING}"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Language" content="{S_USER_LANG}"> +<meta name="robots" content="noindex" /> <title>{SITENAME} :: {PAGE_TITLE}</title> <style type="text/css"> diff --git a/tests/functions/obtain_online_test.php b/tests/functions/obtain_online_test.php index b3beb55a96..de6451a0db 100644 --- a/tests/functions/obtain_online_test.php +++ b/tests/functions/obtain_online_test.php @@ -22,8 +22,9 @@ class phpbb_functions_obtain_online_test extends phpbb_database_test_case { parent::setUp(); - global $config, $db; + global $config, $db, $user; + $user = new StdClass; $db = $this->db = $this->new_dbal(); $config = array( 'load_online_time' => 5, diff --git a/tests/lint_test.php b/tests/lint_test.php index 905067072d..b0149063bd 100644 --- a/tests/lint_test.php +++ b/tests/lint_test.php @@ -9,20 +9,37 @@ class phpbb_lint_test extends phpbb_test_case { + static protected $php_binary; static protected $exclude; static public function setUpBeforeClass() { + // Try to use PHP_BINARY constant if available so lint tests are run + // using the same php binary as phpunit. If not available (pre PHP + // 5.4), assume binary is called 'php' and is in PATH. + self::$php_binary = defined('PHP_BINARY') ? escapeshellcmd(PHP_BINARY) : 'php'; + $output = array(); $status = 1; - exec('(php -v) 2>&1', $output, $status); + exec(sprintf('(%s --version) 2>&1', self::$php_binary), $output, $status); if ($status) { $output = implode("\n", $output); - self::markTestSkipped("php is not in PATH or broken: $output"); + if (self::$php_binary === 'php') + { + self::markTestSkipped(sprintf('php is not in PATH or broken. Output: %s', $output)); + } + else + { + self::markTestSkipped(sprintf('Could not run PHP_BINARY %s. Output: %s', self::$php_binary, $output)); + } } self::$exclude = array( + dirname(__FILE__) . '/../.git', + dirname(__FILE__) . '/../build/new_version', + dirname(__FILE__) . '/../build/old_versions', + dirname(__FILE__) . '/../phpBB/cache', // PHP Fatal error: Cannot declare class Container because the name is already in use in /var/www/projects/phpbb3/tests/../phpBB/vendor/symfony/dependency-injection/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php on line 20 // https://gist.github.com/e003913ffd493da63cbc dirname(__FILE__) . '/../phpBB/vendor', @@ -45,7 +62,7 @@ class phpbb_lint_test extends phpbb_test_case $dh = opendir($root); while (($filename = readdir($dh)) !== false) { - if ($filename == '.' || $filename == '..' || $filename == 'git') + if ($filename == '.' || $filename == '..') { continue; } @@ -61,13 +78,12 @@ class phpbb_lint_test extends phpbb_test_case } else if (substr($filename, strlen($filename)-4) == '.php') { - // assume php binary is called php and it is in PATH - $cmd = '(php -l ' . escapeshellarg($path) . ') 2>&1'; + $cmd = sprintf('(%s -l %s) 2>&1', self::$php_binary, escapeshellarg($path)); $output = array(); $status = 1; exec($cmd, $output, $status); $output = implode("\n", $output); - $this->assertEquals(0, $status, "php -l failed for $path:\n$output"); + $this->assertEquals(0, $status, "PHP lint failed for $path:\n$output"); } } } diff --git a/tests/profile/get_profile_value_test.php b/tests/profile/get_profile_value_test.php new file mode 100644 index 0000000000..a5f37a85ce --- /dev/null +++ b/tests/profile/get_profile_value_test.php @@ -0,0 +1,42 @@ +<?php +/** +* +* @package testing +* @copyright (c) 2014 phpBB Group +* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +* +*/ + +require_once dirname(__FILE__) . '/../../phpBB/includes/functions_profile_fields.php'; + +class phpbb_profile_get_profile_value_test extends phpbb_test_case +{ + static public function get_profile_value_int_data() + { + return array( + array(FIELD_INT, '10', true, 10), + array(FIELD_INT, '0', true, 0), + array(FIELD_INT, '', true, 0), + array(FIELD_INT, null, true, 0), + array(FIELD_INT, '10', false, 10), + array(FIELD_INT, '0', false, 0), + array(FIELD_INT, '', false, null), + array(FIELD_INT, null, false, null), + ); + } + + /** + * @dataProvider get_profile_value_int_data + */ + public function test_get_profile_value_int($type, $value, $show_novalue, $expected) + { + $cp = new custom_profile; + $this->assertSame($expected, $cp->get_profile_value(array( + 'value' => $value, + 'data' => array( + 'field_type' => $type, + 'field_show_novalue' => $show_novalue, + ), + ))); + } +} diff --git a/tests/security/hash_test.php b/tests/security/hash_test.php index 0c2580c19b..e226365ef3 100644 --- a/tests/security/hash_test.php +++ b/tests/security/hash_test.php @@ -17,5 +17,13 @@ class phpbb_security_hash_test extends phpbb_test_case $this->assertTrue(phpbb_check_hash('test', '$P$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); $this->assertFalse(phpbb_check_hash('foo', '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); } + + public function test_check_hash_with_large_input() + { + // 16 MB password, should be rejected quite fast + $start_time = time(); + $this->assertFalse(phpbb_check_hash(str_repeat('a', 1024 * 1024 * 16), '$H$9isfrtKXWqrz8PvztXlL3.daw4U0zI1')); + $this->assertLessThanOrEqual(5, time() - $start_time); + } } diff --git a/travis/phpunit-mariadb-travis.xml b/travis/phpunit-mariadb-travis.xml new file mode 100644 index 0000000000..1eaee5b7d8 --- /dev/null +++ b/travis/phpunit-mariadb-travis.xml @@ -0,0 +1,41 @@ +<?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="true" + strict="true" + verbose="true" + bootstrap="../tests/bootstrap.php"> + <testsuites> + <testsuite name="phpBB Test Suite"> + <directory suffix="_test.php">../tests/</directory> + <exclude>tests/functional</exclude> + <exclude>tests/lint_test.php</exclude> + </testsuite> + <testsuite name="phpBB Functional Tests"> + <directory suffix="_test.php" phpVersion="5.3.19" phpVersionOperator=">=">../tests/functional</directory> + </testsuite> + </testsuites> + + <groups> + <exclude> + <group>slow</group> + </exclude> + </groups> + + <php> + <server name="PHPBB_TEST_DBMS" value="mysqli" /> + <server name="PHPBB_TEST_DBHOST" value="0.0.0.0" /> + <server name="PHPBB_TEST_DBPORT" value="3306" /> + <server name="PHPBB_TEST_DBNAME" value="phpbb_tests" /> + <server name="PHPBB_TEST_DBUSER" value="root" /> + <server name="PHPBB_TEST_DBPASSWD" value="" /> + <server name="PHPBB_TEST_TABLE_PREFIX" value="phpbb_"/> + <server name="PHPBB_FUNCTIONAL_URL" value="http://localhost/" /> + </php> +</phpunit> diff --git a/travis/setup-mariadb.sh b/travis/setup-mariadb.sh new file mode 100755 index 0000000000..aceb6af7ee --- /dev/null +++ b/travis/setup-mariadb.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# +# @copyright (c) 2013 phpBB Group +# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 +# +set -e +set -x + +# MariaDB Series +VERSION='5.5' + +# Operating system codename, e.g. "precise" +OS_CODENAME=$(lsb_release --codename --short) + +# Manually purge MySQL to remove conflicting files (e.g. /etc/mysql/my.cnf) +sudo apt-get purge -y mysql-common + +if ! which add-apt-repository > /dev/null +then + sudo apt-get update + sudo apt-get install -y python-software-properties +fi + +MIRROR_DOMAIN='ftp.osuosl.org' +sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db +sudo add-apt-repository "deb http://$MIRROR_DOMAIN/pub/mariadb/repo/$VERSION/ubuntu $OS_CODENAME main" +sudo apt-get update + +# Pin repository in order to avoid conflicts with MySQL from distribution +# repository. See https://mariadb.com/kb/en/installing-mariadb-deb-files +# section "Version Mismatch Between MariaDB and Ubuntu/Debian Repositories" +echo " +Package: * +Pin: origin $MIRROR_DOMAIN +Pin-Priority: 1000 +" | sudo tee /etc/apt/preferences.d/mariadb + +sudo debconf-set-selections <<< "mariadb-server-$VERSION mysql-server/root_password password rootpasswd" +sudo debconf-set-selections <<< "mariadb-server-$VERSION mysql-server/root_password_again password rootpasswd" +sudo apt-get install -y mariadb-server + +# Set root password to empty string. +echo " +USE mysql; +UPDATE user SET Password = PASSWORD('') where User = 'root'; +FLUSH PRIVILEGES; +" | mysql -u root -prootpasswd + +mysql --version diff --git a/travis/setup-webserver.sh b/travis/setup-webserver.sh index 95fc4ec1f8..f1bf69c575 100755 --- a/travis/setup-webserver.sh +++ b/travis/setup-webserver.sh @@ -4,9 +4,10 @@ # @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2 # set -e +set -x -sudo apt-get update -qq -sudo apt-get install -qq nginx realpath +sudo apt-get update +sudo apt-get install -y nginx realpath sudo service nginx stop |