Thank you for downloading phpBB3. This README will guide through the basics of installation and operation of phpBB3. Please ensure you read this and the accompanying documentation fully before proceeding with the installation.
+
Thank you for downloading phpBB3. This README will guide you through the basics of installation and operation of phpBB3. Please ensure you read this and the accompanying documentation fully before proceeding with the installation.
Installation, update and conversion instructions can be found in the INSTALL document contained in this distribution. If you are intending to convert from a previous phpBB 2.0.x or 3.0.x installation we highly recommend you backup any existing data before proceeding!
+
Installation, update and conversion instructions can be found in the INSTALL document in this directory. If you are intending on converting from a phpBB 2.0.x or 3.0.x installation we highly recommend that you backup any existing data before proceeding!
Users of phpBB 3.0 and 3.1 Beta versions cannot directly update.
-
Please note that we won't support the following installation types:
+
Please note that we don't support the following installation types:
Updates from phpBB 3.0 Beta versions to phpBB 3.0 RC1 and higher
Updates from phpBB 3.1 Beta versions to phpBB 3.1 RC1 and higher
@@ -103,8 +102,8 @@
Updates from phpBB 3.0 RC1 and 3.1 RC1 to the latest version
Note: if using the Automatic Update Package, updates are supported from phpBB 3.0.2 onward. To update a pre-3.0.2 installation, first update to 3.0.2 and then update to the current version.
Conversions from phpBB 2.0.x to the latest version
-
New installations of phpBB 3.0.x - always only the latest released version
-
New installations of phpBB 3.1.x - always only the latest released version
+
New installations of phpBB 3.0.x - only the latest released version
+
New installations of phpBB 3.1.x - only the latest released version
This is the official location for all supported language sets. If you download a package from a 3rd party site you do so with the understanding that we cannot offer support. So please, do not ask for help in these cases!
+
This is the official location for all supported language sets. If you download a package from a 3rd party site you do so with the understanding that we cannot offer support. Please do not ask for support if you download a language pack from a 3rd party site.
Installation of these packages is straightforward: simply download the required language pack, uncompress (unzip) it and via FTP transfer the included language and styles folders to the root of your board installation. The language can then be installed via the Administration Control Panel of your board: System tab -> General Tasks -> Language packs. A more detailed description of the process is in the Knowledge Base article, How to Install a Language Pack.
@@ -175,15 +174,15 @@
-
phpBB3 can seem a little daunting to new users in places, particularly with regard the permission system. The first thing you should do is check the FAQ which covers a few basic getting started questions. If you need additional help there are several places you should look.
+
phpBB3 can sometimes seem a little daunting to new users, particularly with regards to the permission system. The first thing you should do is check the FAQ, which covers a few basic getting started questions. If you need additional help there are several places you can find it.
3.i. phpBB3 Documentation
-
A comprehensive documentation is now available online and can be accessed from the following location:
+
Comprehensive documentation is now available on the phpBB website:
If you do seek help via our forums please be sure to do a Search before posting. This may well save both you and us time and allow the developer, moderator and support groups to spend more time responding to people with unknown issues and problems. Please also remember that phpBB is an entirely volunteer effort, no one receives any compensation for the time they give, this includes moderators as well as developers. So please be respectful and mindful when awaiting responses.
+
If you do seek help via our forums please be sure to do a search before posting; if someone has experienced the issue before, then you may find that your question has already been answered. Please remember that phpBB is entirely staffed by volunteers, no one receives any compensation for the time they give, including moderators as well as developers; please be respectful and mindful when awaiting responses and receiving support.
3.iv Internet Relay Chat
@@ -268,7 +267,7 @@
The relevant database type/version is listed within the administration control panel.
-
Please also be as detailed as you can in your report, if possible list the steps required to duplicate the problem. If you have a patch that fixes the issue, please attach it to the ticket or submit a pull request on GitHub.
+
Please be as detailed as you can in your report, and if possible, list the steps required to duplicate the problem. If you have a patch that fixes the issue, please attach it to the ticket or submit a pull request to our repository on GitHub.
If you create a patch, it is very much appreciated (but not required) if you follow the phpBB coding guidelines. Please note that the coding guidelines are somewhat different between different versions of phpBB. For phpBB 3.1.x the coding guidelines may be found here: http://area51.phpbb.com/docs/31x/coding-guidelines.html
@@ -299,8 +298,8 @@
This list is not complete but does represent those bugs which may affect users on a wider scale. Other bugs listed in the tracker have typically been shown to be limited to certain setups or methods of installation, updating and/or conversions.
-
Conversions may fail to complete on large boards under some hosts
-
Updates may fail to complete on large update sets under some hosts
+
Conversions may fail to complete on large boards under some hosts.
+
Updates may fail to complete on large update sets under some hosts.
Smilies placed directly after bbcode tags will not get parsed. Smilies always need to be separated by spaces.
@@ -322,7 +321,7 @@
phpBB 3.1.x takes advantage of new features added in PHP 5.3. We recommend that you upgrade to the latest stable release of PHP5 to run phpBB. The minimum version required is PHP 5.3.3.
-
Please remember that running any application on a developmental version of PHP can lead to strange/unexpected results which may appear to be bugs in the application (which may not be true). Therefore we recommend you upgrade to the newest stable version of PHP before running phpBB3. If you are running a developmental version of PHP please check any bugs you find on a system running a stable release before submitting.
+
Please remember that running any application on a development (unstable, e.g. a beta release) version of PHP can lead to strange/unexpected results which may appear to be bugs in the application. Therefore, we recommend you upgrade to the newest stable version of PHP before running phpBB3. If you are running a development version of PHP please check any bugs you find on a system running a stable release before submitting.
This board has been developed and tested under Linux and Windows (amongst others) running Apache using MySQL 3.23, 4.x, 5.x, MSSQL Server 2000, PostgreSQL 8.x, Oracle 8, SQLite 2 and Firebird. Versions of PHP used range from 5.3.x to 5.4.x without problem.
diff --git a/phpBB/download/file.php b/phpBB/download/file.php
index eee2090da0..cf7128b25b 100644
--- a/phpBB/download/file.php
+++ b/phpBB/download/file.php
@@ -279,7 +279,7 @@ else if ($download_id)
phpbb_increment_downloads($db, $attachment['attach_id']);
}
- if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && ((strpos(strtolower($user->browser), 'msie') !== false) && (strpos(strtolower($user->browser), 'msie 8.0') === false)))
+ if ($display_cat == ATTACHMENT_CATEGORY_IMAGE && $mode === 'view' && (strpos($attachment['mimetype'], 'image') === 0) && (strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7))
{
wrap_img_in_html(append_sid($phpbb_root_path . 'download/file.' . $phpEx, 'id=' . $attachment['attach_id']), $attachment['real_filename']);
file_gc();
diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php
index 6881e03fdb..24b913260b 100644
--- a/phpBB/includes/acp/acp_board.php
+++ b/phpBB/includes/acp/acp_board.php
@@ -522,84 +522,54 @@ class acp_board
if ($mode == 'auth')
{
// Retrieve a list of auth plugins and check their config values
- $auth_plugins = array();
-
- $dp = @opendir($phpbb_root_path . 'includes/auth');
-
- if ($dp)
- {
- while (($file = readdir($dp)) !== false)
- {
- if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file))
- {
- $auth_plugins[] = basename(preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file));
- }
- }
- closedir($dp);
-
- sort($auth_plugins);
- }
+ $auth_providers = $phpbb_container->get('auth.provider_collection');
$updated_auth_settings = false;
$old_auth_config = array();
- foreach ($auth_plugins as $method)
+ foreach ($auth_providers as $provider)
{
- if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx))
+ if ($fields = $provider->acp($this->new_config))
{
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
-
- $method = 'acp_' . $method;
- if (function_exists($method))
+ // Check if we need to create config fields for this plugin and save config when submit was pressed
+ foreach ($fields['config'] as $field)
{
- if ($fields = $method($this->new_config))
+ if (!isset($config[$field]))
{
- // Check if we need to create config fields for this plugin and save config when submit was pressed
- foreach ($fields['config'] as $field)
- {
- if (!isset($config[$field]))
- {
- set_config($field, '');
- }
-
- if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false)
- {
- continue;
- }
-
- $old_auth_config[$field] = $this->new_config[$field];
- $config_value = $cfg_array[$field];
- $this->new_config[$field] = $config_value;
-
- if ($submit)
- {
- $updated_auth_settings = true;
- set_config($field, $config_value);
- }
- }
+ set_config($field, '');
+ }
+
+ if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false)
+ {
+ continue;
+ }
+
+ $old_auth_config[$field] = $this->new_config[$field];
+ $config_value = $cfg_array[$field];
+ $this->new_config[$field] = $config_value;
+
+ if ($submit)
+ {
+ $updated_auth_settings = true;
+ set_config($field, $config_value);
}
- unset($fields);
}
}
+ unset($fields);
}
if ($submit && (($cfg_array['auth_method'] != $this->new_config['auth_method']) || $updated_auth_settings))
{
$method = basename($cfg_array['auth_method']);
- if ($method && in_array($method, $auth_plugins))
+ if (array_key_exists('auth.provider.' . $method, $auth_providers))
{
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
-
- $method = 'init_' . $method;
- if (function_exists($method))
+ $provider = $auth_providers['auth.provider.' . $method];
+ if ($error = $provider->init())
{
- if ($error = $method())
+ foreach ($old_auth_config as $config_name => $config_value)
{
- foreach ($old_auth_config as $config_name => $config_value)
- {
- set_config($config_name, $config_value);
- }
- trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
+ set_config($config_name, $config_value);
}
+ trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING);
}
set_config('auth_method', basename($cfg_array['auth_method']));
}
@@ -683,24 +653,17 @@ class acp_board
{
$template->assign_var('S_AUTH', true);
- foreach ($auth_plugins as $method)
+ foreach ($auth_providers as $provider)
{
- if ($method && file_exists($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx))
- {
- $method = 'acp_' . $method;
- if (function_exists($method))
- {
- $fields = $method($this->new_config);
+ $fields = $provider->acp($this->new_config);
- if ($fields['tpl'])
- {
- $template->assign_block_vars('auth_tpl', array(
- 'TPL' => $fields['tpl'])
- );
- }
- unset($fields);
- }
+ if ($fields['tpl'])
+ {
+ $template->assign_block_vars('auth_tpl', array(
+ 'TPL' => $fields['tpl'],
+ ));
}
+ unset($fields);
}
}
}
@@ -710,26 +673,16 @@ class acp_board
*/
function select_auth_method($selected_method, $key = '')
{
- global $phpbb_root_path, $phpEx;
+ global $phpbb_root_path, $phpEx, $phpbb_container;
$auth_plugins = array();
+ $auth_providers = $phpbb_container->get('auth.provider_collection');
- $dp = @opendir($phpbb_root_path . 'includes/auth');
-
- if (!$dp)
+ foreach($auth_providers as $key => $value)
{
- return '';
+ $auth_plugins[] = str_replace('auth.provider.', '', $key);
}
- while (($file = readdir($dp)) !== false)
- {
- if (preg_match('#^auth_(.*?)\.' . $phpEx . '$#', $file))
- {
- $auth_plugins[] = preg_replace('#^auth_(.*?)\.' . $phpEx . '$#', '\1', $file);
- }
- }
- closedir($dp);
-
sort($auth_plugins);
$auth_select = '';
diff --git a/phpBB/includes/acp/acp_captcha.php b/phpBB/includes/acp/acp_captcha.php
index c7c64ae56b..1a083c20ac 100644
--- a/phpBB/includes/acp/acp_captcha.php
+++ b/phpBB/includes/acp/acp_captcha.php
@@ -124,6 +124,8 @@ class acp_captcha
'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
'CAPTCHA_SELECT' => $captcha_select,
+
+ 'U_ACTION' => $this->u_action,
));
}
}
diff --git a/phpBB/includes/acp/acp_groups.php b/phpBB/includes/acp/acp_groups.php
index 847ccfb3cc..c79699d465 100644
--- a/phpBB/includes/acp/acp_groups.php
+++ b/phpBB/includes/acp/acp_groups.php
@@ -591,7 +591,7 @@ class acp_groups
$avatar = phpbb_get_group_avatar($group_row, 'GROUP_AVATAR', true);
- if (!$update)
+ if (isset($phpbb_avatar_manager) && !$update)
{
// Merge any avatar errors into the primary error array
$error = array_merge($error, $phpbb_avatar_manager->localize_errors($user, $avatar_error));
diff --git a/phpBB/includes/acp/acp_permission_roles.php b/phpBB/includes/acp/acp_permission_roles.php
index 004187af84..e830479389 100644
--- a/phpBB/includes/acp/acp_permission_roles.php
+++ b/phpBB/includes/acp/acp_permission_roles.php
@@ -21,6 +21,7 @@ if (!defined('IN_PHPBB'))
class acp_permission_roles
{
var $u_action;
+ protected $auth_admin;
function main($id, $mode)
{
@@ -30,7 +31,7 @@ class acp_permission_roles
include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx);
include_once($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
- $auth_admin = new auth_admin();
+ $this->auth_admin = new auth_admin();
$user->add_lang('acp/permissions');
add_permission_language();
@@ -210,7 +211,7 @@ class acp_permission_roles
}
// Now add the auth settings
- $auth_admin->acl_set_role($role_id, $auth_settings);
+ $this->auth_admin->acl_set_role($role_id, $auth_settings);
$role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name;
add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name);
@@ -343,7 +344,7 @@ class acp_permission_roles
// Get users/groups/forums using this preset...
if ($action == 'edit')
{
- $hold_ary = $auth_admin->get_role_mask($role_id);
+ $hold_ary = $this->auth_admin->get_role_mask($role_id);
if (sizeof($hold_ary))
{
@@ -354,7 +355,7 @@ class acp_permission_roles
'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name))
);
- $auth_admin->display_role_mask($hold_ary);
+ $this->auth_admin->display_role_mask($hold_ary);
}
}
@@ -445,8 +446,8 @@ class acp_permission_roles
'S_DISPLAY_ROLE_MASK' => true)
);
- $hold_ary = $auth_admin->get_role_mask($display_item);
- $auth_admin->display_role_mask($hold_ary);
+ $hold_ary = $this->auth_admin->get_role_mask($display_item);
+ $this->auth_admin->display_role_mask($hold_ary);
}
}
@@ -462,7 +463,7 @@ class acp_permission_roles
$auth_options = array(0 => $auth_options);
// Making use of auth_admin method here (we do not really want to change two similar code fragments)
- auth_admin::build_permission_array($auth_options, $content_array, $categories, $key_sort_array);
+ $this->auth_admin->build_permission_array($auth_options, $content_array, $categories, $key_sort_array);
$content_array = $content_array[0];
@@ -500,8 +501,6 @@ class acp_permission_roles
{
global $db;
- $auth_admin = new auth_admin();
-
// Get complete auth array
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
@@ -529,19 +528,19 @@ class acp_permission_roles
$db->sql_freeresult($result);
// Get role assignments
- $hold_ary = $auth_admin->get_role_mask($role_id);
+ $hold_ary = $this->auth_admin->get_role_mask($role_id);
// Re-assign permissions
foreach ($hold_ary as $forum_id => $forum_ary)
{
if (isset($forum_ary['users']))
{
- $auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
+ $this->auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
}
if (isset($forum_ary['groups']))
{
- $auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);
+ $this->auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false);
}
}
@@ -563,6 +562,6 @@ class acp_permission_roles
WHERE role_id = ' . $role_id;
$db->sql_query($sql);
- $auth_admin->acl_clear_prefetch();
+ $this->auth_admin->acl_clear_prefetch();
}
}
diff --git a/phpBB/includes/auth/auth.php b/phpBB/includes/auth/auth.php
index 2535247571..279959974d 100644
--- a/phpBB/includes/auth/auth.php
+++ b/phpBB/includes/auth/auth.php
@@ -927,15 +927,14 @@ class phpbb_auth
*/
function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0)
{
- global $config, $db, $user, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $phpbb_root_path, $phpEx, $phpbb_container;
$method = trim(basename($config['auth_method']));
- include_once($phpbb_root_path . 'includes/auth/auth_' . $method . '.' . $phpEx);
- $method = 'login_' . $method;
- if (function_exists($method))
+ $provider = $phpbb_container->get('auth.provider.' . $method);
+ if ($provider)
{
- $login = $method($username, $password, $user->ip, $user->browser, $user->forwarded_for);
+ $login = $provider->login($username, $password);
// If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS
if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE)
diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php
deleted file mode 100644
index 10b288aa09..0000000000
--- a/phpBB/includes/auth/auth_apache.php
+++ /dev/null
@@ -1,247 +0,0 @@
-is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $user->data['username'] !== htmlspecialchars_decode($request->server('PHP_AUTH_USER')))
- {
- return $user->lang['APACHE_SETUP_BEFORE_USE'];
- }
- return false;
-}
-
-/**
-* Login function
-*/
-function login_apache(&$username, &$password)
-{
- global $db, $request;
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER'));
- $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW'));
-
- if (!empty($php_auth_user) && !empty($php_auth_pw))
- {
- if ($php_auth_user !== $username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
- FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
-
- // this is the user's first login so create an empty profile
- return array(
- 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
- 'error_msg' => false,
- 'user_row' => user_row_apache($php_auth_user, $php_auth_pw),
- );
- }
-
- // Not logged into apache
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
-}
-
-/**
-* Autologin function
-*
-* @return array containing the user row or empty if no auto login should take place
-*/
-function autologin_apache()
-{
- global $db, $request;
-
- if (!$request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- return array();
- }
-
- $php_auth_user = htmlspecialchars_decode($request->server('PHP_AUTH_USER'));
- $php_auth_pw = htmlspecialchars_decode($request->server('PHP_AUTH_PW'));
-
- if (!empty($php_auth_user) && !empty($php_auth_pw))
- {
- set_var($php_auth_user, $php_auth_user, 'string', true);
- set_var($php_auth_pw, $php_auth_pw, 'string', true);
-
- $sql = 'SELECT *
- FROM ' . USERS_TABLE . "
- WHERE username = '" . $db->sql_escape($php_auth_user) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row;
- }
-
- if (!function_exists('user_add'))
- {
- global $phpbb_root_path, $phpEx;
-
- include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
- }
-
- // create the user if he does not exist yet
- user_add(user_row_apache($php_auth_user, $php_auth_pw));
-
- $sql = 'SELECT *
- FROM ' . USERS_TABLE . "
- WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- return $row;
- }
- }
-
- return array();
-}
-
-/**
-* This function generates an array which can be passed to the user_add function in order to create a user
-*/
-function user_row_apache($username, $password)
-{
- global $db, $config, $user;
- // first retrieve default group id
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
- AND group_type = " . GROUP_SPECIAL;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_GROUP');
- }
-
- // generate user account data
- return array(
- 'username' => $username,
- 'user_password' => phpbb_hash($password),
- 'user_email' => '',
- 'group_id' => (int) $row['group_id'],
- 'user_type' => USER_NORMAL,
- 'user_ip' => $user->ip,
- 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
- );
-}
-
-/**
-* The session validation function checks whether the user is still logged in
-*
-* @return boolean true if the given user is authenticated or false if the session should be closed
-*/
-function validate_session_apache(&$user)
-{
- global $request;
-
- // Check if PHP_AUTH_USER is set and handle this case
- if ($request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
- {
- $php_auth_user = $request->server('PHP_AUTH_USER');
-
- return ($php_auth_user === $user['username']) ? true : false;
- }
-
- // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not)
- if ($user['user_type'] == USER_IGNORE)
- {
- return true;
- }
-
- return false;
-}
diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php
deleted file mode 100644
index ac944532a5..0000000000
--- a/phpBB/includes/auth/auth_db.php
+++ /dev/null
@@ -1,289 +0,0 @@
- status constant
-* 'error_msg' => string
-* 'user_row' => array
-* )
-*/
-function login_db($username, $password, $ip = '', $browser = '', $forwarded_for = '')
-{
- global $db, $config;
- global $request;
-
- // Auth plugins get the password untrimmed.
- // For compatibility we trim() here.
- $password = trim($password);
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $username_clean = utf8_clean_string($username);
-
- $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
- FROM ' . USERS_TABLE . "
- WHERE username_clean = '" . $db->sql_escape($username_clean) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (($ip && !$config['ip_login_limit_use_forwarded']) ||
- ($forwarded_for && $config['ip_login_limit_use_forwarded']))
- {
- $sql = 'SELECT COUNT(*) AS attempts
- FROM ' . LOGIN_ATTEMPT_TABLE . '
- WHERE attempt_time > ' . (time() - (int) $config['ip_login_limit_time']);
- if ($config['ip_login_limit_use_forwarded'])
- {
- $sql .= " AND attempt_forwarded_for = '" . $db->sql_escape($forwarded_for) . "'";
- }
- else
- {
- $sql .= " AND attempt_ip = '" . $db->sql_escape($ip) . "' ";
- }
-
- $result = $db->sql_query($sql);
- $attempts = (int) $db->sql_fetchfield('attempts');
- $db->sql_freeresult($result);
-
- $attempt_data = array(
- 'attempt_ip' => $ip,
- 'attempt_browser' => trim(substr($browser, 0, 149)),
- 'attempt_forwarded_for' => $forwarded_for,
- 'attempt_time' => time(),
- 'user_id' => ($row) ? (int) $row['user_id'] : 0,
- 'username' => $username,
- 'username_clean' => $username_clean,
- );
- $sql = 'INSERT INTO ' . LOGIN_ATTEMPT_TABLE . $db->sql_build_array('INSERT', $attempt_data);
- $result = $db->sql_query($sql);
- }
- else
- {
- $attempts = 0;
- }
-
- if (!$row)
- {
- if ($config['ip_login_limit_max'] && $attempts >= $config['ip_login_limit_max'])
- {
- return array(
- 'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $show_captcha = ($config['max_login_attempts'] && $row['user_login_attempts'] >= $config['max_login_attempts']) ||
- ($config['ip_login_limit_max'] && $attempts >= $config['ip_login_limit_max']);
-
- // If there are too much login attempts, we need to check for an confirm image
- // Every auth module is able to define what to do by itself...
- if ($show_captcha)
- {
- // Visual Confirmation handling
- if (!class_exists('phpbb_captcha_factory', false))
- {
- global $phpbb_root_path, $phpEx;
- include ($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx);
- }
-
- $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']);
- $captcha->init(CONFIRM_LOGIN);
- $vc_response = $captcha->validate($row);
- if ($vc_response)
- {
- return array(
- 'status' => LOGIN_ERROR_ATTEMPTS,
- 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
- 'user_row' => $row,
- );
- }
- else
- {
- $captcha->reset();
- }
-
- }
-
- // If the password convert flag is set we need to convert it
- if ($row['user_pass_convert'])
- {
- // enable super globals to get literal value
- // this is needed to prevent unicode normalization
- $super_globals_disabled = $request->super_globals_disabled();
- if ($super_globals_disabled)
- {
- $request->enable_super_globals();
- }
-
- // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
- $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
- $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
- $password_new_format = $request->variable('password', '', true);
-
- if ($super_globals_disabled)
- {
- $request->disable_super_globals();
- }
-
- if ($password == $password_new_format)
- {
- if (!function_exists('utf8_to_cp1252'))
- {
- global $phpbb_root_path, $phpEx;
- include($phpbb_root_path . 'includes/utf/data/recode_basic.' . $phpEx);
- }
-
- // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
- // plain md5 support left in for conversions from other systems.
- if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
- || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
- {
- $hash = phpbb_hash($password_new_format);
-
- // Update the password in the users table to the new format and remove user_pass_convert flag
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_password = \'' . $db->sql_escape($hash) . '\',
- user_pass_convert = 0
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
-
- $row['user_pass_convert'] = 0;
- $row['user_password'] = $hash;
- }
- else
- {
- // Although we weren't able to convert this password we have to
- // increase login attempt count to make sure this cannot be exploited
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . (int) $row['user_id'] . '
- AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
- $db->sql_query($sql);
-
- return array(
- 'status' => LOGIN_ERROR_PASSWORD_CONVERT,
- 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT',
- 'user_row' => $row,
- );
- }
- }
- }
-
- // Check password ...
- if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password']))
- {
- // Check for old password hash...
- if (strlen($row['user_password']) == 32)
- {
- $hash = phpbb_hash($password);
-
- // Update the password in the users table to the new format
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_password = '" . $db->sql_escape($hash) . "',
- user_pass_convert = 0
- WHERE user_id = {$row['user_id']}";
- $db->sql_query($sql);
-
- $row['user_password'] = $hash;
- }
-
- $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
-
- if ($row['user_login_attempts'] != 0)
- {
- // Successful, reset login attempts (the user passed all stages)
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = 0
- WHERE user_id = ' . $row['user_id'];
- $db->sql_query($sql);
- }
-
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login... set user_login_attempts to zero...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
-
- // Password incorrect - increase login attempts
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_login_attempts = user_login_attempts + 1
- WHERE user_id = ' . (int) $row['user_id'] . '
- AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
- $db->sql_query($sql);
-
- // Give status about wrong password...
- return array(
- 'status' => ($show_captcha) ? LOGIN_ERROR_ATTEMPTS : LOGIN_ERROR_PASSWORD,
- 'error_msg' => ($show_captcha) ? 'LOGIN_ERROR_ATTEMPTS' : 'LOGIN_ERROR_PASSWORD',
- 'user_row' => $row,
- );
-}
diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php
deleted file mode 100644
index 98355dd044..0000000000
--- a/phpBB/includes/auth/auth_ldap.php
+++ /dev/null
@@ -1,350 +0,0 @@
-lang['LDAP_NO_LDAP_EXTENSION'];
- }
-
- $config['ldap_port'] = (int) $config['ldap_port'];
- if ($config['ldap_port'])
- {
- $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
- }
- else
- {
- $ldap = @ldap_connect($config['ldap_server']);
- }
-
- if (!$ldap)
- {
- return $user->lang['LDAP_NO_SERVER_CONNECTION'];
- }
-
- @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
- @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
-
- if ($config['ldap_user'] || $config['ldap_password'])
- {
- if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
- {
- return $user->lang['LDAP_INCORRECT_USER_PASSWORD'];
- }
- }
-
- // ldap_connect only checks whether the specified server is valid, so the connection might still fail
- $search = @ldap_search(
- $ldap,
- htmlspecialchars_decode($config['ldap_base_dn']),
- ldap_user_filter($user->data['username']),
- (empty($config['ldap_email'])) ?
- array(htmlspecialchars_decode($config['ldap_uid'])) :
- array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
- 0,
- 1
- );
-
- if ($search === false)
- {
- return $user->lang['LDAP_SEARCH_FAILED'];
- }
-
- $result = @ldap_get_entries($ldap, $search);
-
- @ldap_close($ldap);
-
-
- if (!is_array($result) || sizeof($result) < 2)
- {
- return sprintf($user->lang['LDAP_NO_IDENTITY'], $user->data['username']);
- }
-
- if (!empty($config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($config['ldap_email'])]))
- {
- return $user->lang['LDAP_NO_EMAIL'];
- }
-
- return false;
-}
-
-/**
-* Login function
-*/
-function login_ldap(&$username, &$password)
-{
- global $db, $config, $user;
-
- // do not allow empty password
- if (!$password)
- {
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'NO_PASSWORD_SUPPLIED',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!$username)
- {
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- if (!@extension_loaded('ldap'))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_LDAP_EXTENSION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- $config['ldap_port'] = (int) $config['ldap_port'];
- if ($config['ldap_port'])
- {
- $ldap = @ldap_connect($config['ldap_server'], $config['ldap_port']);
- }
- else
- {
- $ldap = @ldap_connect($config['ldap_server']);
- }
-
- if (!$ldap)
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
-
- @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
- @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
-
- if ($config['ldap_user'] || $config['ldap_password'])
- {
- if (!@ldap_bind($ldap, htmlspecialchars_decode($config['ldap_user']), htmlspecialchars_decode($config['ldap_password'])))
- {
- return array(
- 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
- 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
- }
-
- $search = @ldap_search(
- $ldap,
- htmlspecialchars_decode($config['ldap_base_dn']),
- ldap_user_filter($username),
- (empty($config['ldap_email'])) ?
- array(htmlspecialchars_decode($config['ldap_uid'])) :
- array(htmlspecialchars_decode($config['ldap_uid']), htmlspecialchars_decode($config['ldap_email'])),
- 0,
- 1
- );
-
- $ldap_result = @ldap_get_entries($ldap, $search);
-
- if (is_array($ldap_result) && sizeof($ldap_result) > 1)
- {
- if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password)))
- {
- @ldap_close($ldap);
-
- $sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type
- FROM ' . USERS_TABLE . "
- WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
- {
- unset($ldap_result);
-
- // User inactive...
- if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
- {
- return array(
- 'status' => LOGIN_ERROR_ACTIVE,
- 'error_msg' => 'ACTIVE_ERROR',
- 'user_row' => $row,
- );
- }
-
- // Successful login... set user_login_attempts to zero...
- return array(
- 'status' => LOGIN_SUCCESS,
- 'error_msg' => false,
- 'user_row' => $row,
- );
- }
- else
- {
- // retrieve default group id
- $sql = 'SELECT group_id
- FROM ' . GROUPS_TABLE . "
- WHERE group_name = '" . $db->sql_escape('REGISTERED') . "'
- AND group_type = " . GROUP_SPECIAL;
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- trigger_error('NO_GROUP');
- }
-
- // generate user account data
- $ldap_user_row = array(
- 'username' => $username,
- 'user_password' => phpbb_hash($password),
- 'user_email' => (!empty($config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($config['ldap_email'])][0]) : '',
- 'group_id' => (int) $row['group_id'],
- 'user_type' => USER_NORMAL,
- 'user_ip' => $user->ip,
- 'user_new' => ($config['new_member_post_limit']) ? 1 : 0,
- );
-
- unset($ldap_result);
-
- // this is the user's first login so create an empty profile
- return array(
- 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
- 'error_msg' => false,
- 'user_row' => $ldap_user_row,
- );
- }
- }
- else
- {
- unset($ldap_result);
- @ldap_close($ldap);
-
- // Give status about wrong password...
- return array(
- 'status' => LOGIN_ERROR_PASSWORD,
- 'error_msg' => 'LOGIN_ERROR_PASSWORD',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
- }
- }
-
- @ldap_close($ldap);
-
- return array(
- 'status' => LOGIN_ERROR_USERNAME,
- 'error_msg' => 'LOGIN_ERROR_USERNAME',
- 'user_row' => array('user_id' => ANONYMOUS),
- );
-}
-
-/**
-* Generates a filter string for ldap_search to find a user
-*
-* @param $username string Username identifying the searched user
-*
-* @return string A filter string for ldap_search
-*/
-function ldap_user_filter($username)
-{
- global $config;
-
- $filter = '(' . $config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')';
- if ($config['ldap_user_filter'])
- {
- $_filter = ($config['ldap_user_filter'][0] == '(' && substr($config['ldap_user_filter'], -1) == ')') ? $config['ldap_user_filter'] : "({$config['ldap_user_filter']})";
- $filter = "(&{$filter}{$_filter})";
- }
- return $filter;
-}
-
-/**
-* Escapes an LDAP AttributeValue
-*/
-function ldap_escape($string)
-{
- return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string);
-}
-
-/**
-* This function is used to output any required fields in the authentication
-* admin panel. It also defines any required configuration table fields.
-*/
-function acp_ldap(&$new)
-{
- global $user;
-
- $tpl = '
-
-
-
' . $user->lang['LDAP_SERVER_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_PORT_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_DN_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_UID_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_USER_FILTER_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_EMAIL_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_USER_EXPLAIN'] . '
-
-
-
-
' . $user->lang['LDAP_PASSWORD_EXPLAIN'] . '
-
-
- ';
-
- // These are fields required in the config table
- return array(
- 'tpl' => $tpl,
- 'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password')
- );
-}
diff --git a/phpBB/includes/auth/provider_apache.php b/phpBB/includes/auth/provider_apache.php
new file mode 100644
index 0000000000..5f6f2862b6
--- /dev/null
+++ b/phpBB/includes/auth/provider_apache.php
@@ -0,0 +1,275 @@
+db = $db;
+ $this->config = $config;
+ $this->request = $request;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER) || $this->user->data['username'] !== htmlspecialchars_decode($this->request->server('PHP_AUTH_USER')))
+ {
+ return $this->user->lang['APACHE_SETUP_BEFORE_USE'];
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $php_auth_user = htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'));
+ $php_auth_pw = htmlspecialchars_decode($this->request->server('PHP_AUTH_PW'));
+
+ if (!empty($php_auth_user) && !empty($php_auth_pw))
+ {
+ if ($php_auth_user !== $username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type
+ FROM ' . USERS_TABLE . "
+ WHERE username = '" . $this->db->sql_escape($php_auth_user) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+
+ // this is the user's first login so create an empty profile
+ return array(
+ 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
+ 'error_msg' => false,
+ 'user_row' => user_row_apache($php_auth_user, $php_auth_pw),
+ );
+ }
+
+ // Not logged into apache
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ if (!$this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ return array();
+ }
+
+ $php_auth_user = htmlspecialchars_decode($this->request->server('PHP_AUTH_USER'));
+ $php_auth_pw = htmlspecialchars_decode($this->request->server('PHP_AUTH_PW'));
+
+ if (!empty($php_auth_user) && !empty($php_auth_pw))
+ {
+ set_var($php_auth_user, $php_auth_user, 'string', true);
+ set_var($php_auth_pw, $php_auth_pw, 'string', true);
+
+ $sql = 'SELECT *
+ FROM ' . USERS_TABLE . "
+ WHERE username = '" . $this->db->sql_escape($php_auth_user) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ return ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE) ? array() : $row;
+ }
+
+ if (!function_exists('user_add'))
+ {
+ include($this->phpbb_root_path . 'includes/functions_user.' . $this->php_ext);
+ }
+
+ // create the user if he does not exist yet
+ user_add(user_row_apache($php_auth_user, $php_auth_pw));
+
+ $sql = 'SELECT *
+ FROM ' . USERS_TABLE . "
+ WHERE username_clean = '" . $this->db->sql_escape(utf8_clean_string($php_auth_user)) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ return $row;
+ }
+ }
+
+ return array();
+ }
+
+ /**
+ * This function generates an array which can be passed to the user_add
+ * function in order to create a user
+ *
+ * @param string $username The username of the new user.
+ * @param string $password The password of the new user.
+ * @return array Contains data that can be passed directly to
+ * the user_add function.
+ */
+ private function user_row($username, $password)
+ {
+ // first retrieve default group id
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ trigger_error('NO_GROUP');
+ }
+
+ // generate user account data
+ return array(
+ 'username' => $username,
+ 'user_password' => phpbb_hash($password),
+ 'user_email' => '',
+ 'group_id' => (int) $row['group_id'],
+ 'user_type' => USER_NORMAL,
+ 'user_ip' => $this->user->ip,
+ 'user_new' => ($this->config['new_member_post_limit']) ? 1 : 0,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate_session($user)
+ {
+ // Check if PHP_AUTH_USER is set and handle this case
+ if ($this->request->is_set('PHP_AUTH_USER', phpbb_request_interface::SERVER))
+ {
+ $php_auth_user = $this->request->server('PHP_AUTH_USER');
+
+ return ($php_auth_user === $user['username']) ? true : false;
+ }
+
+ // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not)
+ if ($user['user_type'] == USER_IGNORE)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function logout($data, $new_session)
+ {
+ return;
+ }
+}
diff --git a/phpBB/includes/auth/provider_db.php b/phpBB/includes/auth/provider_db.php
new file mode 100644
index 0000000000..894041c9cf
--- /dev/null
+++ b/phpBB/includes/auth/provider_db.php
@@ -0,0 +1,337 @@
+db = $db;
+ $this->config = $config;
+ $this->request = $request;
+ $this->user = $user;
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->php_ext = $php_ext;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // Auth plugins get the password untrimmed.
+ // For compatibility we trim() here.
+ $password = trim($password);
+
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $username_clean = utf8_clean_string($username);
+
+ $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts
+ FROM ' . USERS_TABLE . "
+ WHERE username_clean = '" . $this->db->sql_escape($username_clean) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (($this->user->ip && !$this->config['ip_login_limit_use_forwarded']) ||
+ ($this->user->forwarded_for && $this->config['ip_login_limit_use_forwarded']))
+ {
+ $sql = 'SELECT COUNT(*) AS attempts
+ FROM ' . LOGIN_ATTEMPT_TABLE . '
+ WHERE attempt_time > ' . (time() - (int) $this->config['ip_login_limit_time']);
+ if ($this->config['ip_login_limit_use_forwarded'])
+ {
+ $sql .= " AND attempt_forwarded_for = '" . $this->db->sql_escape($this->user->forwarded_for) . "'";
+ }
+ else
+ {
+ $sql .= " AND attempt_ip = '" . $this->db->sql_escape($this->user->ip) . "' ";
+ }
+
+ $result = $this->db->sql_query($sql);
+ $attempts = (int) $this->db->sql_fetchfield('attempts');
+ $this->db->sql_freeresult($result);
+
+ $attempt_data = array(
+ 'attempt_ip' => $this->user->ip,
+ 'attempt_browser' => trim(substr($this->user->browser, 0, 149)),
+ 'attempt_forwarded_for' => $this->user->forwarded_for,
+ 'attempt_time' => time(),
+ 'user_id' => ($row) ? (int) $row['user_id'] : 0,
+ 'username' => $username,
+ 'username_clean' => $username_clean,
+ );
+ $sql = 'INSERT INTO ' . LOGIN_ATTEMPT_TABLE . $this->db->sql_build_array('INSERT', $attempt_data);
+ $result = $this->db->sql_query($sql);
+ }
+ else
+ {
+ $attempts = 0;
+ }
+
+ if (!$row)
+ {
+ if ($this->config['ip_login_limit_max'] && $attempts >= $this->config['ip_login_limit_max'])
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ATTEMPTS,
+ 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $show_captcha = ($this->config['max_login_attempts'] && $row['user_login_attempts'] >= $this->config['max_login_attempts']) ||
+ ($this->config['ip_login_limit_max'] && $attempts >= $this->config['ip_login_limit_max']);
+
+ // If there are too many login attempts, we need to check for a confirm image
+ // Every auth module is able to define what to do by itself...
+ if ($show_captcha)
+ {
+ // Visual Confirmation handling
+ if (!class_exists('phpbb_captcha_factory', false))
+ {
+ include ($this->phpbb_root_path . 'includes/captcha/captcha_factory.' . $this->php_ext);
+ }
+
+ $captcha = phpbb_captcha_factory::get_instance($this->config['captcha_plugin']);
+ $captcha->init(CONFIRM_LOGIN);
+ $vc_response = $captcha->validate($row);
+ if ($vc_response)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ATTEMPTS,
+ 'error_msg' => 'LOGIN_ERROR_ATTEMPTS',
+ 'user_row' => $row,
+ );
+ }
+ else
+ {
+ $captcha->reset();
+ }
+
+ }
+
+ // If the password convert flag is set we need to convert it
+ if ($row['user_pass_convert'])
+ {
+ // enable super globals to get literal value
+ // this is needed to prevent unicode normalization
+ $super_globals_disabled = $this->request->super_globals_disabled();
+ if ($super_globals_disabled)
+ {
+ $this->request->enable_super_globals();
+ }
+
+ // in phpBB2 passwords were used exactly as they were sent, with addslashes applied
+ $password_old_format = isset($_REQUEST['password']) ? (string) $_REQUEST['password'] : '';
+ $password_old_format = (!STRIP) ? addslashes($password_old_format) : $password_old_format;
+ $password_new_format = $this->request->variable('password', '', true);
+
+ if ($super_globals_disabled)
+ {
+ $this->request->disable_super_globals();
+ }
+
+ if ($password == $password_new_format)
+ {
+ if (!function_exists('utf8_to_cp1252'))
+ {
+ include($this->phpbb_root_path . 'includes/utf/data/recode_basic.' . $this->php_ext);
+ }
+
+ // cp1252 is phpBB2's default encoding, characters outside ASCII range might work when converted into that encoding
+ // plain md5 support left in for conversions from other systems.
+ if ((strlen($row['user_password']) == 34 && (phpbb_check_hash(md5($password_old_format), $row['user_password']) || phpbb_check_hash(md5(utf8_to_cp1252($password_old_format)), $row['user_password'])))
+ || (strlen($row['user_password']) == 32 && (md5($password_old_format) == $row['user_password'] || md5(utf8_to_cp1252($password_old_format)) == $row['user_password'])))
+ {
+ $hash = phpbb_hash($password_new_format);
+
+ // Update the password in the users table to the new format and remove user_pass_convert flag
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_password = \'' . $this->db->sql_escape($hash) . '\',
+ user_pass_convert = 0
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+
+ $row['user_pass_convert'] = 0;
+ $row['user_password'] = $hash;
+ }
+ else
+ {
+ // Although we weren't able to convert this password we have to
+ // increase login attempt count to make sure this cannot be exploited
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = user_login_attempts + 1
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
+ $this->db->sql_query($sql);
+
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD_CONVERT,
+ 'error_msg' => 'LOGIN_ERROR_PASSWORD_CONVERT',
+ 'user_row' => $row,
+ );
+ }
+ }
+ }
+
+ // Check password ...
+ if (!$row['user_pass_convert'] && phpbb_check_hash($password, $row['user_password']))
+ {
+ // Check for old password hash...
+ if (strlen($row['user_password']) == 32)
+ {
+ $hash = phpbb_hash($password);
+
+ // Update the password in the users table to the new format
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_password = '" . $this->db->sql_escape($hash) . "',
+ user_pass_convert = 0
+ WHERE user_id = {$row['user_id']}";
+ $this->db->sql_query($sql);
+
+ $row['user_password'] = $hash;
+ }
+
+ $sql = 'DELETE FROM ' . LOGIN_ATTEMPT_TABLE . '
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+
+ if ($row['user_login_attempts'] != 0)
+ {
+ // Successful, reset login attempts (the user passed all stages)
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = 0
+ WHERE user_id = ' . $row['user_id'];
+ $this->db->sql_query($sql);
+ }
+
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login... set user_login_attempts to zero...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+
+ // Password incorrect - increase login attempts
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_login_attempts = user_login_attempts + 1
+ WHERE user_id = ' . (int) $row['user_id'] . '
+ AND user_login_attempts < ' . LOGIN_ATTEMPTS_MAX;
+ $this->db->sql_query($sql);
+
+ // Give status about wrong password...
+ return array(
+ 'status' => ($show_captcha) ? LOGIN_ERROR_ATTEMPTS : LOGIN_ERROR_PASSWORD,
+ 'error_msg' => ($show_captcha) ? 'LOGIN_ERROR_ATTEMPTS' : 'LOGIN_ERROR_PASSWORD',
+ 'user_row' => $row,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function logout($data, $new_session)
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validate_session($user)
+ {
+ return;
+ }
+}
diff --git a/phpBB/includes/auth/provider_interface.php b/phpBB/includes/auth/provider_interface.php
new file mode 100644
index 0000000000..2d1935f8f0
--- /dev/null
+++ b/phpBB/includes/auth/provider_interface.php
@@ -0,0 +1,93 @@
+ status constant
+ * 'error_msg' => string
+ * 'user_row' => array
+ * )
+ */
+ public function login($username, $password);
+
+ /**
+ * Autologin function
+ *
+ * @return array|null containing the user row, empty if no auto login
+ * should take place, or null if not impletmented.
+ */
+ public function autologin();
+
+ /**
+ * This function is used to output any required fields in the authentication
+ * admin panel. It also defines any required configuration table fields.
+ *
+ * @param array $new Contains the new configuration values that have
+ * been set in acp_board.
+ * @return array|null Returns null if not implemented or an array of the
+ * form:
+ * array(
+ * 'tpl' => string
+ * 'config' => array
+ * )
+ */
+ public function acp($new);
+
+ /**
+ * Performs additional actions during logout.
+ *
+ * @param array $data An array corresponding to
+ * phpbb_session::data
+ * @param boolean $new_session True for a new session, false for no new
+ * session.
+ */
+ public function logout($data, $new_session);
+
+ /**
+ * The session validation function checks whether the user is still logged
+ * into phpBB.
+ *
+ * @param array $user
+ * @return boolean true if the given user is authenticated, false if the
+ * session should be closed, or null if not implemented.
+ */
+ public function validate_session($user);
+}
diff --git a/phpBB/includes/auth/provider_ldap.php b/phpBB/includes/auth/provider_ldap.php
new file mode 100644
index 0000000000..f67c1e9247
--- /dev/null
+++ b/phpBB/includes/auth/provider_ldap.php
@@ -0,0 +1,386 @@
+db = $db;
+ $this->config = $config;
+ $this->user = $user;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ if (!@extension_loaded('ldap'))
+ {
+ return $this->user->lang['LDAP_NO_LDAP_EXTENSION'];
+ }
+
+ $this->config['ldap_port'] = (int) $this->config['ldap_port'];
+ if ($this->config['ldap_port'])
+ {
+ $ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']);
+ }
+ else
+ {
+ $ldap = @ldap_connect($this->config['ldap_server']);
+ }
+
+ if (!$ldap)
+ {
+ return $this->user->lang['LDAP_NO_SERVER_CONNECTION'];
+ }
+
+ @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
+ @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
+
+ if ($this->config['ldap_user'] || $this->config['ldap_password'])
+ {
+ if (!@ldap_bind($ldap, htmlspecialchars_decode($this->config['ldap_user']), htmlspecialchars_decode($this->config['ldap_password'])))
+ {
+ return $this->user->lang['LDAP_INCORRECT_USER_PASSWORD'];
+ }
+ }
+
+ // ldap_connect only checks whether the specified server is valid, so the connection might still fail
+ $search = @ldap_search(
+ $ldap,
+ htmlspecialchars_decode($this->config['ldap_base_dn']),
+ $this->ldap_user_filter($this->user->data['username']),
+ (empty($this->config['ldap_email'])) ?
+ array(htmlspecialchars_decode($this->config['ldap_uid'])) :
+ array(htmlspecialchars_decode($this->config['ldap_uid']), htmlspecialchars_decode($this->config['ldap_email'])),
+ 0,
+ 1
+ );
+
+ if ($search === false)
+ {
+ return $this->user->lang['LDAP_SEARCH_FAILED'];
+ }
+
+ $result = @ldap_get_entries($ldap, $search);
+
+ @ldap_close($ldap);
+
+
+ if (!is_array($result) || sizeof($result) < 2)
+ {
+ return sprintf($this->user->lang['LDAP_NO_IDENTITY'], $this->user->data['username']);
+ }
+
+ if (!empty($this->config['ldap_email']) && !isset($result[0][htmlspecialchars_decode($this->config['ldap_email'])]))
+ {
+ return $this->user->lang['LDAP_NO_EMAIL'];
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function login($username, $password)
+ {
+ // do not allow empty password
+ if (!$password)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'NO_PASSWORD_SUPPLIED',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!$username)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ if (!@extension_loaded('ldap'))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_LDAP_EXTENSION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ $this->config['ldap_port'] = (int) $this->config['ldap_port'];
+ if ($this->config['ldap_port'])
+ {
+ $ldap = @ldap_connect($this->config['ldap_server'], $this->config['ldap_port']);
+ }
+ else
+ {
+ $ldap = @ldap_connect($this->config['ldap_server']);
+ }
+
+ if (!$ldap)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
+ @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
+
+ if ($this->config['ldap_user'] || $this->config['ldap_password'])
+ {
+ if (!@ldap_bind($ldap, htmlspecialchars_decode($this->config['ldap_user']), htmlspecialchars_decode($this->config['ldap_password'])))
+ {
+ return array(
+ 'status' => LOGIN_ERROR_EXTERNAL_AUTH,
+ 'error_msg' => 'LDAP_NO_SERVER_CONNECTION',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+ }
+
+ $search = @ldap_search(
+ $ldap,
+ htmlspecialchars_decode($this->config['ldap_base_dn']),
+ $this->ldap_user_filter($username),
+ (empty($this->config['ldap_email'])) ?
+ array(htmlspecialchars_decode($this->config['ldap_uid'])) :
+ array(htmlspecialchars_decode($this->config['ldap_uid']), htmlspecialchars_decode($this->config['ldap_email'])),
+ 0,
+ 1
+ );
+
+ $ldap_result = @ldap_get_entries($ldap, $search);
+
+ if (is_array($ldap_result) && sizeof($ldap_result) > 1)
+ {
+ if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password)))
+ {
+ @ldap_close($ldap);
+
+ $sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type
+ FROM ' . USERS_TABLE . "
+ WHERE username_clean = '" . $this->db->sql_escape(utf8_clean_string($username)) . "'";
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if ($row)
+ {
+ unset($ldap_result);
+
+ // User inactive...
+ if ($row['user_type'] == USER_INACTIVE || $row['user_type'] == USER_IGNORE)
+ {
+ return array(
+ 'status' => LOGIN_ERROR_ACTIVE,
+ 'error_msg' => 'ACTIVE_ERROR',
+ 'user_row' => $row,
+ );
+ }
+
+ // Successful login... set user_login_attempts to zero...
+ return array(
+ 'status' => LOGIN_SUCCESS,
+ 'error_msg' => false,
+ 'user_row' => $row,
+ );
+ }
+ else
+ {
+ // retrieve default group id
+ $sql = 'SELECT group_id
+ FROM ' . GROUPS_TABLE . "
+ WHERE group_name = '" . $this->db->sql_escape('REGISTERED') . "'
+ AND group_type = " . GROUP_SPECIAL;
+ $result = $this->db->sql_query($sql);
+ $row = $this->db->sql_fetchrow($result);
+ $this->db->sql_freeresult($result);
+
+ if (!$row)
+ {
+ trigger_error('NO_GROUP');
+ }
+
+ // generate user account data
+ $ldap_user_row = array(
+ 'username' => $username,
+ 'user_password' => phpbb_hash($password),
+ 'user_email' => (!empty($this->config['ldap_email'])) ? utf8_htmlspecialchars($ldap_result[0][htmlspecialchars_decode($this->config['ldap_email'])][0]) : '',
+ 'group_id' => (int) $row['group_id'],
+ 'user_type' => USER_NORMAL,
+ 'user_ip' => $this->user->ip,
+ 'user_new' => ($this->config['new_member_post_limit']) ? 1 : 0,
+ );
+
+ unset($ldap_result);
+
+ // this is the user's first login so create an empty profile
+ return array(
+ 'status' => LOGIN_SUCCESS_CREATE_PROFILE,
+ 'error_msg' => false,
+ 'user_row' => $ldap_user_row,
+ );
+ }
+ }
+ else
+ {
+ unset($ldap_result);
+ @ldap_close($ldap);
+
+ // Give status about wrong password...
+ return array(
+ 'status' => LOGIN_ERROR_PASSWORD,
+ 'error_msg' => 'LOGIN_ERROR_PASSWORD',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+ }
+
+ @ldap_close($ldap);
+
+ return array(
+ 'status' => LOGIN_ERROR_USERNAME,
+ 'error_msg' => 'LOGIN_ERROR_USERNAME',
+ 'user_row' => array('user_id' => ANONYMOUS),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function autologin()
+ {
+ return;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function acp($new)
+ {
+ $tpl = '
+
+
diff --git a/tests/RUNNING_TESTS.md b/tests/RUNNING_TESTS.md
index f89c1fefeb..f2688ab675 100644
--- a/tests/RUNNING_TESTS.md
+++ b/tests/RUNNING_TESTS.md
@@ -50,9 +50,11 @@ Database Tests
By default all tests requiring a database connection will use sqlite. If you
do not have sqlite installed the tests will be skipped. If you wish to run the
tests on a different database you have to create a test_config.php file within
-your tests directory following the same format as phpBB's config.php. An
-example for mysqli can be found below. More information on configuration
-options can be found on the wiki (see below).
+your tests directory following the same format as phpBB's config.php. Testing
+makes use of a seperate database defined in this config file and before running
+the tests each time this database is deleted. An example for mysqli can be
+found below. More information on configuration options can be found on the
+wiki (see below).
+
+