diff options
51 files changed, 1001 insertions, 135 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/adm/index.php b/phpBB/adm/index.php index 26f934f6bf..4c568cf441 100644 --- a/phpBB/adm/index.php +++ b/phpBB/adm/index.php @@ -533,7 +533,7 @@ function validate_config_vars($config_vars, &$cfg_array, &$error)  				// Check if the path is writable  				if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath')  				{ -					if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !@is_writable($phpbb_root_path . $cfg_array[$config_name])) +					if (file_exists($phpbb_root_path . $cfg_array[$config_name]) && !phpbb_is_writable($phpbb_root_path . $cfg_array[$config_name]))  					{  						$error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]);  					} diff --git a/phpBB/adm/style/admin.css b/phpBB/adm/style/admin.css index 5f1f01c0a9..4c3fa51af3 100644 --- a/phpBB/adm/style/admin.css +++ b/phpBB/adm/style/admin.css @@ -670,14 +670,10 @@ legend {  	position: relative;  	text-transform: none;  	line-height: 1.2em; -	top: 0; +	top: -.2em;  	vertical-align: middle;  } -/* Hide from macIE \*/ -legend { top: -1.2em; } -/* end */ -  * html legend {  	margin: 0 0 -10px -7px;  	line-height: 1em; diff --git a/phpBB/download/file.php b/phpBB/download/file.php index 2154847865..1f2cee4d95 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)) @@ -42,6 +48,7 @@ if (isset($_GET['avatar']))  	require($phpbb_root_path . 'includes/cache.' . $phpEx);  	require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);  	require($phpbb_root_path . 'includes/constants.' . $phpEx); +	require($phpbb_root_path . 'includes/functions.' . $phpEx);  	$db = new $sql_db();  	$cache = new cache(); @@ -61,7 +68,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/acm/acm_file.php b/phpBB/includes/acm/acm_file.php index 5a758aa2bb..5c1876d006 100644 --- a/phpBB/includes/acm/acm_file.php +++ b/phpBB/includes/acm/acm_file.php @@ -78,8 +78,14 @@ class acm  		if (!$this->_write('data_global'))  		{ +			if (!function_exists('phpbb_is_writable')) +			{ +				global $phpbb_root_path; +				include($phpbb_root_path . 'includes/functions.' . $phpEx); +			} +  			// Now, this occurred how often? ... phew, just tell the user then... -			if (!@is_writable($this->cache_dir)) +			if (!phpbb_is_writable($this->cache_dir))  			{  				// We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload())  				die($this->cache_dir . ' is NOT writable.'); @@ -707,7 +713,13 @@ class acm  	*/  	function remove_file($filename, $check = false)  	{ -		if ($check && !@is_writable($this->cache_dir)) +		if (!function_exists('phpbb_is_writable')) +		{ +			global $phpbb_root_path, $phpEx; +			include($phpbb_root_path . 'includes/functions.' . $phpEx); +		} + +		if ($check && !phpbb_is_writable($this->cache_dir))  		{  			// E_USER_ERROR - not using language entry - intended.  			trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); diff --git a/phpBB/includes/acm/acm_memory.php b/phpBB/includes/acm/acm_memory.php index efbfd4dd62..2936ea0bae 100644 --- a/phpBB/includes/acm/acm_memory.php +++ b/phpBB/includes/acm/acm_memory.php @@ -407,7 +407,13 @@ class acm_memory  	*/  	function remove_file($filename, $check = false)  	{ -		if ($check && !@is_writable($this->cache_dir)) +		if (!function_exists('phpbb_is_writable')) +		{ +			global $phpbb_root_path, $phpEx; +			include($phpbb_root_path . 'includes/functions.' . $phpEx); +		} + +		if ($check && !phpbb_is_writable($this->cache_dir))  		{  			// E_USER_ERROR - not using language entry - intended.  			trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index 980558c830..fc5f44e14f 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1222,7 +1222,7 @@ class acp_attachments  			return;  		} -		if (!is_writable($phpbb_root_path . $upload_dir)) +		if (!phpbb_is_writable($phpbb_root_path . $upload_dir))  		{  			$error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir);  			return; 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_groups.php b/phpBB/includes/acp/acp_groups.php index 3df61ff4e2..60512c67b8 100644 --- a/phpBB/includes/acp/acp_groups.php +++ b/phpBB/includes/acp/acp_groups.php @@ -49,7 +49,7 @@ class acp_groups  		// Clear some vars -		$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; +		$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false;  		$group_row = array();  		// Grab basic data for group, if group_id is set and exists diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 3310560c73..2ccc728031 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -748,7 +748,7 @@ parse_css_file = {PARSE_CSS_FILE}  			$additional = '';  			// If the template is stored on the filesystem try to write the file else store it in the database -			if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && @is_writable($file)) +			if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && phpbb_is_writable($file))  			{  				if (!($fp = @fopen($file, 'wb')))  				{ @@ -1155,7 +1155,7 @@ parse_css_file = {PARSE_CSS_FILE}  			$message = $user->lang['THEME_UPDATED'];  			// If the theme is stored on the filesystem try to write the file else store it in the database -			if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file)) +			if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && phpbb_is_writable($file))  			{  				if (!($fp = @fopen($file, 'wb')))  				{ @@ -2040,23 +2040,18 @@ parse_css_file = {PARSE_CSS_FILE}  			{  				case 'tar':  					$ext = '.tar'; -					$mimetype = 'x-tar'; -					$compress = 'compress_tar';  				break;  				case 'zip':  					$ext = '.zip'; -					$mimetype = 'zip';  				break;  				case 'tar.gz':  					$ext = '.tar.gz'; -					$mimetype = 'x-gzip';  				break;  				case 'tar.bz2':  					$ext = '.tar.bz2'; -					$mimetype = 'x-bzip2';  				break;  				default: @@ -2246,7 +2241,7 @@ parse_css_file = {PARSE_CSS_FILE}  			{  				// a rather elaborate check we have to do here once to avoid trouble later  				$check = "{$phpbb_root_path}styles/" . $style_row["{$mode}_path"] . (($mode === 'theme') ? '/theme/stylesheet.css' : '/template'); -				if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !@is_writable($check))) +				if (($style_row["{$mode}_storedb"] != $store_db) && !$store_db && ($safe_mode || !phpbb_is_writable($check)))  				{  					$error[] = $user->lang['EDIT_' . strtoupper($mode) . '_STORED_DB'];  					$store_db = 1; @@ -2326,7 +2321,7 @@ parse_css_file = {PARSE_CSS_FILE}  						{  							$theme_data = $this->db_theme_data($style_row);  						} -						else if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css")) +						else if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['theme_path']}/theme/stylesheet.css"))  						{  							$store_db = 1;  							$theme_data = $style_row['theme_data']; @@ -2357,7 +2352,7 @@ parse_css_file = {PARSE_CSS_FILE}  						}  						else  						{ -							if (!$store_db && !$safe_mode && @is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template")) +							if (!$store_db && !$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$style_row['template_path']}/template"))  							{  								$err = $this->store_in_fs('template', $style_row['template_id']);  								if ($err) @@ -2531,13 +2526,21 @@ parse_css_file = {PARSE_CSS_FILE}  		// Match CSS imports  		$matches = array(); -		preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); +		preg_match_all('/@import url\((["\'])(.*)\1\);/i', $stylesheet, $matches); + +		// remove commented stylesheets (very simple parser, allows only whitespace +		// around an @import statement) +		preg_match_all('#/\*\s*@import url\((["\'])(.*)\1\);\s\*/#i', $stylesheet, $commented); +		$matches[2] = array_diff($matches[2], $commented[2]);  		if (sizeof($matches))  		{  			foreach ($matches[0] as $idx => $match)  			{ -				$stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet); +				if (isset($matches[2][$idx])) +				{ +					$stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[2][$idx]), $stylesheet); +				}  			}  		} @@ -3728,7 +3731,7 @@ parse_css_file = {PARSE_CSS_FILE}  		$store_db = 0;  		$error = array(); -		if (!$safe_mode && @is_writable("{$phpbb_root_path}styles/{$path}/template")) +		if (!$safe_mode && phpbb_is_writable("{$phpbb_root_path}styles/{$path}/template"))  		{  			$sql = 'SELECT *  					FROM ' . STYLES_TEMPLATE_DATA_TABLE . " diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php index 1f10893781..6be0760be0 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) @@ -1701,7 +1698,7 @@ class acp_users  				include($phpbb_root_path . 'includes/functions_display.' . $phpEx);  				include($phpbb_root_path . 'includes/functions_user.' . $phpEx); -				$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; +				$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false;  				if ($submit)  				{ 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..c4ff998e69 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); @@ -701,7 +718,7 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)  			clearstatcache(); -			if (is_readable($filename) && is_writable($filename)) +			if (is_readable($filename) && phpbb_is_writable($filename))  			{  				break;  			} @@ -711,7 +728,7 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)  			clearstatcache(); -			if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) +			if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))  			{  				break;  			} @@ -721,7 +738,7 @@ function phpbb_chmod($filename, $perms = CHMOD_READ)  			clearstatcache(); -			if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || is_writable($filename))) +			if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || phpbb_is_writable($filename)))  			{  				break;  			} @@ -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_compress.php b/phpBB/includes/functions_compress.php index f422eaa8c1..455debd939 100644 --- a/phpBB/includes/functions_compress.php +++ b/phpBB/includes/functions_compress.php @@ -53,13 +53,18 @@ class compress  			$filelist = filelist("$phpbb_root_path$src", '', '*');  			krsort($filelist); +			/** +			* Commented out, as adding the folders produces corrupted archives  			if ($src_path)  			{  				$this->data($src_path, '', true, stat("$phpbb_root_path$src"));  			} +			*/  			foreach ($filelist as $path => $file_ary)  			{ +				/** +				* Commented out, as adding the folders produces corrupted archives  				if ($path)  				{  					// Same as for src_path @@ -68,6 +73,7 @@ class compress  					$this->data("$src_path$path", '', true, stat("$phpbb_root_path$src$path"));  				} +				*/  				foreach ($file_ary as $file)  				{ diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php index c035fd3739..9e26043b39 100644 --- a/phpBB/includes/functions_convert.php +++ b/phpBB/includes/functions_convert.php @@ -2306,7 +2306,7 @@ function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $sour  		}  	} -	if (!is_writable($path)) +	if (!phpbb_is_writable($path))  	{  		@chmod($path, 0777);  	} @@ -2341,7 +2341,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_  		@chmod($trg_path, 0777);  	} -	if (!@is_writable($trg_path)) +	if (!phpbb_is_writable($trg_path))  	{  		$bad_dirs[] = path($config['script_path']) . $trg;  	} @@ -2408,7 +2408,7 @@ function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_  				@chmod($trg_path . $dir, 0777);  			} -			if (!@is_writable($trg_path . $dir)) +			if (!phpbb_is_writable($trg_path . $dir))  			{  				$bad_dirs[] = $trg . $dir;  				$bad_dirs[] = $trg_path . $dir; 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_privmsgs.php b/phpBB/includes/functions_privmsgs.php index c4cbb7ca1e..4c34bc92ca 100644 --- a/phpBB/includes/functions_privmsgs.php +++ b/phpBB/includes/functions_privmsgs.php @@ -1380,6 +1380,9 @@ function submit_pm($mode, $subject, &$data, $put_in_outbox = true)  		}  	} +	// First of all make sure the subject are having the correct length. +	$subject = truncate_string($subject); +  	$db->sql_transaction('begin');  	$sql = ''; diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index fa1cc98e10..3937cf9c21 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -543,8 +543,9 @@ class custom_profile  				else if ($day && $month && $year)  				{  					global $user; -					// d/m/y 00:00 GMT isn't necessarily on the same d/m/y in the user's timezone, so add the timezone seconds -					return $user->format_date(gmmktime(0, 0, 0, $month, $day, $year) + $user->timezone + $user->dst, $user->lang['DATE_FORMAT'], true); +					// Date should display as the same date for every user regardless of timezone, so remove offset +					// to compensate for the offset added by user::format_date() +					return $user->format_date(gmmktime(0, 0, 0, $month, $day, $year) - ($user->timezone + $user->dst), $user->lang['DATE_FORMAT'], true);  				}  				return $value; diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index 0b26f28864..f2c80705ba 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;  	} @@ -2326,7 +2344,7 @@ function avatar_process_user(&$error, $custom_userdata = false, $can_upload = nu  	// Can we upload?  	if (is_null($can_upload))  	{ -		$can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $change_avatar && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; +		$can_upload = ($config['allow_avatar_upload'] && file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $change_avatar && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;  	}  	if ((!empty($_FILES['uploadfile']['name']) || $data['uploadurl']) && $can_upload) 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/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php index 1fbedbac4f..7098b4bbce 100644 --- a/phpBB/includes/mcp/mcp_post.php +++ b/phpBB/includes/mcp/mcp_post.php @@ -176,7 +176,7 @@ function mcp_post_details($id, $mode, $action)  	}  	$template->assign_vars(array( -		'U_MCP_ACTION'			=> "$url&i=main&quickmod=1", // Use this for mode paramaters +		'U_MCP_ACTION'			=> "$url&i=main&quickmod=1&mode=post_details", // Use this for mode paramaters  		'U_POST_ACTION'			=> "$url&i=$id&mode=post_details", // Use this for action parameters  		'U_APPROVE_ACTION'		=> append_sid("{$phpbb_root_path}mcp.$phpEx", "i=queue&p=$post_id&f={$post_info['forum_id']}"), 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_groups.php b/phpBB/includes/ucp/ucp_groups.php index 423d9b718a..1c055a4823 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -490,7 +490,7 @@ class ucp_groups  						$avatar_select = basename(request_var('avatar_select', ''));  						$category = basename(request_var('category', '')); -						$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false; +						$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $file_uploads) ? true : false;  						// Did we submit?  						if ($update) diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 26968e1382..16700c490c 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -309,7 +309,7 @@ function get_user_information($user_id, $user_row)  	get_user_rank($user_row['user_rank'], $user_row['user_posts'], $user_row['rank_title'], $user_row['rank_image'], $user_row['rank_image_src']); -	if (!empty($user_row['user_allow_viewemail']) || $auth->acl_get('a_email')) +	if ((!empty($user_row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email'))  	{  		$user_row['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&u=$user_id") : ((($config['board_hide_emails'] && !$auth->acl_get('a_email')) || empty($user_row['user_email'])) ? '' : 'mailto:' . $user_row['user_email']);  	} diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index 363a4803b6..c099e3b3fa 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); @@ -564,7 +561,7 @@ class ucp_profile  				$avatar_select = basename(request_var('avatar_select', ''));  				$category = basename(request_var('category', '')); -				$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && @is_writable($phpbb_root_path . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; +				$can_upload = (file_exists($phpbb_root_path . $config['avatar_path']) && phpbb_is_writable($phpbb_root_path . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false;  				add_form_key('ucp_avatar'); 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/install/install_convert.php b/phpBB/install/install_convert.php index 8c3ffd61a8..814b50cf68 100644 --- a/phpBB/install/install_convert.php +++ b/phpBB/install/install_convert.php @@ -835,7 +835,7 @@ class install_convert extends module  							$this->p_master->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__);  						} -						if (!$local_path || !@is_writable($phpbb_root_path . $local_path)) +						if (!$local_path || !phpbb_is_writable($phpbb_root_path . $local_path))  						{  							if (!$local_path)  							{ diff --git a/phpBB/install/install_install.php b/phpBB/install/install_install.php index 4c22db07b2..6c23460de9 100644 --- a/phpBB/install/install_install.php +++ b/phpBB/install/install_install.php @@ -486,7 +486,7 @@ class install_install extends module  			$write = $exists = true;  			if (file_exists($phpbb_root_path . $dir))  			{ -				if (!@is_writable($phpbb_root_path . $dir)) +				if (!phpbb_is_writable($phpbb_root_path . $dir))  				{  					$write = false;  				} @@ -906,7 +906,7 @@ class install_install extends module  		$config_data .= '?' . '>'; // Done this to prevent highlighting editors getting confused!  		// Attempt to write out the config file directly. If it works, this is the easiest way to do it ... -		if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && is_writable($phpbb_root_path . 'config.' . $phpEx)) || is_writable($phpbb_root_path)) +		if ((file_exists($phpbb_root_path . 'config.' . $phpEx) && phpbb_is_writable($phpbb_root_path . 'config.' . $phpEx)) || phpbb_is_writable($phpbb_root_path))  		{  			// Assume it will work ... if nothing goes wrong below  			$written = true; 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/memberlist.php b/phpBB/memberlist.php index b46230b10a..2fa2d11ee1 100644 --- a/phpBB/memberlist.php +++ b/phpBB/memberlist.php @@ -1607,7 +1607,7 @@ function show_profile($data, $user_notes_enabled = false, $warn_user_enabled = f  	$rank_title = $rank_img = $rank_img_src = '';  	get_user_rank($data['user_rank'], (($user_id == ANONYMOUS) ? false : $data['user_posts']), $rank_title, $rank_img, $rank_img_src); -	if (!empty($data['user_allow_viewemail']) || $auth->acl_get('a_user')) +	if ((!empty($data['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_user'))  	{  		$email = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=email&u=' . $user_id) : (($config['board_hide_emails'] && !$auth->acl_get('a_user')) ? '' : 'mailto:' . $data['user_email']);  	} diff --git a/phpBB/posting.php b/phpBB/posting.php index df063ef391..8cacac2910 100644 --- a/phpBB/posting.php +++ b/phpBB/posting.php @@ -402,6 +402,16 @@ if ($post_data['poll_start'])  	$db->sql_freeresult($result);  } +$original_poll_data = array( +	'poll_title'		=> $post_data['poll_title'], +	'poll_length'		=> $post_data['poll_length'], +	'poll_max_options'	=> $post_data['poll_max_options'], +	'poll_option_text'	=> implode("\n", $post_data['poll_options']), +	'poll_start'		=> $post_data['poll_start'], +	'poll_last_vote'	=> $post_data['poll_last_vote'], +	'poll_vote_change'	=> $post_data['poll_vote_change'], +); +  $orig_poll_options_size = sizeof($post_data['poll_options']);  $message_parser = new parse_message(); @@ -912,6 +922,22 @@ if ($submit || $preview || $refresh)  			$message_parser->warn_msg[] = $user->lang['NO_DELETE_POLL_OPTIONS'];  		}*/  	} +	else if (!$auth->acl_get('f_poll', $forum_id) && ($mode == 'edit') && ($post_id == $post_data['topic_first_post_id']) && ($original_poll_data['poll_title'] != '')) +	{ +		// We have a poll but the editing user is not permitted to create/edit it. +		// So we just keep the original poll-data. +		$poll = array_merge($original_poll_data, array( +			'enable_bbcode'		=> $post_data['enable_bbcode'], +			'enable_urls'		=> $post_data['enable_urls'], +			'enable_smilies'	=> $post_data['enable_smilies'], +			'img_status'		=> $img_status, +		)); + +		$message_parser->parse_poll($poll); + +		$post_data['poll_options'] = (isset($poll['poll_options'])) ? $poll['poll_options'] : ''; +		$post_data['poll_title'] = (isset($poll['poll_title'])) ? $poll['poll_title'] : ''; +	}  	else  	{  		$poll = array(); diff --git a/phpBB/styles/prosilver/template/login_body.html b/phpBB/styles/prosilver/template/login_body.html index fe111aaa45..e52ccd6434 100644 --- a/phpBB/styles/prosilver/template/login_body.html +++ b/phpBB/styles/prosilver/template/login_body.html @@ -32,11 +32,11 @@  		</dl>  		<!-- ENDIF --> +		{S_LOGIN_REDIRECT}  		<dl>  			<dt> </dt>  			<dd>{S_HIDDEN_FIELDS}<input type="submit" name="login" tabindex="6" value="{L_LOGIN}" class="button1" /></dd>  		</dl> -		{S_LOGIN_REDIRECT}  		</fieldset>  	</div>  	<span class="corners-bottom"><span></span></span></div> diff --git a/phpBB/styles/prosilver/template/mcp_post.html b/phpBB/styles/prosilver/template/mcp_post.html index 0265d7ce12..dab2d572a9 100644 --- a/phpBB/styles/prosilver/template/mcp_post.html +++ b/phpBB/styles/prosilver/template/mcp_post.html @@ -54,6 +54,8 @@  		</ul>  		<!-- ENDIF --> +		<span class="right-box clear" id="expand"><a href="#post_details" onclick="viewableArea(getElementById('post_details'), true); var rev_text = getElementById('expand').getElementsByTagName('a').item(0).firstChild; if (rev_text.data == '{LA_EXPAND_VIEW}'){rev_text.data = '{LA_COLLAPSE_VIEW}'; } else if (rev_text.data == '{LA_COLLAPSE_VIEW}'){rev_text.data = '{LA_EXPAND_VIEW}'}; return false;">{L_EXPAND_VIEW}</a></span> +  		<h3><a href="{U_VIEW_POST}">{POST_SUBJECT}</a></h3>  		<!-- IF S_PM -->  		<p class="author"> @@ -84,7 +86,7 @@  			</p>  		<!-- ENDIF --> -		<div class="content"> +		<div class="content" id="post_details">  			{POST_PREVIEW}  		</div> 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/phpBB/styles/prosilver/theme/content.css b/phpBB/styles/prosilver/theme/content.css index 417537e660..dfe00371e4 100644 --- a/phpBB/styles/prosilver/theme/content.css +++ b/phpBB/styles/prosilver/theme/content.css @@ -298,6 +298,15 @@ div[class].topic-actions {  	display: none;  } +/* MCP Post details +----------------------------------------*/ +#post_details +{ +	/* This will only work in IE7+, plus the others */ +	overflow: auto; +	max-height: 300px; +} +  /* Content container styles  ----------------------------------------*/  .content { diff --git a/phpBB/styles/subsilver2/template/login_body.html b/phpBB/styles/subsilver2/template/login_body.html index 51f7068b5f..503de9e69e 100644 --- a/phpBB/styles/subsilver2/template/login_body.html +++ b/phpBB/styles/subsilver2/template/login_body.html @@ -72,12 +72,12 @@  	<!-- INCLUDE {CAPTCHA_TEMPLATE} -->  <!-- ENDIF --> +{S_LOGIN_REDIRECT}  <tr>  	<td class="cat" <!-- IF not S_ADMIN_AUTH or S_CONFIRM_CODE -->colspan="2"<!-- ENDIF --> align="center">{S_HIDDEN_FIELDS}<input type="submit" name="login" class="btnmain" value="{L_LOGIN}" tabindex="5" /></td>  </tr>  </table>  {S_FORM_TOKEN} -{S_LOGIN_REDIRECT}  </form>  <br clear="all" /> diff --git a/phpBB/viewtopic.php b/phpBB/viewtopic.php index 8926d5a40b..498088c5c8 100644 --- a/phpBB/viewtopic.php +++ b/phpBB/viewtopic.php @@ -1146,7 +1146,7 @@ while ($row = $db->sql_fetchrow($result))  			get_user_rank($row['user_rank'], $row['user_posts'], $user_cache[$poster_id]['rank_title'], $user_cache[$poster_id]['rank_image'], $user_cache[$poster_id]['rank_image_src']); -			if (!empty($row['user_allow_viewemail']) || $auth->acl_get('a_email')) +			if ((!empty($row['user_allow_viewemail']) && $auth->acl_get('u_sendemail')) || $auth->acl_get('a_email'))  			{  				$user_cache[$poster_id]['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid("{$phpbb_root_path}memberlist.$phpEx", "mode=email&u=$poster_id") : (($config['board_hide_emails'] && !$auth->acl_get('a_email')) ? '' : 'mailto:' . $row['user_email']);  			} 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); +			} +		} +	} +} | 
