aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xgit-tools/hooks/commit-msg257
-rwxr-xr-xgit-tools/hooks/install17
-rwxr-xr-xgit-tools/hooks/pre-commit7
-rwxr-xr-xgit-tools/hooks/prepare-commit-msg10
-rwxr-xr-xgit-tools/hooks/uninstall16
-rw-r--r--phpBB/download/file.php8
-rw-r--r--phpBB/includes/acp/acp_forums.php3
-rw-r--r--phpBB/includes/acp/acp_users.php5
-rw-r--r--phpBB/includes/cache.php9
-rw-r--r--phpBB/includes/captcha/plugins/captcha_abstract.php8
-rw-r--r--phpBB/includes/functions.php191
-rw-r--r--phpBB/includes/functions_admin.php82
-rw-r--r--phpBB/includes/functions_posting.php2
-rw-r--r--phpBB/includes/functions_user.php38
-rw-r--r--phpBB/includes/mcp/mcp_main.php35
-rw-r--r--phpBB/includes/search/fulltext_native.php13
-rw-r--r--phpBB/includes/session.php2
-rw-r--r--phpBB/includes/ucp/ucp_profile.php5
-rw-r--r--phpBB/includes/ucp/ucp_register.php6
-rw-r--r--phpBB/includes/ucp/ucp_remind.php4
-rw-r--r--phpBB/install/database_update.php46
-rw-r--r--phpBB/language/en/acp/board.php4
-rw-r--r--phpBB/styles/prosilver/theme/bidi.css1
-rw-r--r--tests/all_tests.php4
-rw-r--r--tests/network/all_tests.php40
-rw-r--r--tests/network/checkdnsrr.php63
-rw-r--r--tests/random/all_tests.php40
-rw-r--r--tests/random/gen_rand_string.php63
28 files changed, 890 insertions, 89 deletions
diff --git a/git-tools/hooks/commit-msg b/git-tools/hooks/commit-msg
new file mode 100755
index 0000000000..d6ad57a38a
--- /dev/null
+++ b/git-tools/hooks/commit-msg
@@ -0,0 +1,257 @@
+#!/bin/sh
+#
+# A hook to check syntax of a phpBB3 commit message, per:
+# * <http://wiki.phpbb.com/display/DEV/Git>
+# * <http://area51.phpbb.com/phpBB/viewtopic.php?p=209919#p209919>
+#
+# This is a commit-msg hook.
+#
+# To install this you can either copy or symlink it to
+# $GIT_DIR/hooks, example:
+#
+# ln -s ../../git-tools/hooks/commit-msg \\
+# .git/hooks/commit-msg
+
+config_ns="phpbb.hooks.commit-msg";
+
+if [ "$(git config --bool $config_ns.fatal)" = "false" ]
+then
+ fatal=0;
+else
+ fatal=1;
+fi
+
+debug_level=$(git config --int $config_ns.debug || echo 0);
+
+# Error codes
+ERR_LENGTH=1;
+ERR_HEADER=2;
+ERR_EMPTY=3;
+ERR_DESCRIPTION=4;
+ERR_FOOTER=5;
+ERR_EOF=6;
+ERR_UNKNOWN=42;
+
+debug()
+{
+ local level;
+
+ level=$1;
+ shift;
+
+ if [ $debug_level -ge $level ]
+ then
+ echo $@;
+ fi
+}
+
+quit()
+{
+ if [ $1 -gt 0 ] && [ $1 -ne $ERR_UNKNOWN ] && [ $fatal -eq 0 ]
+ then
+ exit 0;
+ else
+ exit $1;
+ fi
+}
+
+if [ "$(wc --max-line-length "$1" | cut -f1 -d" ")" -gt 80 ]
+then
+ echo "The following lines are greater than 80 characters long:\n" >&2;
+
+ grep -nE '.{81,}' "$1" >&2;
+
+ quit $ERR_LENGTH;
+fi
+
+lines=$(wc --lines "$1" | cut -f1 -d" ");
+expecting=header;
+in_description=0;
+in_empty=0;
+ticket=0;
+branch_regex="[a-z]+[a-z0-9-]*[a-z0-9]+";
+i=1;
+tickets="";
+
+while [ $i -le $lines ]
+do
+ # Grab the line we are studying
+ line=$(head -n$i "$1" | tail -n1);
+
+ debug 1 "==> [$i] $line (description: $in_description, empty: $in_empty)";
+
+ err=$ERR_UNKNOWN;
+
+ if [ -z "$expecting" ]
+ then
+ quit $err;
+ fi
+
+ if [ "${expecting#comment}" = "$expecting" ]
+ then
+ # Prefix comments to the expected tokens list
+ expecting="comment $expecting";
+ fi
+
+ debug 2 "Expecting: $expecting";
+
+ # Loop over each of the expected line formats
+ for expect in $expecting
+ do
+ # Reset the error code each iteration
+ err=$ERR_UNKNOWN;
+
+ # Test for validity of each line format
+ # This is done first so $? contains the result
+ case $expect in
+ "header")
+ err=$ERR_HEADER;
+ echo "$line" | grep -Eq "^\[(ticket/[0-9]+|feature/$branch_regex|task/$branch_regex)\] [A-Z].+$"
+ ;;
+ "empty")
+ err=$ERR_EMPTY;
+ echo "$line" | grep -Eq "^$"
+ ;;
+ "description")
+ err=$ERR_DESCRIPTION;
+ # Free flow text, the line length was constrained by the initial check
+ echo "$line" | grep -Eq "^.+$";
+ ;;
+ "footer")
+ err=$ERR_FOOTER;
+ # Each ticket is on its own line
+ echo "$line" | grep -Eq "^PHPBB3-[0-9]+$";
+ ;;
+ "eof")
+ err=$ERR_EOF;
+ # Should not end up here
+ false
+ ;;
+ "comment")
+ echo "$line" | grep -Eq "^#";
+ ;;
+ *)
+ echo "Unrecognised token $expect" >&2;
+ quit $err;
+ ;;
+ esac
+
+ # Preserve the result of the line check
+ result=$?;
+
+ debug 2 "$expect - '$line' - $result";
+
+ if [ $result -eq 0 ]
+ then
+ # Break out the loop on success
+ # otherwise roll on round and keep looking for a match
+ break;
+ fi
+ done
+
+ if [ $result -eq 0 ]
+ then
+ # Have we switched out of description mode?
+ if [ $in_description -eq 1 ] && [ "$expect" != "description" ] && [ "$expect" != "empty" ] && [ "$expect" != "comment" ]
+ then
+ # Yes, okay we need to backtrace one line and reanalyse
+ in_description=0;
+ i=$(( $i - $in_empty ));
+
+ # Reset the empty counter
+ in_empty=0;
+ continue;
+ fi
+
+ # Successful match, but on which line format
+ case $expect in
+ "header")
+ expecting="empty";
+
+ echo "$line" | grep -Eq "^\[ticket/[0-9]+\]$" && (
+ ticket=$(echo "$line" | sed 's,\[ticket/\([0-9]*\)\].*,\1,');
+ )
+ ;;
+ "empty")
+ # Description might have empty lines as spacing
+ expecting="footer description";
+ in_empty=$(($in_empty + 1));
+
+ if [ $in_description -eq 1 ]
+ then
+ expecting="$expecting empty";
+ fi
+ ;;
+ "description")
+ expecting="description empty";
+ in_description=1;
+ ;;
+ "footer")
+ expecting="footer eof";
+ if [ "$tickets" = "" ]
+ then
+ tickets="$line";
+ else
+ tickets="$tickets $line";
+ fi
+ ;;
+ "comment")
+ # Comments should expect the same thing again
+ ;;
+ *)
+ echo "Unrecognised token $expect" >&2;
+ quit 254;
+ ;;
+ esac
+
+ if [ "$expect" != "empty" ]
+ then
+ in_empty=0;
+ fi
+
+ debug 3 "Now expecting: $expecting";
+ else
+ # None of the expected line formats matched
+ # Guess we'll call it a day here then
+ echo "Syntax error on line $i:" >&2;
+ echo ">> $line" >&2;
+ echo -n "Expecting: " >&2;
+ echo "$expecting" | sed 's/ /, /g' >&2;
+ exit $err;
+ fi
+
+ i=$(( $i + 1 ));
+done
+
+# If EOF is expected exit cleanly
+echo "$expecting" | grep -q "eof" || (
+ # Unexpected EOF, error
+ echo "Unexpected EOF encountered" >&2;
+ quit $ERR_EOF;
+) && (
+ # Do post scan checks
+ if [ ! -z "$tickets" ]
+ then
+ # Check for duplicate tickets
+ dupes=$(echo "$tickets" | sed 's/ /\n/g' | sort | uniq -d);
+
+ if [ ! -z "$dupes" ]
+ then
+ echo "The following tickets are repeated:" >&2;
+ echo "$dupes" | sed 's/ /\n/g;s/^/* /g' >&2;
+ quit $ERR_FOOTER;
+ fi
+ fi
+ # Check the branch ticket is mentioned, doesn't make sense otherwise
+ if [ $ticket -gt 0 ]
+ then
+ echo "$tickets" | grep -Eq "\bPHPBB3-$ticket\b" || (
+ echo "Ticket ID [$ticket] of branch missing from list of tickets:" >&2;
+ echo "$tickets" | sed 's/ /\n/g;s/^/* /g' >&2;
+ quit $ERR_FOOTER;
+ ) || exit $?;
+ fi
+ # Got here okay exit to reality
+ exit 0;
+);
+exit $?;
diff --git a/git-tools/hooks/install b/git-tools/hooks/install
new file mode 100755
index 0000000000..a42c55a769
--- /dev/null
+++ b/git-tools/hooks/install
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# Script to install the git hooks
+# by symlinking them into the .git/hooks directory
+#
+# Usage (from within git-tools/hooks):
+# ./install
+
+dir=$(dirname $0)
+
+for file in $(ls $dir)
+do
+ if [ $file != "install" ] && [ $file != "uninstall" ]
+ then
+ ln -s "../../git-tools/hooks/$file" "$dir/../../.git/hooks/$file"
+ fi
+done
diff --git a/git-tools/hooks/pre-commit b/git-tools/hooks/pre-commit
index 9719b91746..4d03359773 100755
--- a/git-tools/hooks/pre-commit
+++ b/git-tools/hooks/pre-commit
@@ -27,6 +27,13 @@ fi
error=0
errors=""
+if ! which $PHP_BIN >/dev/null 2>&1
+then
+ echo "PHP Syntax check failed:"
+ echo "PHP binary does not exist or is not in path: $PHP_BIN"
+ exit 1
+fi
+
# dash does not support $'\n':
# http://forum.soft32.com/linux2/Bug-409179-DASH-Settings-IFS-work-properly-ftopict70039.html
IFS='
diff --git a/git-tools/hooks/prepare-commit-msg b/git-tools/hooks/prepare-commit-msg
index 033cb187c7..2bf25e58a4 100755
--- a/git-tools/hooks/prepare-commit-msg
+++ b/git-tools/hooks/prepare-commit-msg
@@ -30,5 +30,13 @@ branch="$(echo "$branch" | sed "s/refs\/heads\///g")"
# * also make sure the branch name begins with bug/ or feature/
if [ "$2" = "" ]
then
- echo "[$branch] $(cat "$1")" > "$1"
+ tail="";
+
+ # Branch is prefixed with 'ticket/', append ticket ID to message
+ if [ "$branch" != "${branch##ticket/}" ];
+ then
+ tail="\n\nPHPBB3-${branch##ticket/}";
+ fi
+
+ echo "[$branch]$tail $(cat "$1")" > "$1"
fi
diff --git a/git-tools/hooks/uninstall b/git-tools/hooks/uninstall
new file mode 100755
index 0000000000..1b3b7fd2c9
--- /dev/null
+++ b/git-tools/hooks/uninstall
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# Script to uninstall the git hooks
+#
+# Usage (from within git-tools/hooks):
+# ./uninstall
+
+dir=$(dirname $0)
+
+for file in $(ls $dir)
+do
+ if [ $file != "install" ] && [ $file != "uninstall" ]
+ then
+ rm -f "$dir/../../.git/hooks/$file"
+ fi
+done
diff --git a/phpBB/download/file.php b/phpBB/download/file.php
index 2154847865..97f4ff3c8a 100644
--- a/phpBB/download/file.php
+++ b/phpBB/download/file.php
@@ -31,6 +31,12 @@ else if (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'
if (isset($_GET['avatar']))
{
+ if (!defined('E_DEPRECATED'))
+ {
+ define('E_DEPRECATED', 8192);
+ }
+ error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
+
require($phpbb_root_path . 'config.' . $phpEx);
if (!defined('PHPBB_INSTALLED') || empty($dbms) || empty($acm_type))
@@ -61,7 +67,7 @@ if (isset($_GET['avatar']))
$avatar_group = false;
$exit = false;
- if ($filename[0] === 'g')
+ if (isset($filename[0]) && $filename[0] === 'g')
{
$avatar_group = true;
$filename = substr($filename, 1);
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index f2f1bd80e2..4d9b9f01e0 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -1642,6 +1642,9 @@ class acp_forums
delete_attachments('topic', $topic_ids, false);
+ // Delete shadow topics pointing to topics in this forum
+ delete_topic_shadows($forum_id);
+
// Before we remove anything we make sure we are able to adjust the post counts later. ;)
$sql = 'SELECT poster_id
FROM ' . POSTS_TABLE . '
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index 1f10893781..9e8a4c80b9 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -319,10 +319,7 @@ class acp_users
$server_url = generate_board_url();
- $user_actkey = gen_rand_string(10);
- $key_len = 54 - (strlen($server_url));
- $key_len = ($key_len > 6) ? $key_len : 6;
- $user_actkey = substr($user_actkey, 0, $key_len);
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
$email_template = ($user_row['user_type'] == USER_NORMAL) ? 'user_reactivate_account' : 'user_resend_inactive';
if ($user_row['user_type'] == USER_NORMAL)
diff --git a/phpBB/includes/cache.php b/phpBB/includes/cache.php
index 6b1e078ca4..b50fab4ca2 100644
--- a/phpBB/includes/cache.php
+++ b/phpBB/includes/cache.php
@@ -88,7 +88,14 @@ class cache extends acm
{
if ($unicode)
{
- $censors['match'][] = '#(?<![\p{Nd}\p{L}_])(' . str_replace('\*', '[\p{Nd}\p{L}_]*?', preg_quote($row['word'], '#')) . ')(?![\p{Nd}\p{L}_])#iu';
+ // Unescape the asterisk to simplify further conversions
+ $row['word'] = str_replace('\*', '*', preg_quote($row['word'], '#'));
+
+ // Replace the asterisk inside the pattern, at the start and at the end of it with regexes
+ $row['word'] = preg_replace(array('#(?<=[\p{Nd}\p{L}_])\*(?=[\p{Nd}\p{L}_])#iu', '#^\*#', '#\*$#'), array('([\x20]*?|[\p{Nd}\p{L}_-]*?)', '[\p{Nd}\p{L}_-]*?', '[\p{Nd}\p{L}_-]*?'), $row['word']);
+
+ // Generate the final substitution
+ $censors['match'][] = '#(?<![\p{Nd}\p{L}_-])(' . $row['word'] . ')(?![\p{Nd}\p{L}_-])#iu';
}
else
{
diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php
index e7b8742b05..21cacd730c 100644
--- a/phpBB/includes/captcha/plugins/captcha_abstract.php
+++ b/phpBB/includes/captcha/plugins/captcha_abstract.php
@@ -59,7 +59,7 @@ class phpbb_default_captcha
{
global $user;
- $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
// compute $seed % 0x7fffffff
@@ -235,7 +235,7 @@ class phpbb_default_captcha
{
global $db, $user;
- $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->confirm_id = md5(unique_id($user->ip));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
@@ -259,7 +259,7 @@ class phpbb_default_captcha
{
global $db, $user;
- $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
// compute $seed % 0x7fffffff
@@ -281,7 +281,7 @@ class phpbb_default_captcha
{
global $db, $user;
- $this->code = gen_rand_string(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
+ $this->code = gen_rand_string_friendly(mt_rand(CAPTCHA_MIN_CHARS, CAPTCHA_MAX_CHARS));
$this->seed = hexdec(substr(unique_id(), 4, 10));
$this->solved = 0;
// compute $seed % 0x7fffffff
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index bc3d721de5..36b9e18176 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -195,10 +195,27 @@ function set_config_count($config_name, $increment, $is_dynamic = false)
/**
* Generates an alphanumeric random string of given length
+*
+* @return string
*/
function gen_rand_string($num_chars = 8)
{
+ // [a, z] + [0, 9] = 36
+ return substr(strtoupper(base_convert(unique_id(), 16, 36)), 0, $num_chars);
+}
+
+/**
+* Generates a user-friendly alphanumeric random string of given length
+* We remove 0 and O so users cannot confuse those in passwords etc.
+*
+* @return string
+*/
+function gen_rand_string_friendly($num_chars = 8)
+{
$rand_str = unique_id();
+
+ // Remove Z and Y from the base_convert(), replace 0 with Z and O with Y
+ // [a, z] + [0, 9] - {z, y} = [a, z] + [0, 9] - {0, o} = 34
$rand_str = str_replace(array('0', 'O'), array('Z', 'Y'), strtoupper(base_convert($rand_str, 16, 34)));
return substr($rand_str, 0, $num_chars);
@@ -2519,6 +2536,11 @@ function build_url($strip_vars = false)
$key = $arguments[0];
unset($arguments[0]);
+ if ($key === '')
+ {
+ continue;
+ }
+
$query[$key] = implode('=', $arguments);
}
@@ -3440,26 +3462,110 @@ function short_ipv6($ip, $length)
/**
* Wrapper for php's checkdnsrr function.
*
-* The windows failover is from the php manual
-* Please make sure to check the return value for === true and === false, since NULL could
-* be returned too.
+* @param string $host Fully-Qualified Domain Name
+* @param string $type Resource record type to lookup
+* Supported types are: MX (default), A, AAAA, NS, TXT, CNAME
+* Other types may work or may not work
+*
+* @return mixed true if entry found,
+* false if entry not found,
+* null if this function is not supported by this environment
*
-* @return true if entry found, false if not, NULL if this function is not supported by this environment
+* Since null can also be returned, you probably want to compare the result
+* with === true or === false,
+*
+* @author bantu
*/
-function phpbb_checkdnsrr($host, $type = '')
+function phpbb_checkdnsrr($host, $type = 'MX')
{
- $type = (!$type) ? 'MX' : $type;
+ // The dot indicates to search the DNS root (helps those having DNS prefixes on the same domain)
+ if (substr($host, -1) == '.')
+ {
+ $host_fqdn = $host;
+ $host = substr($host, 0, -1);
+ }
+ else
+ {
+ $host_fqdn = $host . '.';
+ }
+ // $host has format some.host.example.com
+ // $host_fqdn has format some.host.example.com.
- // Call checkdnsrr() if available. This is also the case on Windows with PHP 5.3 or later.
- if (function_exists('checkdnsrr'))
+ // If we're looking for an A record we can use gethostbyname()
+ if ($type == 'A' && function_exists('gethostbyname'))
{
- // The dot indicates to search the DNS root (helps those having DNS prefixes on the same domain)
- return checkdnsrr($host . '.', $type);
+ return (@gethostbyname($host_fqdn) == $host_fqdn) ? false : true;
}
- else if (DIRECTORY_SEPARATOR == '\\' && function_exists('exec'))
+
+ // checkdnsrr() is available on Windows since PHP 5.3,
+ // but until 5.3.3 it only works for MX records
+ // See: http://bugs.php.net/bug.php?id=51844
+
+ // Call checkdnsrr() if
+ // we're looking for an MX record or
+ // we're not on Windows or
+ // we're running a PHP version where #51844 has been fixed
+
+ // checkdnsrr() supports AAAA since 5.0.0
+ // checkdnsrr() supports TXT since 5.2.4
+ if (
+ ($type == 'MX' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.3', '>=')) &&
+ ($type != 'AAAA' || version_compare(PHP_VERSION, '5.0.0', '>=')) &&
+ ($type != 'TXT' || version_compare(PHP_VERSION, '5.2.4', '>=')) &&
+ function_exists('checkdnsrr')
+ )
{
- // @exec('nslookup -retry=1 -timout=1 -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host), $output);
- @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host) . '.', $output);
+ return checkdnsrr($host_fqdn, $type);
+ }
+
+ // dns_get_record() is available since PHP 5; since PHP 5.3 also on Windows,
+ // but on Windows it does not work reliable for AAAA records before PHP 5.3.1
+
+ // Call dns_get_record() if
+ // we're not looking for an AAAA record or
+ // we're not on Windows or
+ // we're running a PHP version where AAAA lookups work reliable
+ if (
+ ($type != 'AAAA' || DIRECTORY_SEPARATOR != '\\' || version_compare(PHP_VERSION, '5.3.1', '>=')) &&
+ function_exists('dns_get_record')
+ )
+ {
+ // dns_get_record() expects an integer as second parameter
+ // We have to convert the string $type to the corresponding integer constant.
+ $type_constant = 'DNS_' . $type;
+ $type_param = (defined($type_constant)) ? constant($type_constant) : DNS_ANY;
+
+ // dns_get_record() might throw E_WARNING and return false for records that do not exist
+ $resultset = @dns_get_record($host_fqdn, $type_param);
+
+ if (empty($resultset) || !is_array($resultset))
+ {
+ return false;
+ }
+ else if ($type_param == DNS_ANY)
+ {
+ // $resultset is a non-empty array
+ return true;
+ }
+
+ foreach ($resultset as $result)
+ {
+ if (
+ isset($result['host']) && $result['host'] == $host &&
+ isset($result['type']) && $result['type'] == $type
+ )
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ // If we're on Windows we can still try to call nslookup via exec() as a last resort
+ if (DIRECTORY_SEPARATOR == '\\' && function_exists('exec'))
+ {
+ @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host_fqdn), $output);
// If output is empty, the nslookup failed
if (empty($output))
@@ -3469,15 +3575,66 @@ function phpbb_checkdnsrr($host, $type = '')
foreach ($output as $line)
{
- if (!trim($line))
+ $line = trim($line);
+
+ if (empty($line))
{
continue;
}
- // Valid records begin with host name:
- if (strpos($line, $host) === 0)
+ // Squash tabs and multiple whitespaces to a single whitespace.
+ $line = preg_replace('/\s+/', ' ', $line);
+
+ switch ($type)
{
- return true;
+ case 'MX':
+ if (stripos($line, "$host MX") === 0)
+ {
+ return true;
+ }
+ break;
+
+ case 'NS':
+ if (stripos($line, "$host nameserver") === 0)
+ {
+ return true;
+ }
+ break;
+
+ case 'TXT':
+ if (stripos($line, "$host text") === 0)
+ {
+ return true;
+ }
+ break;
+
+ case 'CNAME':
+ if (stripos($line, "$host canonical name") === 0)
+ {
+ return true;
+ }
+
+ default:
+ case 'A':
+ case 'AAAA':
+ if (!empty($host_matches))
+ {
+ // Second line
+ if (stripos($line, "Address: ") === 0)
+ {
+ return true;
+ }
+ else
+ {
+ $host_matches = false;
+ }
+ }
+ else if (stripos($line, "Name: $host") === 0)
+ {
+ // First line
+ $host_matches = true;
+ }
+ break;
}
}
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 89892feb30..3178d35c34 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -1125,53 +1125,65 @@ function delete_attachments($mode, $ids, $resync = true)
}
/**
-* Remove topic shadows
+* Deletes shadow topics pointing to a specified forum.
+*
+* @param int $forum_id The forum id
+* @param string $sql_more Additional WHERE statement, e.g. t.topic_time < (time() - 1234)
+* @param bool $auto_sync Will call sync() if this is true
+*
+* @return array Array with affected forums
+*
+* @author bantu
*/
-function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true)
+function delete_topic_shadows($forum_id, $sql_more = '', $auto_sync = true)
{
- $where = (is_array($forum_id)) ? 'AND ' . $db->sql_in_set('t.forum_id', array_map('intval', $forum_id)) : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : '');
+ global $db;
- switch ($db->sql_layer)
+ if (!$forum_id)
{
- case 'mysql4':
- case 'mysqli':
- $sql = 'DELETE t.*
- FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2
- WHERE t.topic_moved_id = t2.topic_id
- AND t.topic_time < ' . (time() - $max_age)
- . $where;
- $db->sql_query($sql);
- break;
+ // Nothing to do.
+ return;
+ }
- default:
- $sql = 'SELECT t.topic_id
- FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2
- WHERE t.topic_moved_id = t2.topic_id
- AND t.topic_time < ' . (time() - $max_age)
- . $where;
- $result = $db->sql_query($sql);
+ // Set of affected forums we have to resync
+ $sync_forum_ids = array();
- $topic_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $topic_ids[] = $row['topic_id'];
- }
- $db->sql_freeresult($result);
+ // Amount of topics we select and delete at once.
+ $batch_size = 500;
- if (sizeof($topic_ids))
- {
- $sql = 'DELETE FROM ' . TOPICS_TABLE . '
- WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
- $db->sql_query($sql);
- }
- break;
+ do
+ {
+ $sql = 'SELECT t2.forum_id, t2.topic_id
+ FROM ' . TOPICS_TABLE . ' t2, ' . TOPICS_TABLE . ' t
+ WHERE t2.topic_moved_id = t.topic_id
+ AND t.forum_id = ' . (int) $forum_id . '
+ ' . (($sql_more) ? 'AND ' . $sql_more : '');
+ $result = $db->sql_query_limit($sql, $batch_size);
+
+ $topic_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (!empty($topic_ids))
+ {
+ $sql = 'DELETE FROM ' . TOPICS_TABLE . '
+ WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
+ $db->sql_query($sql);
+ }
}
+ while (sizeof($topic_ids) == $batch_size);
if ($auto_sync)
{
- $where_type = ($forum_id) ? 'forum_id' : '';
- sync('forum', $where_type, $forum_id, true, true);
+ sync('forum', 'forum_id', $sync_forum_ids, true, true);
}
+
+ return $sync_forum_ids;
}
/**
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index f6f90575d4..5e25648eb8 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -2537,7 +2537,7 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
if ($mode == 'post' || $mode == 'reply' || $mode == 'quote')
{
// Mark this topic as posted to
- markread('post', $data['forum_id'], $data['topic_id'], $data['post_time']);
+ markread('post', $data['forum_id'], $data['topic_id']);
}
// Mark this topic as read
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 0b26f28864..d3594196b7 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -766,7 +766,8 @@ function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reas
if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) &&
(strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2))
{
- $ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0]));
+ $time_offset = (isset($user->timezone) && isset($user->dst)) ? (int) $user->timezone + (int) $user->dst : 0;
+ $ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0]) - $time_offset);
}
else
{
@@ -1229,22 +1230,39 @@ function user_unban($mode, $ban)
}
/**
-* Whois facility
+* Internet Protocol Address Whois
+* RFC3912: WHOIS Protocol Specification
*
-* @link http://tools.ietf.org/html/rfc3912 RFC3912: WHOIS Protocol Specification
+* @param string $ip Ip address, either IPv4 or IPv6.
+*
+* @return string Empty string if not a valid ip address.
+* Otherwise make_clickable()'ed whois result.
*/
function user_ipwhois($ip)
{
- $ipwhois = '';
+ if (empty($ip))
+ {
+ return '';
+ }
- // Check IP
- // Only supporting IPv4 at the moment...
- if (empty($ip) || !preg_match(get_preg_expression('ipv4'), $ip))
+ if (preg_match(get_preg_expression('ipv4'), $ip))
+ {
+ // IPv4 address
+ $whois_host = 'whois.arin.net.';
+ }
+ else if (preg_match(get_preg_expression('ipv6'), $ip))
+ {
+ // IPv6 address
+ $whois_host = 'whois.sixxs.net.';
+ }
+ else
{
return '';
}
- if (($fsk = @fsockopen('whois.arin.net', 43)))
+ $ipwhois = '';
+
+ if (($fsk = @fsockopen($whois_host, 43)))
{
// CRLF as per RFC3912
fputs($fsk, "$ip\r\n");
@@ -1257,7 +1275,7 @@ function user_ipwhois($ip)
$match = array();
- // Test for referrals from ARIN to other whois databases, roll on rwhois
+ // Test for referrals from $whois_host to other whois databases, roll on rwhois
if (preg_match('#ReferralServer: whois://(.+)#im', $ipwhois, $match))
{
if (strpos($match[1], ':') !== false)
@@ -1285,7 +1303,7 @@ function user_ipwhois($ip)
@fclose($fsk);
}
- // Use the result from ARIN if we don't get any result here
+ // Use the result from $whois_host if we don't get any result here
$ipwhois = (empty($buffer)) ? $ipwhois : $buffer;
}
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index 80c3559649..d5551f5114 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -1048,6 +1048,35 @@ function mcp_fork_topic($topic_ids)
$total_posts = 0;
$new_topic_id_list = array();
+ if ($topic_data['enable_indexing'])
+ {
+ // Select the search method and do some additional checks to ensure it can actually be utilised
+ $search_type = basename($config['search_type']);
+
+ if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
+ {
+ trigger_error('NO_SUCH_SEARCH_MODULE');
+ }
+
+ if (!class_exists($search_type))
+ {
+ include("{$phpbb_root_path}includes/search/$search_type.$phpEx");
+ }
+
+ $error = false;
+ $search = new $search_type($error);
+ $search_mode = 'post';
+
+ if ($error)
+ {
+ trigger_error($error);
+ }
+ }
+ else
+ {
+ $search_type = false;
+ }
+
foreach ($topic_data as $topic_id => $topic_row)
{
$sql_ary = array(
@@ -1158,6 +1187,12 @@ function mcp_fork_topic($topic_ids)
// Copy whether the topic is dotted
markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']);
+ if ($search_type)
+ {
+ $search->index($search_mode, $sql_ary['post_id'], $sql_ary['post_text'], $sql_ary['post_subject'], $sql_ary['poster_id'], ($topic_row['topic_type'] == POST_GLOBAL) ? 0 : $to_forum_id);
+ $search_mode = 'reply'; // After one we index replies
+ }
+
// Copy Attachments
if ($row['post_attachment'])
{
diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php
index c89e92711e..727e3aaffb 100644
--- a/phpBB/includes/search/fulltext_native.php
+++ b/phpBB/includes/search/fulltext_native.php
@@ -83,7 +83,9 @@ class fulltext_native extends search_backend
{
global $db, $user, $config;
- $keywords = trim($this->cleanup($keywords, '+-|()*'));
+ $tokens = '+-|()*';
+
+ $keywords = trim($this->cleanup($keywords, $tokens));
// allow word|word|word without brackets
if ((strpos($keywords, ' ') === false) && (strpos($keywords, '|') !== false) && (strpos($keywords, '(') === false))
@@ -114,6 +116,15 @@ class fulltext_native extends search_backend
case ' ':
$keywords[$i] = '|';
break;
+ case '*':
+ if ($i === 0 || ($keywords[$i - 1] !== '*' && strcspn($keywords[$i - 1], $tokens) === 0))
+ {
+ if ($i === $n - 1 || ($keywords[$i + 1] !== '*' && strcspn($keywords[$i + 1], $tokens) === 0))
+ {
+ $keywords = substr($keywords, 0, $i) . substr($keywords, $i + 1);
+ }
+ }
+ break;
}
}
else
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index e157053e61..79023cc7bc 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -1831,7 +1831,7 @@ class user extends session
// Is load exceeded?
if ($config['limit_load'] && $this->load !== false)
{
- if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN'))
+ if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !defined('IN_ADMIN'))
{
// Set board disabled to true to let the admins/mods get the proper notification
$config['board_disable'] = '1';
diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php
index 363a4803b6..4fd25b7d1c 100644
--- a/phpBB/includes/ucp/ucp_profile.php
+++ b/phpBB/includes/ucp/ucp_profile.php
@@ -141,10 +141,7 @@ class ucp_profile
$server_url = generate_board_url();
- $user_actkey = gen_rand_string(10);
- $key_len = 54 - (strlen($server_url));
- $key_len = ($key_len > 6) ? $key_len : 6;
- $user_actkey = substr($user_actkey, 0, $key_len);
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
$messenger = new messenger(false);
diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php
index 9656a4a3af..7fd99da55a 100644
--- a/phpBB/includes/ucp/ucp_register.php
+++ b/phpBB/includes/ucp/ucp_register.php
@@ -286,11 +286,7 @@ class ucp_register
$config['require_activation'] == USER_ACTIVATION_SELF ||
$config['require_activation'] == USER_ACTIVATION_ADMIN) && $config['email_enable'])
{
- $user_actkey = gen_rand_string(10);
- $key_len = 54 - (strlen($server_url));
- $key_len = ($key_len < 6) ? 6 : $key_len;
- $user_actkey = substr($user_actkey, 0, $key_len);
-
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
$user_type = USER_INACTIVE;
$user_inactive_reason = INACTIVE_REGISTER;
$user_inactive_time = time();
diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php
index f9b792de20..cb89ad99be 100644
--- a/phpBB/includes/ucp/ucp_remind.php
+++ b/phpBB/includes/ucp/ucp_remind.php
@@ -79,10 +79,10 @@ class ucp_remind
// Make password at least 8 characters long, make it longer if admin wants to.
// gen_rand_string() however has a limit of 12 or 13.
- $user_password = gen_rand_string(max(8, rand((int) $config['min_pass_chars'], (int) $config['max_pass_chars'])));
+ $user_password = gen_rand_string_friendly(max(8, mt_rand((int) $config['min_pass_chars'], (int) $config['max_pass_chars'])));
// For the activation key a random length between 6 and 10 will do.
- $user_actkey = gen_rand_string(rand(6, 10));
+ $user_actkey = gen_rand_string(mt_rand(6, 10));
$sql = 'UPDATE ' . USERS_TABLE . "
SET user_newpasswd = '" . $db->sql_escape(phpbb_hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "'
diff --git a/phpBB/install/database_update.php b/phpBB/install/database_update.php
index 83bbbf4577..fec09f89db 100644
--- a/phpBB/install/database_update.php
+++ b/phpBB/install/database_update.php
@@ -1749,6 +1749,52 @@ function change_database_data(&$no_updates, $version)
_sql($sql, $errored, $error_ary);
// end Bing Bot addition
+ // Delete shadow topics pointing to not existing topics
+ $batch_size = 500;
+
+ // Set of affected forums we have to resync
+ $sync_forum_ids = array();
+
+ do
+ {
+ $sql_array = array(
+ 'SELECT' => 't1.topic_id, t1.forum_id',
+ 'FROM' => array(
+ TOPICS_TABLE => 't1',
+ ),
+ 'LEFT_JOIN' => array(
+ array(
+ 'FROM' => array(TOPICS_TABLE => 't2'),
+ 'ON' => 't1.topic_moved_id = t2.topic_id',
+ ),
+ ),
+ 'WHERE' => 't1.topic_moved_id <> 0
+ AND t2.topic_id IS NULL',
+ );
+ $sql = $db->sql_build_query('SELECT', $sql_array);
+ $result = $db->sql_query_limit($sql, $batch_size);
+
+ $topic_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $topic_ids[] = (int) $row['topic_id'];
+
+ $sync_forum_ids[(int) $row['forum_id']] = (int) $row['forum_id'];
+ }
+ $db->sql_freeresult($result);
+
+ if (!empty($topic_ids))
+ {
+ $sql = 'DELETE FROM ' . TOPICS_TABLE . '
+ WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
+ $db->sql_query($sql);
+ }
+ }
+ while (sizeof($topic_ids) == $batch_size);
+
+ // Sync the forums we have deleted shadow topics from.
+ sync('forum', 'forum_id', $sync_forum_ids, true, true);
+
$no_updates = false;
break;
}
diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php
index 8b12a926b0..ac0ddf1b73 100644
--- a/phpBB/language/en/acp/board.php
+++ b/phpBB/language/en/acp/board.php
@@ -177,8 +177,8 @@ $lang = array_merge($lang, array(
'MIN_CHAR_LIMIT_EXPLAIN' => 'The minimum number of characters the user need to enter within a post/private message.',
'POSTING' => 'Posting',
'POSTS_PER_PAGE' => 'Posts per page',
- 'QUOTE_DEPTH_LIMIT' => 'Maximum nested quotes per post',
- 'QUOTE_DEPTH_LIMIT_EXPLAIN' => 'Maximum number of nested quotes in a post. Set to 0 for unlimited depth.',
+ 'QUOTE_DEPTH_LIMIT' => 'Maximum nesting depth for quotes',
+ 'QUOTE_DEPTH_LIMIT_EXPLAIN' => 'Maximum quote nesting depth in a post. Set to 0 for unlimited depth.',
'SMILIES_LIMIT' => 'Maximum smilies per post',
'SMILIES_LIMIT_EXPLAIN' => 'Maximum number of smilies in a post. Set to 0 for unlimited smilies.',
'SMILIES_PER_PAGE' => 'Smilies per page',
diff --git a/phpBB/styles/prosilver/theme/bidi.css b/phpBB/styles/prosilver/theme/bidi.css
index 109312ac1b..f441784d85 100644
--- a/phpBB/styles/prosilver/theme/bidi.css
+++ b/phpBB/styles/prosilver/theme/bidi.css
@@ -236,6 +236,7 @@
}
.rtl a.top2 {
+ background-position: 100% 50%;
padding-left: 0;
padding-right: 15px;
}
diff --git a/tests/all_tests.php b/tests/all_tests.php
index 7894d688ee..bae7725ee7 100644
--- a/tests/all_tests.php
+++ b/tests/all_tests.php
@@ -24,6 +24,8 @@ require_once 'template/all_tests.php';
require_once 'text_processing/all_tests.php';
require_once 'dbal/all_tests.php';
require_once 'regex/all_tests.php';
+require_once 'network/all_tests.php';
+require_once 'random/all_tests.php';
// exclude the test directory from code coverage reports
PHPUnit_Util_Filter::addDirectoryToFilter('./');
@@ -46,6 +48,8 @@ class phpbb_all_tests
$suite->addTest(phpbb_text_processing_all_tests::suite());
$suite->addTest(phpbb_dbal_all_tests::suite());
$suite->addTest(phpbb_regex_all_tests::suite());
+ $suite->addTest(phpbb_network_all_tests::suite());
+ $suite->addTest(phpbb_random_all_tests::suite());
return $suite;
}
diff --git a/tests/network/all_tests.php b/tests/network/all_tests.php
new file mode 100644
index 0000000000..b500647f81
--- /dev/null
+++ b/tests/network/all_tests.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2010 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_network_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'network/checkdnsrr.php';
+
+class phpbb_network_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Network Functions');
+
+ $suite->addTestSuite('phpbb_network_checkdnsrr_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_network_all_tests::main')
+{
+ phpbb_network_all_tests::main();
+}
diff --git a/tests/network/checkdnsrr.php b/tests/network/checkdnsrr.php
new file mode 100644
index 0000000000..57fe2761cc
--- /dev/null
+++ b/tests/network/checkdnsrr.php
@@ -0,0 +1,63 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2010 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/functions.php';
+
+class phpbb_network_checkdnsrr_test extends phpbb_test_case
+{
+ public function data_provider()
+ {
+ return array(
+ // Existing MX record
+ array('phpbb.com', 'MX', true),
+
+ // Non-existing MX record
+ array('does-not-exist.phpbb.com', 'MX', false),
+
+ // Existing A record
+ array('www.phpbb.com', 'A', true),
+
+ // Non-existing A record
+ array('does-not-exist.phpbb.com', 'A', false),
+
+ // Existing AAAA record
+ array('www.six.heise.de', 'AAAA', true),
+
+ // Non-existing AAAA record
+ array('does-not-exist.phpbb.com', 'AAAA', false),
+
+ // Existing CNAME record
+ array('news.cnet.com', 'CNAME', true),
+
+ // Non-existing CNAME record
+ array('does-not-exist.phpbb.com', 'CNAME', false),
+
+ // Existing NS record
+ array('phpbb.com', 'NS', true),
+
+ // Non-existing NS record
+ array('does-not-exist', 'NS', false),
+
+ // Existing TXT record
+ array('phpbb.com', 'TXT', true),
+
+ // Non-existing TXT record
+ array('does-not-exist', 'TXT', false),
+ );
+ }
+
+ /**
+ * @dataProvider data_provider
+ */
+ public function test_checkdnsrr($host, $type, $expected)
+ {
+ $this->assertEquals($expected, phpbb_checkdnsrr($host, $type));
+ }
+}
diff --git a/tests/random/all_tests.php b/tests/random/all_tests.php
new file mode 100644
index 0000000000..c6ffe78024
--- /dev/null
+++ b/tests/random/all_tests.php
@@ -0,0 +1,40 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2010 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+if (!defined('PHPUnit_MAIN_METHOD'))
+{
+ define('PHPUnit_MAIN_METHOD', 'phpbb_random_all_tests::main');
+}
+
+require_once 'test_framework/framework.php';
+require_once 'PHPUnit/TextUI/TestRunner.php';
+
+require_once 'random/gen_rand_string.php';
+
+class phpbb_random_all_tests
+{
+ public static function main()
+ {
+ PHPUnit_TextUI_TestRunner::run(self::suite());
+ }
+
+ public static function suite()
+ {
+ $suite = new PHPUnit_Framework_TestSuite('phpBB Random Functions');
+
+ $suite->addTestSuite('phpbb_random_gen_rand_string_test');
+
+ return $suite;
+ }
+}
+
+if (PHPUnit_MAIN_METHOD == 'phpbb_random_all_tests::main')
+{
+ phpbb_random_all_tests::main();
+}
diff --git a/tests/random/gen_rand_string.php b/tests/random/gen_rand_string.php
new file mode 100644
index 0000000000..cd58d14ed3
--- /dev/null
+++ b/tests/random/gen_rand_string.php
@@ -0,0 +1,63 @@
+<?php
+/**
+*
+* @package testing
+* @copyright (c) 2010 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+require_once 'test_framework/framework.php';
+require_once '../phpBB/includes/functions.php';
+
+class phpbb_random_gen_rand_string_test extends phpbb_test_case
+{
+ const TEST_COUNT = 100;
+ const MIN_STRING_LENGTH = 1;
+ const MAX_STRING_LENGTH = 15;
+
+ public function setUp()
+ {
+ global $config;
+
+ if (!is_array($config))
+ {
+ $config = array();
+ }
+
+ $config['rand_seed'] = '';
+ $config['rand_seed_last_update'] = time() + 600;
+ }
+
+ public function test_gen_rand_string()
+ {
+ for ($tests = 0; $tests <= self::TEST_COUNT; ++$tests)
+ {
+ for ($num_chars = self::MIN_STRING_LENGTH; $num_chars <= self::MAX_STRING_LENGTH; ++$num_chars)
+ {
+ $random_string = gen_rand_string($num_chars);
+ $random_string_length = strlen($random_string);
+
+ $this->assertTrue($random_string_length >= self::MIN_STRING_LENGTH);
+ $this->assertTrue($random_string_length <= $num_chars);
+ $this->assertRegExp('#^[A-Z0-9]+$#', $random_string);
+ }
+ }
+ }
+
+ public function test_gen_rand_string_friendly()
+ {
+ for ($tests = 0; $tests <= self::TEST_COUNT; ++$tests)
+ {
+ for ($num_chars = self::MIN_STRING_LENGTH; $num_chars <= self::MAX_STRING_LENGTH; ++$num_chars)
+ {
+ $random_string = gen_rand_string_friendly($num_chars);
+ $random_string_length = strlen($random_string);
+
+ $this->assertTrue($random_string_length >= self::MIN_STRING_LENGTH);
+ $this->assertTrue($random_string_length <= $num_chars);
+ $this->assertRegExp('#^[A-NP-Z1-9]+$#', $random_string);
+ }
+ }
+ }
+}