Merge branch 'develop' of https://github.com/phpbb/phpbb3 into ticket/10411-2

* 'develop' of https://github.com/phpbb/phpbb3: (497 commits)
  [ticket/10986] message.id fallback to SERVER_NAME or phpbb.generated
  [ticket/11358] Changed the name of post parameter.
  [ticket/11358] Changed the action parameter value to represent the link.
  [ticket/11358] Enabled link making all users default for a group.
  [ticket/11358] Removed redundant code and referred proper variable.
  [ticket/11358] Success message even without selecting a user.
  [ticket/11355] Referred proper variable when validating selection.
  [ticket/11355] Wrong error message when no user is selected.
  [ticket/10896] Add missing email validation lost in develop merge
  [ticket/7262] Add note about set_config() not updating is_dynamic.
  [ticket/7262] Add $is_dynamic example to set_config() and set_config_count().
  [ticket/7262] Backport set_config() and set_config_count() docs from develop.
  [ticket/11122] Move rxu to 'Former Contributors' section.
  [ticket/11122] Add EXreaction to docs/AUTHORS.
  [ticket/11298] Fix typo in language key; EXTENSIONS -> EXTENSION
  [ticket/11361] Make sure that array passed to strtr() has the proper format.
  [ticket/11342] Fix "unexpected token" syntax error
  [ticket/11179] remove extra & in function call
  [ticket/11179] correct start parameter in sphinx search
  [ticket/11179] correct start parameter in native author search
  ...

Conflicts:
	phpBB/config/services.yml
	phpBB/includes/functions_user.php
	phpBB/install/schemas/firebird_schema.sql
	phpBB/install/schemas/mssql_schema.sql
	phpBB/install/schemas/mysql_40_schema.sql
	phpBB/install/schemas/mysql_41_schema.sql
	phpBB/install/schemas/oracle_schema.sql
	phpBB/install/schemas/postgres_schema.sql
	phpBB/install/schemas/sqlite_schema.sql
This commit is contained in:
Joas Schilling 2013-02-25 21:03:34 +01:00
commit 8c6a1e50f5
259 changed files with 10483 additions and 3167 deletions

2
.gitignore vendored
View file

@ -2,7 +2,7 @@
/phpunit.xml /phpunit.xml
/phpBB/cache/*.html /phpBB/cache/*.html
/phpBB/cache/*.php /phpBB/cache/*.php
/phpBB/cache/queue.php.lock /phpBB/cache/*.lock
/phpBB/composer.phar /phpBB/composer.phar
/phpBB/config.php /phpBB/config.php
/phpBB/config_dev.php /phpBB/config_dev.php

View file

@ -3,21 +3,28 @@ php:
- 5.3.3 - 5.3.3
- 5.3 - 5.3
- 5.4 - 5.4
- 5.5
env: env:
- DB=mysql - DB=mysql
- DB=postgres - DB=postgres
matrix:
allow_failures:
- php: 5.5
before_script: before_script:
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi" - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'DROP DATABASE IF EXISTS phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi" - sh -c "if [ '$DB' = 'postgres' ]; then psql -c 'create database phpbb_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi" - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS phpbb_tests;'; fi"
- travis/install-php-extensions.sh
- pyrus set auto_discover 1 - pyrus set auto_discover 1
- pyrus install --force phpunit/DbUnit - pyrus install --force phpunit/DbUnit
- phpenv rehash - phpenv rehash
- cd phpBB - cd phpBB
- php ../composer.phar install --dev - php ../composer.phar install --dev
- cd ../ - cd ..
- sh -c "if [ `php -r "echo (int) version_compare(PHP_VERSION, '5.3.19', '>=');"` = "1" ]; then travis/setup-webserver.sh; fi"
script: script:
- phpunit --configuration travis/phpunit-$DB-travis.xml - phpunit --configuration travis/phpunit-$DB-travis.xml

View file

@ -2,17 +2,16 @@
<project name="phpBB" description="The phpBB forum software" default="all" basedir="../"> <project name="phpBB" description="The phpBB forum software" default="all" basedir="../">
<!-- a few settings for the build --> <!-- a few settings for the build -->
<property name="newversion" value="3.0.11" /> <property name="newversion" value="3.1.0-dev" />
<property name="prevversion" value="3.0.10" /> <property name="prevversion" value="3.0.11" />
<property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.11-RC1, 3.0.11-RC2" /> <property name="olderversions" value="3.0.2, 3.0.3, 3.0.4, 3.0.5, 3.0.6, 3.0.7, 3.0.7-PL1, 3.0.8, 3.0.9, 3.0.10" />
<!-- no configuration should be needed beyond this point --> <!-- no configuration should be needed beyond this point -->
<property name="oldversions" value="${olderversions}, ${prevversion}" /> <property name="oldversions" value="${olderversions}, ${prevversion}" />
<property name="versions" value="${oldversions}, ${newversion}" /> <property name="versions" value="${oldversions}, ${newversion}" />
<!-- These are the main targets which you will probably want to use --> <!-- These are the main targets which you will probably want to use -->
<target name="package" depends="clean,prepare,composer,create-package" /> <target name="all" depends="clean,prepare,composer,test,docs,package" />
<target name="all" depends="clean,prepare,composer,test,docs,create-package" />
<target name="build" depends="clean,prepare,composer,test,docs" /> <target name="build" depends="clean,prepare,composer,test,docs" />
<target name="prepare"> <target name="prepare">
@ -43,9 +42,15 @@
<delete dir="build/save" /> <delete dir="build/save" />
</target> </target>
<target name="composer" depends="clean,prepare"> <!--
<exec dir="./phpBB/" This target basically just runs composer in the phpBB tree to ensure
command="php ../composer.phar install" all dependencies are loaded. Additional development dependencies are
loaded because testing framework may depend on them.
-->
<target name="composer">
<exec dir="phpBB"
command="php ../composer.phar install --dev"
checkreturn="true"
passthru="true" /> passthru="true" />
</target> </target>
@ -122,7 +127,7 @@
</target> </target>
<target name="create-package" depends="prepare-new-version,old-version-diffs"> <target name="package" depends="clean,prepare,prepare-new-version,old-version-diffs">
<exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" /> <exec dir="build" command="php -f package.php '${versions}' > logs/package.log" escape="false" />
<exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" /> <exec dir="build" command="php -f build_diff.php '${prevversion}' '${newversion}' > logs/build_diff.log" escape="false" />
@ -162,9 +167,27 @@
command="git archive ${revision} | tar -xf - -C ../${dir}" command="git archive ${revision} | tar -xf - -C ../${dir}"
checkreturn="true" /> checkreturn="true" />
<exec dir="${dir}" <!--
command="php ../composer.phar install" If composer.phar exists in this version of the tree, also export
passthru="true" /> it into ${dir}, install dependencies, then delete it again.
-->
<exec dir="."
command="git ls-tree ${revision} composer.phar"
checkreturn="true"
outputProperty='composer-ls-tree-output' />
<if>
<not><equals arg1="${composer-ls-tree-output}" arg2="" trim="true" /></not>
<then>
<exec dir="."
command="git archive ${revision} composer.phar | tar -xf - -C ${dir}"
checkreturn="true" />
<exec dir="${dir}"
command="php composer.phar install"
checkreturn="true"
passthru="true" />
<delete file="${dir}/composer.phar" />
</then>
</if>
<delete file="${dir}/config.php" /> <delete file="${dir}/config.php" />
<delete dir="${dir}/develop" /> <delete dir="${dir}/develop" />
@ -187,6 +210,7 @@
<delete dir="${dir}/files" /> <delete dir="${dir}/files" />
<delete dir="${dir}/install" /> <delete dir="${dir}/install" />
<delete dir="${dir}/store" /> <delete dir="${dir}/store" />
<delete dir="${dir}/vendor" />
</target> </target>
</project> </project>

View file

@ -42,7 +42,6 @@ if (!$auth->acl_get('a_'))
// We define the admin variables now, because the user is now able to use the admin related features... // We define the admin variables now, because the user is now able to use the admin related features...
define('IN_ADMIN', true); define('IN_ADMIN', true);
$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : './';
// Some oft used variables // Some oft used variables
$safe_mode = (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) === 'on') ? true : false; $safe_mode = (@ini_get('safe_mode') == '1' || strtolower(@ini_get('safe_mode')) === 'on') ? true : false;
@ -52,7 +51,7 @@ $mode = request_var('mode', '');
// Set custom style for admin area // Set custom style for admin area
$phpbb_style->set_ext_dir_prefix('adm/'); $phpbb_style->set_ext_dir_prefix('adm/');
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', ''); $phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), '');
$template->assign_var('T_ASSETS_PATH', $phpbb_root_path . 'assets'); $template->assign_var('T_ASSETS_PATH', $phpbb_root_path . 'assets');
$template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style'); $template->assign_var('T_TEMPLATE_PATH', $phpbb_admin_path . 'style');

View file

@ -7,7 +7,13 @@
<p>{L_EXTENSIONS_EXPLAIN}</p> <p>{L_EXTENSIONS_EXPLAIN}</p>
<p>{L_ENABLE_EXPLAIN}</p> <p>{L_ENABLE_EXPLAIN}</p>
<!-- IF PRE --> <!-- IF MIGRATOR_ERROR -->
<div class="errorbox">
<p><strong>{L_MIGRATION_EXCEPTION_ERROR}</strong></p>
<p>{MIGRATOR_ERROR}</p>
<p><a href="{U_RETURN}">{L_RETURN}</a></p>
</div>
<!-- ELSEIF PRE -->
<div class="errorbox"> <div class="errorbox">
<p>{L_ENABLE_CONFIRM}</p> <p>{L_ENABLE_CONFIRM}</p>
</div> </div>

View file

@ -7,7 +7,13 @@
<p>{L_EXTENSIONS_EXPLAIN}</p> <p>{L_EXTENSIONS_EXPLAIN}</p>
<p>{L_PURGE_EXPLAIN}</p> <p>{L_PURGE_EXPLAIN}</p>
<!-- IF PRE --> <!-- IF MIGRATOR_ERROR -->
<div class="errorbox">
<p><strong>{L_MIGRATION_EXCEPTION_ERROR}</strong></p>
<p>{MIGRATOR_ERROR}</p>
<p><a href="{U_RETURN}">{L_RETURN}</a></p>
</div>
<!-- ELSEIF PRE -->
<div class="errorbox"> <div class="errorbox">
<p>{L_PURGE_CONFIRM}</p> <p>{L_PURGE_CONFIRM}</p>
</div> </div>

View file

@ -241,6 +241,7 @@
<dt><label for="topics_per_page">{L_FORUM_TOPICS_PAGE}{L_COLON}</label><br /><span>{L_FORUM_TOPICS_PAGE_EXPLAIN}</span></dt> <dt><label for="topics_per_page">{L_FORUM_TOPICS_PAGE}{L_COLON}</label><br /><span>{L_FORUM_TOPICS_PAGE_EXPLAIN}</span></dt>
<dd><input type="text" id="topics_per_page" name="topics_per_page" value="{TOPICS_PER_PAGE}" size="4" maxlength="4" /></dd> <dd><input type="text" id="topics_per_page" name="topics_per_page" value="{TOPICS_PER_PAGE}" size="4" maxlength="4" /></dd>
</dl> </dl>
<!-- EVENT acp_forums_normal_settings_append -->
</fieldset> </fieldset>
<fieldset> <fieldset>

View file

@ -76,6 +76,8 @@
</div> </div>
<!-- ENDIF --> <!-- ENDIF -->
<!-- EVENT acp_main_notice_after -->
<table cellspacing="1"> <table cellspacing="1">
<caption>{L_FORUM_STATS}</caption> <caption>{L_FORUM_STATS}</caption>
<col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" /> <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" />
@ -202,6 +204,8 @@
<dd><input type="hidden" name="action" value="purge_cache" /><input class="button2" type="submit" id="action_purge_cache" name="action_purge_cache" value="{L_RUN}" /></dd> <dd><input type="hidden" name="action" value="purge_cache" /><input class="button2" type="submit" id="action_purge_cache" name="action_purge_cache" value="{L_RUN}" /></dd>
</dl> </dl>
</form> </form>
<!-- EVENT acp_main_actions_append -->
</fieldset> </fieldset>
<!-- ENDIF --> <!-- ENDIF -->

View file

@ -53,6 +53,7 @@
<dt><label for="password_confirm">{L_CONFIRM_PASSWORD}{L_COLON}</label><br /><span>{L_CONFIRM_PASSWORD_EXPLAIN}</span></dt> <dt><label for="password_confirm">{L_CONFIRM_PASSWORD}{L_COLON}</label><br /><span>{L_CONFIRM_PASSWORD_EXPLAIN}</span></dt>
<dd><input type="password" id="password_confirm" name="password_confirm" value="" autocomplete="off" /></dd> <dd><input type="password" id="password_confirm" name="password_confirm" value="" autocomplete="off" /></dd>
</dl> </dl>
<!-- EVENT acp_users_overview_options_append -->
<p class="quick"> <p class="quick">
<input class="button1" type="submit" name="update" value="{L_SUBMIT}" /> <input class="button1" type="submit" name="update" value="{L_SUBMIT}" />

View file

@ -2,11 +2,11 @@
"use strict"; "use strict";
var img_templates = { var imgTemplates = {
up: $('.template-up-img'), up: $('.template-up-img'),
up_disabled: $('.template-up-img-disabled'), upDisabled: $('.template-up-img-disabled'),
down: $('.template-down-img'), down: $('.template-down-img'),
down_disabled: $('.template-down-img-disabled') downDisabled: $('.template-down-img-disabled')
}; };
/** /**
@ -15,20 +15,19 @@ var img_templates = {
* an item is moved up. It moves the row up or down, and deactivates / * an item is moved up. It moves the row up or down, and deactivates /
* activates any up / down icons that require it (the ones at the top or bottom). * activates any up / down icons that require it (the ones at the top or bottom).
*/ */
phpbb.add_ajax_callback('row_down', function() { phpbb.addAjaxCallback('row_down', function() {
var el = $(this), var el = $(this),
tr = el.parents('tr'), tr = el.parents('tr'),
tr_swap = tr.next(); trSwap = tr.next();
/* /*
* If the element was the first one, we have to: * If the element was the first one, we have to:
* - Add the up-link to the row we moved * - Add the up-link to the row we moved
* - Remove the up-link on the next row * - Remove the up-link on the next row
*/ */
if (tr.is(':first-child')) if (tr.is(':first-child')) {
{ var upImg = imgTemplates.up.clone().attr('href', tr.attr('data-up'));
var up_img = img_templates.up.clone().attr('href', tr.attr('data-up')); tr.find('.up').html(upImg);
tr.find('.up').html(up_img);
phpbb.ajaxify({ phpbb.ajaxify({
selector: tr.find('.up').children('a'), selector: tr.find('.up').children('a'),
@ -36,45 +35,43 @@ phpbb.add_ajax_callback('row_down', function() {
overlay: false overlay: false
}); });
tr_swap.find('.up').html(img_templates.up_disabled.clone()); trSwap.find('.up').html(imgTemplates.upDisabled.clone());
} }
tr.insertAfter(tr_swap); tr.insertAfter(trSwap);
/* /*
* As well as: * As well as:
* - Remove the down-link on the moved row, if it is now the last row * - Remove the down-link on the moved row, if it is now the last row
* - Add the down-link to the next row, if it was the last row * - Add the down-link to the next row, if it was the last row
*/ */
if (tr.is(':last-child')) if (tr.is(':last-child')) {
{ tr.find('.down').html(imgTemplates.downDisabled.clone());
tr.find('.down').html(img_templates.down_disabled.clone());
var down_img = img_templates.down.clone().attr('href', tr_swap.attr('data-down')); var downImg = imgTemplates.down.clone().attr('href', trSwap.attr('data-down'));
tr_swap.find('.down').html(down_img); trSwap.find('.down').html(downImg);
phpbb.ajaxify({ phpbb.ajaxify({
selector: tr_swap.find('.down').children('a'), selector: trSwap.find('.down').children('a'),
callback: 'row_down', callback: 'row_down',
overlay: false overlay: false
}); });
} }
}); });
phpbb.add_ajax_callback('row_up', function() { phpbb.addAjaxCallback('row_up', function() {
var el = $(this), var el = $(this),
tr = el.parents('tr'), tr = el.parents('tr'),
tr_swap = tr.prev(); trSwap = tr.prev();
/* /*
* If the element was the last one, we have to: * If the element was the last one, we have to:
* - Add the down-link to the row we moved * - Add the down-link to the row we moved
* - Remove the down-link on the next row * - Remove the down-link on the next row
*/ */
if (tr.is(':last-child')) if (tr.is(':last-child')) {
{ var downImg = imgTemplates.down.clone().attr('href', tr.attr('data-down'));
var down_img = img_templates.down.clone().attr('href', tr.attr('data-down')); tr.find('.down').html(downImg);
tr.find('.down').html(down_img);
phpbb.ajaxify({ phpbb.ajaxify({
selector: tr.find('.down').children('a'), selector: tr.find('.down').children('a'),
@ -82,25 +79,24 @@ phpbb.add_ajax_callback('row_up', function() {
overlay: false overlay: false
}); });
tr_swap.find('.down').html(img_templates.down_disabled.clone()); trSwap.find('.down').html(imgTemplates.downDisabled.clone());
} }
tr.insertBefore(tr_swap); tr.insertBefore(trSwap);
/* /*
* As well as: * As well as:
* - Remove the up-link on the moved row, if it is now the first row * - Remove the up-link on the moved row, if it is now the first row
* - Add the up-link to the previous row, if it was the first row * - Add the up-link to the previous row, if it was the first row
*/ */
if (tr.is(':first-child')) if (tr.is(':first-child')) {
{ tr.find('.up').html(imgTemplates.upDisabled.clone());
tr.find('.up').html(img_templates.up_disabled.clone());
var up_img = img_templates.up.clone().attr('href', tr_swap.attr('data-up')); var upImg = imgTemplates.up.clone().attr('href', trSwap.attr('data-up'));
tr_swap.find('.up').html(up_img); trSwap.find('.up').html(upImg);
phpbb.ajaxify({ phpbb.ajaxify({
selector: tr_swap.find('.up').children('a'), selector: trSwap.find('.up').children('a'),
callback: 'row_up', callback: 'row_up',
overlay: false overlay: false
}); });
@ -112,29 +108,26 @@ phpbb.add_ajax_callback('row_up', function() {
* It does this by replacing the text, and replacing all instances of "activate" * It does this by replacing the text, and replacing all instances of "activate"
* in the href with "deactivate", and vice versa. * in the href with "deactivate", and vice versa.
*/ */
phpbb.add_ajax_callback('activate_deactivate', function(res) { phpbb.addAjaxCallback('activate_deactivate', function(res) {
var el = $(this), var el = $(this),
new_href = el.attr('href'); newHref = el.attr('href');
el.text(res.text); el.text(res.text);
if (new_href.indexOf('deactivate') !== -1) if (newHref.indexOf('deactivate') !== -1) {
{ newHref = newHref.replace('deactivate', 'activate')
new_href = new_href.replace('deactivate', 'activate') } else {
} newHref = newHref.replace('activate', 'deactivate')
else
{
new_href = new_href.replace('activate', 'deactivate')
} }
el.attr('href', new_href); el.attr('href', newHref);
}); });
/** /**
* The removes the parent row of the link or form that triggered the callback, * The removes the parent row of the link or form that triggered the callback,
* and is good for stuff like the removal of forums. * and is good for stuff like the removal of forums.
*/ */
phpbb.add_ajax_callback('row_delete', function() { phpbb.addAjaxCallback('row_delete', function() {
$(this).parents('tr').remove(); $(this).parents('tr').remove();
}); });
@ -145,8 +138,7 @@ $('[data-ajax]').each(function() {
ajax = $this.attr('data-ajax'), ajax = $this.attr('data-ajax'),
fn; fn;
if (ajax !== 'false') if (ajax !== 'false') {
{
fn = (ajax !== 'true') ? ajax : null; fn = (ajax !== 'true') ? ajax : null;
phpbb.ajaxify({ phpbb.ajaxify({
selector: this, selector: this,

View file

@ -5,7 +5,7 @@
<!-- IF META -->{META}<!-- ENDIF --> <!-- IF META -->{META}<!-- ENDIF -->
<title>{PAGE_TITLE}</title> <title>{PAGE_TITLE}</title>
<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> <link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
<script type="text/javascript"> <script type="text/javascript">
// <![CDATA[ // <![CDATA[
@ -49,7 +49,7 @@ function dE(n, s, type)
</form> </form>
<!-- ENDIF --> <!-- ENDIF -->
</div> </div>
<div id="page-body"> <div id="page-body">
<div id="tabs"> <div id="tabs">
<ul> <ul>
@ -73,5 +73,5 @@ function dE(n, s, type)
<!-- END l_block2 --> <!-- END l_block2 -->
</ul> </ul>
</div> </div>
<div id="main" class="install-body"> <div id="main" class="install-body">

View file

@ -5,7 +5,7 @@
<!-- IF META -->{META}<!-- ENDIF --> <!-- IF META -->{META}<!-- ENDIF -->
<title>{PAGE_TITLE}</title> <title>{PAGE_TITLE}</title>
<link href="../adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> <link href="{T_TEMPLATE_PATH}/admin.css" rel="stylesheet" type="text/css" media="screen" />
<script type="text/javascript"> <script type="text/javascript">
// <![CDATA[ // <![CDATA[

View file

@ -42,5 +42,7 @@
<!-- INCLUDEJS ajax.js --> <!-- INCLUDEJS ajax.js -->
{SCRIPTS} {SCRIPTS}
<!-- EVENT acp_overall_footer_after -->
</body> </body>
</html> </html>

View file

@ -155,6 +155,7 @@ function switch_menu()
// ]]> // ]]>
</script> </script>
<!-- EVENT acp_overall_header_head_append -->
</head> </head>
<body class="{S_CONTENT_DIRECTION}"> <body class="{S_CONTENT_DIRECTION}">

View file

@ -18,6 +18,7 @@
<script type="text/javascript" src="{T_JQUERY_LINK}"></script> <script type="text/javascript" src="{T_JQUERY_LINK}"></script>
<!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF --> <!-- IF S_JQUERY_FALLBACK --><script type="text/javascript">window.jQuery || document.write(unescape('%3Cscript src="{T_ASSETS_PATH}/javascript/jquery.js?assets_version={T_ASSETS_VERSION}" type="text/javascript"%3E%3C/script%3E'));</script><!-- ENDIF -->
<!-- EVENT acp_simple_footer_after -->
</body> </body>
</html> </html>

View file

@ -101,6 +101,7 @@ function find_username(url)
// ]]> // ]]>
</script> </script>
<!-- EVENT acp_simple_header_head_append -->
</head> </head>
<body class="{S_CONTENT_DIRECTION}"> <body class="{S_CONTENT_DIRECTION}">

View file

@ -1,11 +1,11 @@
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
$('#tz_date').change(function() { $('#tz_date').change(function() {
phpbb.timezone_switch_date(false); phpbb.timezoneSwitchDate(false);
}); });
$(document).ready( $(document).ready(
phpbb.timezone_enable_date_selection phpbb.timezoneEnableDateSelection
); );
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -21,10 +21,8 @@ $user->session_begin(false);
$auth->acl($user->data); $auth->acl($user->data);
$user->setup(); $user->setup();
$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : './';
// Set custom template for admin area // Set custom template for admin area
$phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', ''); $phpbb_style->set_custom_style('admin', $phpbb_admin_path . 'style', array(), '');
$template->set_filenames(array( $template->set_filenames(array(
'body' => 'colour_swatch.html') 'body' => 'colour_swatch.html')

View file

@ -1,5 +1,5 @@
var phpbb = {}; var phpbb = {};
phpbb.alert_time = 100; phpbb.alertTime = 100;
(function($) { // Avoid conflicts with other libraries (function($) { // Avoid conflicts with other libraries
@ -12,35 +12,42 @@ var keymap = {
}; };
var dark = $('#darkenwrapper'); var dark = $('#darkenwrapper');
var loading_alert = $('#loadingalert'); var loadingAlert = $('#loadingalert');
var phpbbAlertTimer = null;
/** /**
* Display a loading screen. * Display a loading screen
* *
* @returns object Returns loading_alert. * @returns object Returns loadingAlert.
*/ */
phpbb.loading_alert = function() { phpbb.loadingAlert = function() {
if (dark.is(':visible')) if (dark.is(':visible')) {
{ loadingAlert.fadeIn(phpbb.alertTime);
loading_alert.fadeIn(phpbb.alert_time); } else {
} loadingAlert.show();
else dark.fadeIn(phpbb.alertTime, function() {
{
loading_alert.show();
dark.fadeIn(phpbb.alert_time, function() {
// Wait five seconds and display an error if nothing has been returned by then. // Wait five seconds and display an error if nothing has been returned by then.
setTimeout(function() { phpbbAlertTimer = setTimeout(function() {
if (loading_alert.is(':visible')) if (loadingAlert.is(':visible')) {
{
phpbb.alert($('#phpbb_alert').attr('data-l-err'), $('#phpbb_alert').attr('data-l-timeout-processing-req')); phpbb.alert($('#phpbb_alert').attr('data-l-err'), $('#phpbb_alert').attr('data-l-timeout-processing-req'));
} }
}, 5000); }, 5000);
}); });
} }
return loading_alert; return loadingAlert;
} };
/**
* Clear loading alert timeout
*/
phpbb.clearLoadingTimeout = function() {
if (phpbbAlertTimer !== null) {
clearTimeout(phpbbAlertTimer);
phpbbAlertTimer = null;
}
};
/** /**
* Display a simple alert similar to JSs native alert(). * Display a simple alert similar to JSs native alert().
@ -67,7 +74,7 @@ phpbb.alert = function(title, msg, fadedark) {
div.find('.alert_close').unbind('click'); div.find('.alert_close').unbind('click');
fade = (typeof fadedark !== 'undefined' && !fadedark) ? div : dark; fade = (typeof fadedark !== 'undefined' && !fadedark) ? div : dark;
fade.fadeOut(phpbb.alert_time, function() { fade.fadeOut(phpbb.alertTime, function() {
div.hide(); div.hide();
}); });
@ -90,27 +97,22 @@ phpbb.alert = function(title, msg, fadedark) {
e.preventDefault(); e.preventDefault();
}); });
if (loading_alert.is(':visible')) if (loadingAlert.is(':visible')) {
{ loadingAlert.fadeOut(phpbb.alertTime, function() {
loading_alert.fadeOut(phpbb.alert_time, function() {
dark.append(div); dark.append(div);
div.fadeIn(phpbb.alert_time); div.fadeIn(phpbb.alertTime);
}); });
} } else if (dark.is(':visible')) {
else if (dark.is(':visible'))
{
dark.append(div); dark.append(div);
div.fadeIn(phpbb.alert_time); div.fadeIn(phpbb.alertTime);
} } else {
else
{
dark.append(div); dark.append(div);
div.show(); div.show();
dark.fadeIn(phpbb.alert_time); dark.fadeIn(phpbb.alertTime);
} }
return div; return div;
} };
/** /**
* Display a simple yes / no box to the user. * Display a simple yes / no box to the user.
@ -133,13 +135,13 @@ phpbb.confirm = function(msg, callback, fadedark) {
e.stopPropagation(); e.stopPropagation();
}); });
var click_handler = function(e) { var clickHandler = function(e) {
var res = this.className === 'button1'; var res = this.className === 'button1';
var fade = (typeof fadedark !== 'undefined' && !fadedark && res) ? div : dark; var fade = (typeof fadedark !== 'undefined' && !fadedark && res) ? div : dark;
fade.fadeOut(phpbb.alert_time, function() { fade.fadeOut(phpbb.alertTime, function() {
div.hide(); div.hide();
}); });
div.find('input[type="button"]').unbind('click', click_handler); div.find('input[type="button"]').unbind('click', clickHandler);
callback(res); callback(res);
if (e) { if (e) {
@ -147,11 +149,11 @@ phpbb.confirm = function(msg, callback, fadedark) {
e.stopPropagation(); e.stopPropagation();
} }
}; };
div.find('input[type="button"]').one('click', click_handler); div.find('input[type="button"]').one('click', clickHandler);
dark.one('click', function(e) { dark.one('click', function(e) {
div.find('.alert_close').unbind('click'); div.find('.alert_close').unbind('click');
dark.fadeOut(phpbb.alert_time, function() { dark.fadeOut(phpbb.alertTime, function() {
div.hide(); div.hide();
}); });
callback(false); callback(false);
@ -174,7 +176,7 @@ phpbb.confirm = function(msg, callback, fadedark) {
div.find('.alert_close').one('click', function(e) { div.find('.alert_close').one('click', function(e) {
var fade = (typeof fadedark !== 'undefined' && fadedark) ? div : dark; var fade = (typeof fadedark !== 'undefined' && fadedark) ? div : dark;
fade.fadeOut(phpbb.alert_time, function() { fade.fadeOut(phpbb.alertTime, function() {
div.hide(); div.hide();
}); });
callback(false); callback(false);
@ -182,27 +184,22 @@ phpbb.confirm = function(msg, callback, fadedark) {
e.preventDefault(); e.preventDefault();
}); });
if (loading_alert.is(':visible')) if (loadingAlert.is(':visible')) {
{ loadingAlert.fadeOut(phpbb.alertTime, function() {
loading_alert.fadeOut(phpbb.alert_time, function() {
dark.append(div); dark.append(div);
div.fadeIn(phpbb.alert_time); div.fadeIn(phpbb.alertTime);
}); });
} } else if (dark.is(':visible')) {
else if (dark.is(':visible'))
{
dark.append(div); dark.append(div);
div.fadeIn(phpbb.alert_time); div.fadeIn(phpbb.alertTime);
} } else {
else
{
dark.append(div); dark.append(div);
div.show(); div.show();
dark.fadeIn(phpbb.alert_time); dark.fadeIn(phpbb.alertTime);
} }
return div; return div;
} };
/** /**
* Turn a querystring into an array. * Turn a querystring into an array.
@ -210,17 +207,16 @@ phpbb.confirm = function(msg, callback, fadedark) {
* @argument string string The querystring to parse. * @argument string string The querystring to parse.
* @returns object The object created. * @returns object The object created.
*/ */
phpbb.parse_querystring = function(string) { phpbb.parseQuerystring = function(string) {
var params = {}, i, split; var params = {}, i, split;
string = string.split('&'); string = string.split('&');
for (i = 0; i < string.length; i++) for (i = 0; i < string.length; i++) {
{
split = string[i].split('='); split = string[i].split('=');
params[split[0]] = decodeURIComponent(split[1]); params[split[0]] = decodeURIComponent(split[1]);
} }
return params; return params;
} };
/** /**
@ -246,14 +242,13 @@ phpbb.ajaxify = function(options) {
refresh = options.refresh, refresh = options.refresh,
callback = options.callback, callback = options.callback,
overlay = (typeof options.overlay !== 'undefined') ? options.overlay : true, overlay = (typeof options.overlay !== 'undefined') ? options.overlay : true,
is_form = elements.is('form'), isForm = elements.is('form'),
event_name = is_form ? 'submit' : 'click'; eventName = isForm ? 'submit' : 'click';
elements.bind(event_name, function(event) { elements.bind(eventName, function(event) {
var action, method, data, submit, that = this, $this = $(this); var action, method, data, submit, that = this, $this = $(this);
if ($this.find('input[type="submit"][data-clicked]').attr('data-ajax') === 'false') if ($this.find('input[type="submit"][data-clicked]').attr('data-ajax') === 'false') {
{
return; return;
} }
@ -267,110 +262,88 @@ phpbb.ajaxify = function(options) {
* *
* @param object res The object sent back by the server. * @param object res The object sent back by the server.
*/ */
function return_handler(res) function returnHandler(res) {
{
var alert; var alert;
phpbb.clearLoadingTimeout();
// Is a confirmation required? // Is a confirmation required?
if (typeof res.S_CONFIRM_ACTION === 'undefined') if (typeof res.S_CONFIRM_ACTION === 'undefined') {
{
// If a confirmation is not required, display an alert and call the // If a confirmation is not required, display an alert and call the
// callbacks. // callbacks.
if (typeof res.MESSAGE_TITLE !== 'undefined') if (typeof res.MESSAGE_TITLE !== 'undefined') {
{
alert = phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT); alert = phpbb.alert(res.MESSAGE_TITLE, res.MESSAGE_TEXT);
} } else {
else dark.fadeOut(phpbb.alertTime);
{
dark.fadeOut(phpbb.alert_time);
} }
if (typeof phpbb.ajax_callbacks[callback] === 'function') if (typeof phpbb.ajaxCallbacks[callback] === 'function') {
{ phpbb.ajaxCallbacks[callback].call(that, res);
phpbb.ajax_callbacks[callback].call(that, res);
} }
// If the server says to refresh the page, check whether the page should // If the server says to refresh the page, check whether the page should
// be refreshed and refresh page after specified time if required. // be refreshed and refresh page after specified time if required.
if (res.REFRESH_DATA) if (res.REFRESH_DATA) {
{ if (typeof refresh === 'function') {
if (typeof refresh === 'function')
{
refresh = refresh(res.REFRESH_DATA.url); refresh = refresh(res.REFRESH_DATA.url);
} } else if (typeof refresh !== 'boolean') {
else if (typeof refresh !== 'boolean')
{
refresh = false; refresh = false;
} }
setTimeout(function() { setTimeout(function() {
if (refresh) if (refresh) {
{
window.location = res.REFRESH_DATA.url; window.location = res.REFRESH_DATA.url;
} }
// Hide the alert even if we refresh the page, in case the user // Hide the alert even if we refresh the page, in case the user
// presses the back button. // presses the back button.
dark.fadeOut(phpbb.alert_time, function() { dark.fadeOut(phpbb.alertTime, function() {
alert.hide(); alert.hide();
}); });
}, res.REFRESH_DATA.time * 1000); // Server specifies time in seconds }, res.REFRESH_DATA.time * 1000); // Server specifies time in seconds
} }
} } else {
else
{
// If confirmation is required, display a diologue to the user. // If confirmation is required, display a diologue to the user.
phpbb.confirm(res.MESSAGE_TEXT, function(del) { phpbb.confirm(res.MESSAGE_TEXT, function(del) {
if (del) if (del) {
{ phpbb.loadingAlert();
phpbb.loading_alert();
data = $('<form>' + res.S_HIDDEN_FIELDS + '</form>').serialize(); data = $('<form>' + res.S_HIDDEN_FIELDS + '</form>').serialize();
$.ajax({ $.ajax({
url: res.S_CONFIRM_ACTION, url: res.S_CONFIRM_ACTION,
type: 'POST', type: 'POST',
data: data + '&confirm=' + res.YES_VALUE, data: data + '&confirm=' + res.YES_VALUE,
success: return_handler, success: returnHandler,
error: error_handler error: errorHandler
}); });
} }
}, false); }, false);
} }
} }
function error_handler() function errorHandler() {
{
var alert; var alert;
phpbb.clearLoadingTimeout();
alert = phpbb.alert(dark.attr('data-ajax-error-title'), dark.attr('data-ajax-error-text')); alert = phpbb.alert(dark.attr('data-ajax-error-title'), dark.attr('data-ajax-error-text'));
setTimeout(function () {
dark.fadeOut(phpbb.alert_time, function() {
alert.hide();
});
}, 5000);
} }
// If the element is a form, POST must be used and some extra data must // If the element is a form, POST must be used and some extra data must
// be taken from the form. // be taken from the form.
var run_filter = (typeof options.filter === 'function'); var runFilter = (typeof options.filter === 'function');
if (is_form) if (isForm) {
{
action = $this.attr('action').replace('&amp;', '&'); action = $this.attr('action').replace('&amp;', '&');
data = $this.serializeArray(); data = $this.serializeArray();
method = $this.attr('method') || 'GET'; method = $this.attr('method') || 'GET';
if ($this.find('input[type="submit"][data-clicked]')) if ($this.find('input[type="submit"][data-clicked]')) {
{
submit = $this.find('input[type="submit"][data-clicked]'); submit = $this.find('input[type="submit"][data-clicked]');
data.push({ data.push({
name: submit.attr('name'), name: submit.attr('name'),
value: submit.val() value: submit.val()
}); });
} }
} } else {
else
{
action = this.href; action = this.href;
data = null; data = null;
method = 'GET'; method = 'GET';
@ -378,28 +351,27 @@ phpbb.ajaxify = function(options) {
// If filter function returns false, cancel the AJAX functionality, // If filter function returns false, cancel the AJAX functionality,
// and return true (meaning that the HTTP request will be sent normally). // and return true (meaning that the HTTP request will be sent normally).
if (run_filter && !options.filter.call(this, data)) if (runFilter && !options.filter.call(this, data)) {
{
return; return;
} }
if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') == 'true')) if (overlay && (typeof $this.attr('data-overlay') === 'undefined' || $this.attr('data-overlay') == 'true'))
{ {
phpbb.loading_alert(); phpbb.loadingAlert();
} }
$.ajax({ $.ajax({
url: action, url: action,
type: method, type: method,
data: data, data: data,
success: return_handler, success: returnHandler,
error: error_handler error: errorHandler
}); });
event.preventDefault(); event.preventDefault();
}); });
if (is_form) { if (isForm) {
elements.find('input:submit').click(function () { elements.find('input:submit').click(function () {
var $this = $(this); var $this = $(this);
@ -409,14 +381,14 @@ phpbb.ajaxify = function(options) {
} }
return this; return this;
} };
/** /**
* Hide the optgroups that are not the selected timezone * Hide the optgroups that are not the selected timezone
* *
* @param bool keep_selection Shall we keep the value selected, or shall the user be forced to repick one. * @param bool keepSelection Shall we keep the value selected, or shall the user be forced to repick one.
*/ */
phpbb.timezone_switch_date = function(keep_selection) { phpbb.timezoneSwitchDate = function(keepSelection) {
if ($('#timezone_copy').length == 0) { if ($('#timezone_copy').length == 0) {
// We make a backup of the original dropdown, so we can remove optgroups // We make a backup of the original dropdown, so we can remove optgroups
// instead of setting display to none, because IE and chrome will not // instead of setting display to none, because IE and chrome will not
@ -440,27 +412,30 @@ phpbb.timezone_switch_date = function(keep_selection) {
if ($("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option").size() == 1) { if ($("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option").size() == 1) {
// If there is only one timezone for the selected date, we just select that automatically. // If there is only one timezone for the selected date, we just select that automatically.
$("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option:first").attr('selected', true); $("#timezone > optgroup[label='" + $('#tz_date').val() + "'] > option:first").attr('selected', true);
keep_selection = true; keepSelection = true;
} }
if (typeof keep_selection !== 'undefined' && !keep_selection) { if (typeof keepSelection !== 'undefined' && !keepSelection) {
$('#timezone > option:first').attr('selected', true); var timezoneOptions = $('#timezone > optgroup option');
if (timezoneOptions.filter(':selected').length <= 0) {
timezoneOptions.filter(':first').attr('selected', true);
}
} }
} };
/** /**
* Display the date/time select * Display the date/time select
*/ */
phpbb.timezone_enable_date_selection = function() { phpbb.timezoneEnableDateSelection = function() {
$('#tz_select_date').css('display', 'block'); $('#tz_select_date').css('display', 'block');
} };
/** /**
* Preselect a date/time or suggest one, if it is not picked. * Preselect a date/time or suggest one, if it is not picked.
* *
* @param bool force_selector Shall we select the suggestion? * @param bool forceSelector Shall we select the suggestion?
*/ */
phpbb.timezone_preselect_select = function(force_selector) { phpbb.timezonePreselectSelect = function(forceSelector) {
// The offset returned here is in minutes and negated. // The offset returned here is in minutes and negated.
// http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp // http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp
@ -489,21 +464,21 @@ phpbb.timezone_preselect_select = function(force_selector) {
} }
var prefix = 'GMT' + sign + hours + ':' + minutes; var prefix = 'GMT' + sign + hours + ':' + minutes;
var prefix_length = prefix.length; var prefixLength = prefix.length;
var selector_options = $('#tz_date > option'); var selectorOptions = $('#tz_date > option');
for (var i = 0; i < selector_options.length; ++i) { for (var i = 0; i < selectorOptions.length; ++i) {
var option = selector_options[i]; var option = selectorOptions[i];
if (option.value.substring(0, prefix_length) == prefix) { if (option.value.substring(0, prefixLength) == prefix) {
if ($('#tz_date').val() != option.value && !force_selector) { if ($('#tz_date').val() != option.value && !forceSelector) {
// We do not select the option for the user, but notify him, // We do not select the option for the user, but notify him,
// that we would suggest a different setting. // that we would suggest a different setting.
phpbb.timezone_switch_date(true); phpbb.timezoneSwitchDate(true);
$('#tz_select_date_suggest').css('display', 'inline'); $('#tz_select_date_suggest').css('display', 'inline');
} else { } else {
option.selected = true; option.selected = true;
phpbb.timezone_switch_date(!force_selector); phpbb.timezoneSwitchDate(!forceSelector);
$('#tz_select_date_suggest').css('display', 'none'); $('#tz_select_date_suggest').css('display', 'none');
} }
@ -515,9 +490,9 @@ phpbb.timezone_preselect_select = function(force_selector) {
return; return;
} }
} }
} };
phpbb.ajax_callbacks = {}; phpbb.ajaxCallbacks = {};
/** /**
* Adds an AJAX callback to be used by phpbb.ajaxify. * Adds an AJAX callback to be used by phpbb.ajaxify.
@ -527,14 +502,12 @@ phpbb.ajax_callbacks = {};
* @param string id The name of the callback. * @param string id The name of the callback.
* @param function callback The callback to be called. * @param function callback The callback to be called.
*/ */
phpbb.add_ajax_callback = function(id, callback) phpbb.addAjaxCallback = function(id, callback) {
{ if (typeof callback === 'function') {
if (typeof callback === 'function') phpbb.ajaxCallbacks[id] = callback;
{
phpbb.ajax_callbacks[id] = callback;
} }
return this; return this;
} };
/** /**
@ -542,14 +515,14 @@ phpbb.add_ajax_callback = function(id, callback)
* the alt-text data attribute, and replaces the text in the attribute with the * the alt-text data attribute, and replaces the text in the attribute with the
* current text so that the process can be repeated. * current text so that the process can be repeated.
*/ */
phpbb.add_ajax_callback('alt_text', function() { phpbb.addAjaxCallback('alt_text', function() {
var el = $(this), var el = $(this),
alt_text; altText;
alt_text = el.attr('data-alt-text'); altText = el.attr('data-alt-text');
el.attr('data-alt-text', el.text()); el.attr('data-alt-text', el.text());
el.attr('title', alt_text); el.attr('title', altText);
el.text(alt_text); el.text(altText);
}); });
/** /**
@ -561,28 +534,28 @@ phpbb.add_ajax_callback('alt_text', function() {
* Additionally it replaces the class of the link's parent * Additionally it replaces the class of the link's parent
* and changes the link itself. * and changes the link itself.
*/ */
phpbb.add_ajax_callback('toggle_link', function() { phpbb.addAjaxCallback('toggle_link', function() {
var el = $(this), var el = $(this),
toggle_text, toggleText,
toggle_url, toggleUrl,
toggle_class; toggleClass;
// Toggle link text // Toggle link text
toggle_text = el.attr('data-toggle-text'); toggleText = el.attr('data-toggle-text');
el.attr('data-toggle-text', el.text()); el.attr('data-toggle-text', el.text());
el.attr('title', toggle_text); el.attr('title', toggleText);
el.text(toggle_text); el.text(toggleText);
// Toggle link url // Toggle link url
toggle_url = el.attr('data-toggle-url'); toggleUrl = el.attr('data-toggle-url');
el.attr('data-toggle-url', el.attr('href')); el.attr('data-toggle-url', el.attr('href'));
el.attr('href', toggle_url); el.attr('href', toggleUrl);
// Toggle class of link parent // Toggle class of link parent
toggle_class = el.attr('data-toggle-class'); toggleClass = el.attr('data-toggle-class');
el.attr('data-toggle-class', el.parent().attr('class')); el.attr('data-toggle-class', el.parent().attr('class'));
el.parent().attr('class', toggle_class); el.parent().attr('class', toggleClass);
}); });
})(jQuery); // Avoid conflicts with other libraries })(jQuery); // Avoid conflicts with other libraries

View file

@ -63,6 +63,10 @@ if (!defined('PHPBB_INSTALLED'))
exit; exit;
} }
// In case $phpbb_adm_relative_path is not set (in case of an update), use the default.
$phpbb_adm_relative_path = (isset($phpbb_adm_relative_path)) ? $phpbb_adm_relative_path : 'adm/';
$phpbb_admin_path = (defined('PHPBB_ADMIN_PATH')) ? PHPBB_ADMIN_PATH : $phpbb_root_path . $phpbb_adm_relative_path;
// Include files // Include files
require($phpbb_root_path . 'includes/class_loader.' . $phpEx); require($phpbb_root_path . 'includes/class_loader.' . $phpEx);
@ -71,7 +75,6 @@ require($phpbb_root_path . 'includes/functions_content.' . $phpEx);
require($phpbb_root_path . 'includes/functions_container.' . $phpEx); require($phpbb_root_path . 'includes/functions_container.' . $phpEx);
require($phpbb_root_path . 'includes/constants.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/db/' . ltrim($dbms, 'dbal_') . '.' . $phpEx);
require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx); require($phpbb_root_path . 'includes/utf/utf_tools.' . $phpEx);
// Set PHP error handler to ours // Set PHP error handler to ours
@ -84,18 +87,7 @@ $phpbb_class_loader_ext = new phpbb_class_loader('phpbb_ext_', "{$phpbb_root_pat
$phpbb_class_loader_ext->register(); $phpbb_class_loader_ext->register();
// Set up container // Set up container
$phpbb_container = phpbb_create_dumped_container_unless_debug( $phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx);
array(
new phpbb_di_extension_config($phpbb_root_path . 'config.' . $phpEx),
new phpbb_di_extension_core($phpbb_root_path),
),
array(
new phpbb_di_pass_collection_pass(),
new phpbb_di_pass_kernel_pass(),
),
$phpbb_root_path,
$phpEx
);
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));
@ -128,8 +120,9 @@ $phpbb_style = $phpbb_container->get('style');
// Add own hook handler // Add own hook handler
require($phpbb_root_path . 'includes/hooks/index.' . $phpEx); require($phpbb_root_path . 'includes/hooks/index.' . $phpEx);
$phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('phpbb_template', 'display'))); $phpbb_hook = new phpbb_hook(array('exit_handler', 'phpbb_user_session_handler', 'append_sid', array('phpbb_template', 'display')));
$phpbb_hook_finder = $phpbb_container->get('hook_finder');
foreach ($cache->obtain_hooks() as $hook) foreach ($phpbb_hook_finder->find() as $hook)
{ {
@include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx); @include($phpbb_root_path . 'includes/hooks/' . $hook . '.' . $phpEx);
} }

View file

@ -6,6 +6,8 @@ services:
- %core.php_ext% - %core.php_ext%
- @config - @config
- @dbal.conn - @dbal.conn
calls:
- [set_name, [cron.task.core.prune_all_forums]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -16,6 +18,8 @@ services:
- %core.php_ext% - %core.php_ext%
- @config - @config
- @dbal.conn - @dbal.conn
calls:
- [set_name, [cron.task.core.prune_forum]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -25,6 +29,8 @@ services:
- %core.root_path% - %core.root_path%
- %core.php_ext% - %core.php_ext%
- @config - @config
calls:
- [set_name, [cron.task.core.queue]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -33,6 +39,8 @@ services:
arguments: arguments:
- @config - @config
- @cache.driver - @cache.driver
calls:
- [set_name, [cron.task.core.tidy_cache]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -42,6 +50,8 @@ services:
- %core.root_path% - %core.root_path%
- %core.php_ext% - %core.php_ext%
- @config - @config
calls:
- [set_name, [cron.task.core.tidy_database]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -54,6 +64,8 @@ services:
- @config - @config
- @dbal.conn - @dbal.conn
- @user - @user
calls:
- [set_name, [cron.task.core.tidy_search]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -62,6 +74,8 @@ services:
arguments: arguments:
- @config - @config
- @user - @user
calls:
- [set_name, [cron.task.core.tidy_sessions]]
tags: tags:
- { name: cron.task } - { name: cron.task }
@ -71,5 +85,7 @@ services:
- %core.root_path% - %core.root_path%
- %core.php_ext% - %core.php_ext%
- @config - @config
calls:
- [set_name, [cron.task.core.tidy_warnings]]
tags: tags:
- { name: cron.task } - { name: cron.task }

49
phpBB/config/migrator.yml Normal file
View file

@ -0,0 +1,49 @@
services:
migrator:
class: phpbb_db_migrator
arguments:
- @config
- @dbal.conn
- @dbal.tools
- %tables.migrations%
- %core.root_path%
- %core.php_ext%
- %core.table_prefix%
- @migrator.tool_collection
migrator.tool_collection:
class: phpbb_di_service_collection
arguments:
- @service_container
tags:
- { name: service_collection, tag: migrator.tool }
migrator.tool.config:
class: phpbb_db_migration_tool_config
arguments:
- @config
tags:
- { name: migrator.tool }
migrator.tool.module:
class: phpbb_db_migration_tool_module
arguments:
- @dbal.conn
- @cache
- @user
- %core.root_path%
- %core.php_ext%
- %tables.modules%
tags:
- { name: migrator.tool }
migrator.tool.permission:
class: phpbb_db_migration_tool_permission
arguments:
- @dbal.conn
- @cache
- @auth
- %core.root_path%
- %core.php_ext%
tags:
- { name: migrator.tool }

View file

@ -1,6 +1,7 @@
imports: imports:
- { resource: tables.yml } - { resource: tables.yml }
- { resource: cron_tasks.yml } - { resource: cron_tasks.yml }
- { resource: migrator.yml }
services: services:
auth: auth:
@ -10,6 +11,10 @@ services:
class: phpbb_cache_service class: phpbb_cache_service
arguments: arguments:
- @cache.driver - @cache.driver
- @config
- @dbal.conn
- %core.root_path%
- %core.php_ext%
cache.driver: cache.driver:
class: %cache.driver.class% class: %cache.driver.class%
@ -59,15 +64,6 @@ services:
- @service_container - @service_container
- @ext.finder - @ext.finder
controller.route_collection:
class: phpbb_controller_route_collection
arguments:
- @ext.finder
- @controller.provider
controller.provider:
class: phpbb_controller_provider
cron.task_collection: cron.task_collection:
class: phpbb_di_service_collection class: phpbb_di_service_collection
arguments: arguments:
@ -99,6 +95,12 @@ services:
calls: calls:
- [sql_connect, [%dbal.dbhost%, %dbal.dbuser%, %dbal.dbpasswd%, %dbal.dbname%, %dbal.dbport%, false, %dbal.new_link%]] - [sql_connect, [%dbal.dbhost%, %dbal.dbuser%, %dbal.dbpasswd%, %dbal.dbname%, %dbal.dbport%, false, %dbal.new_link%]]
dbal.tools:
file: %core.root_path%includes/db/db_tools.%core.php_ext%
class: phpbb_db_tools
arguments:
- @dbal.conn
event.subscriber_loader: event.subscriber_loader:
class: phpbb_event_extension_subscriber_loader class: phpbb_event_extension_subscriber_loader
arguments: arguments:
@ -110,8 +112,10 @@ services:
ext.manager: ext.manager:
class: phpbb_extension_manager class: phpbb_extension_manager
arguments: arguments:
- @service_container
- @dbal.conn - @dbal.conn
- @config - @config
- @migrator
- %tables.ext% - %tables.ext%
- %core.root_path% - %core.root_path%
- .%core.php_ext% - .%core.php_ext%
@ -126,13 +130,6 @@ services:
- .%core.php_ext% - .%core.php_ext%
- _ext_finder - _ext_finder
http_kernel:
class: Symfony\Component\HttpKernel\HttpKernel
arguments:
- @dispatcher
- @controller.resolver
groupposition.legend: groupposition.legend:
class: phpbb_groupposition_legend class: phpbb_groupposition_legend
arguments: arguments:
@ -146,6 +143,19 @@ services:
- @user - @user
- @cache.driver - @cache.driver
http_kernel:
class: Symfony\Component\HttpKernel\HttpKernel
arguments:
- @dispatcher
- @controller.resolver
hook_finder:
class: phpbb_hook_finder
arguments:
- %core.root_path%
- .%core.php_ext%
- @cache.driver
kernel_request_subscriber: kernel_request_subscriber:
class: phpbb_event_kernel_request_subscriber class: phpbb_event_kernel_request_subscriber
arguments: arguments:
@ -203,6 +213,7 @@ services:
- @user - @user
- @style.resource_locator - @style.resource_locator
- @template_context - @template_context
- @ext.manager
template_context: template_context:
class: phpbb_template_context class: phpbb_template_context

View file

@ -1,3 +1,5 @@
parameters: parameters:
tables.config: %core.table_prefix%config tables.config: %core.table_prefix%config
tables.ext: %core.table_prefix%ext tables.ext: %core.table_prefix%ext
tables.migrations: %core.table_prefix%migrations
tables.modules: %core.table_prefix%modules

View file

@ -1272,6 +1272,19 @@ function get_schema_struct()
), ),
); );
$schema_data['phpbb_migrations'] = array(
'COLUMNS' => array(
'migration_name' => array('VCHAR', ''),
'migration_depends_on' => array('TEXT', ''),
'migration_schema_done' => array('BOOL', 0),
'migration_data_done' => array('BOOL', 0),
'migration_data_state' => array('TEXT', ''),
'migration_start_time' => array('TIMESTAMP', 0),
'migration_end_time' => array('TIMESTAMP', 0),
),
'PRIMARY_KEY' => 'migration_name',
);
$schema_data['phpbb_modules'] = array( $schema_data['phpbb_modules'] = array(
'COLUMNS' => array( 'COLUMNS' => array(
'module_id' => array('UINT', NULL, 'auto_increment'), 'module_id' => array('UINT', NULL, 'auto_increment'),
@ -1519,18 +1532,21 @@ function get_schema_struct()
$schema_data['phpbb_reports'] = array( $schema_data['phpbb_reports'] = array(
'COLUMNS' => array( 'COLUMNS' => array(
'report_id' => array('UINT', NULL, 'auto_increment'), 'report_id' => array('UINT', NULL, 'auto_increment'),
'reason_id' => array('USINT', 0), 'reason_id' => array('USINT', 0),
'post_id' => array('UINT', 0), 'post_id' => array('UINT', 0),
'pm_id' => array('UINT', 0), 'pm_id' => array('UINT', 0),
'user_id' => array('UINT', 0), 'user_id' => array('UINT', 0),
'user_notify' => array('BOOL', 0), 'user_notify' => array('BOOL', 0),
'report_closed' => array('BOOL', 0), 'report_closed' => array('BOOL', 0),
'report_time' => array('TIMESTAMP', 0), 'report_time' => array('TIMESTAMP', 0),
'report_text' => array('MTEXT_UNI', ''), 'report_text' => array('MTEXT_UNI', ''),
'reported_post_text' => array('MTEXT_UNI', ''), 'reported_post_text' => array('MTEXT_UNI', ''),
'reported_post_uid' => array('VCHAR:8', ''), 'reported_post_uid' => array('VCHAR:8', ''),
'reported_post_bitfield' => array('VCHAR:255', ''), 'reported_post_bitfield' => array('VCHAR:255', ''),
'reported_post_enable_magic_url' => array('BOOL', 1),
'reported_post_enable_smilies' => array('BOOL', 1),
'reported_post_enable_bbcode' => array('BOOL', 1)
), ),
'PRIMARY_KEY' => 'report_id', 'PRIMARY_KEY' => 'report_id',
'KEYS' => array( 'KEYS' => array(

View file

@ -23,11 +23,11 @@ involved in phpBB.
phpBB Lead Developer: naderman (Nils Adermann) phpBB Lead Developer: naderman (Nils Adermann)
phpBB Developers: bantu (Andreas Fischer) phpBB Developers: bantu (Andreas Fischer)
EXreaction (Nathan Guse)
igorw (Igor Wiedler) igorw (Igor Wiedler)
imkingdavid (David King) imkingdavid (David King)
nickvergessen (Joas Schilling) nickvergessen (Joas Schilling)
Oleg (Oleg Pudeyev) Oleg (Oleg Pudeyev)
rxu (Ruslan Uzdenov)
Contributions by: leviatan21 (Gabriel Vazquez) Contributions by: leviatan21 (Gabriel Vazquez)
Raimon (Raimon Meuldijk) Raimon (Raimon Meuldijk)
@ -53,6 +53,7 @@ phpBB Developers: A_Jelly_Doughnut (Josh Woody) [01/2010 - 11/2010]
dhn (Dominik Dröscher) [05/2007 - 01/2011] dhn (Dominik Dröscher) [05/2007 - 01/2011]
GrahamJE (Graham Eames) [09/2005 - 11/2006] GrahamJE (Graham Eames) [09/2005 - 11/2006]
kellanved (Henry Sudhof) [04/2007 - 03/2011] kellanved (Henry Sudhof) [04/2007 - 03/2011]
rxu (Ruslan Uzdenov) [04/2010 - 12/2012]
TerraFrost (Jim Wigginton) [04/2009 - 01/2011] TerraFrost (Jim Wigginton) [04/2009 - 01/2011]
ToonArmy (Chris Smith) [06/2008 - 11/2011] ToonArmy (Chris Smith) [06/2008 - 11/2011]
Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009] Vic D'Elfant (Vic D'Elfant) [04/2007 - 04/2009]

View file

@ -72,6 +72,7 @@
<ol style="list-style-type: lower-roman;"> <ol style="list-style-type: lower-roman;">
<li><a href="#templates">General Templating</a></li> <li><a href="#templates">General Templating</a></li>
<li><a href="#stylestree">Styles Tree</a></li> <li><a href="#stylestree">Styles Tree</a></li>
<li><a href="#template-events">Template Events</a></li>
</ol></li> </ol></li>
<li><a href="#charsets">Character Sets and Encodings</a></li> <li><a href="#charsets">Character Sets and Encodings</a></li>
<li><a href="#translation">Translation (<abbr title="Internationalisation">i18n</abbr>/<abbr title="Localisation">L10n</abbr>) Guidelines</a> <li><a href="#translation">Translation (<abbr title="Internationalisation">i18n</abbr>/<abbr title="Localisation">L10n</abbr>) Guidelines</a>
@ -1678,6 +1679,57 @@ version = 3.1.0
parent = prosilver parent = prosilver
</pre></div> </pre></div>
<a name="template-events"></a><h3>4.iii. Template Events</h3>
<p>Template events must follow this format: <code>&lt;!-- EVENT event_name --&gt;</code></p>
<p>Using the above example, files named <code>event_name.html</code> located within extensions will be injected into the location of the event.</p>
<h4>Template event naming guidelines:</h4>
<ul>
<li>An event name must be all lowercase, with each word separated by an underscore.</li>
<li>An event name must briefly describe the location and purpose of the event.</li>
<li>An event name must end with one of the following suffixes:</li>
<ul>
<li><code>_prepend</code> - This event adds an item to the beginning of a block of related items, or adds to the beginning of individual items in a block.</li>
<li><code>_append</code> - This event adds an item to the end of a block of related items, or adds to the end of individual items in a block.</li>
<li><code>_before</code> - This event adds content directly before the specified block</li>
<li><code>_after</code> - This event adds content directly after the specified block</li>
</ul>
</ul>
<h4>Template event documentation</h4>
<p>Events must be documented in <code>phpBB/docs/events.md</code> in alphabetical order based on the event name. The format is as follows:</p>
<ul><li>An event found in only one template file:
<div class="codebox"><pre>event_name
===
* Location: styles/&lt;style_name&gt;/template/filename.html
* Purpose: A brief description of what this event should be used for.
This may span multiple lines.
</pre></div></li>
<li>An event found in multiple template files:
<div class="codebox"><pre>event_name
===
* Locations:
+ first/file/path.html
+ second/file/path.html
* Purpose: Same as above.
</pre></div>
<li>An event that is found multiple times in a file should have the number of instances in parenthesis next to the filename.
<div class="codebox"><pre>event_name
===
* Locations:
+ first/file/path.html (2)
+ second/file/path.html
* Purpose: Same as above.
</pre></div></li>
<li>An actual example event documentation:
<div class="codebox"><pre>forumlist_body_last_post_title_prepend
====
* Locations:
+ styles/prosilver/template/forumlist_body.html
+ styles/subsilver2/template/forumlist_body.html
* Purpose: Add content before the post title of the latest post in a forum on the forum list.</pre></div></ul><br />
</div> </div>
<div class="back2top"><a href="#wrap" class="top">Back to Top</a></div> <div class="back2top"><a href="#wrap" class="top">Back to Top</a></div>

132
phpBB/docs/events.md Normal file
View file

@ -0,0 +1,132 @@
acp_forums_normal_settings_append
===
* Location: adm/style/acp_forums.html
* Purpose: Add settings to forums
acp_main_actions_append
===
* Location: adm/style/acp_main.html
* Purpose: Add actions to the ACP main page below the cache purge action
acp_main_notice_after
===
* Location: adm/style/acp_main.html
* Purpose: Add notices or other blocks in the ACP below other configuration notices
acp_overall_footer_after
===
* Location: adm/style/overall_footer.html
* Purpose: Add content below the footer in the ACP
acp_overall_header_head_append
===
* Location: adm/style/overall_header.html
* Add assets within the `<head>` tags in the ACP
acp_simple_footer_after
===
* Location: adm/style/simple_footer.html
* Purpose: Add content below the simple footer in the ACP
acp_simple_header_head_append
===
* Location: adm/style/overall_header.html
* Add assets within the `<head>` tags in the simple header of the ACP
acp_users_overview_options_append
===
* Location: adm/style/acp_users.html
* Purpose: Add options and settings on user overview page
forumlist_body_last_post_title_prepend
====
* Locations:
+ styles/prosilver/template/forumlist_body.html
+ styles/subsilver2/template/forumlist_body.html
* Purpose: Add content before the post title of the latest post in a forum on the forum list.
index_body_stat_blocks_before
===
* Locations:
+ styles/prosilver/template/index_body.html
+ styles/subsilver2/template/index_body.html
* Purpose: Add new statistic blocks above the Who Is Online and Board Statistics blocks
overall_footer_after
===
* Locations:
+ styles/prosilver/template/overall_footer.html
+ styles/subsilver2/template/overall_footer.html
* Purpose: Add content at the end of the file, directly prior to the `</body>` tag
overall_footer_breadcrumb_append
===
* Location: styles/prosilver/template/overall_footer.html
* Purpose: Add links to the list of breadcrumbs in the footer
overall_footer_copyright_append
===
* Locations:
+ styles/prosilver/template/overall_footer.html
+ styles/subsilver2/template/overall_footer.html
* Purpose: Add content after the copyright line (no new line by default), before the ACP link
overall_footer_copyright_prepend
===
* Locations:
+ styles/prosilver/template/overall_footer.html
+ styles/subsilver2/template/overall_footer.html
* Purpose: Add content before the copyright line
overall_header_breadcrumb_append
===
* Locations:
+ styles/prosilver/template/overall_header.html
+ styles/subsilver2/template/breadcrumbs.html
* Purpose: Add links to the list of breadcrumbs in the header
overall_header_head_append
===
* Locations:
+ styles/prosilver/template/overall_header.html
+ styles/subsilver2/template/overall_header.html
* Purpose: Add asset calls directly before the `</head>` tag
overall_header_navigation_append
===
* Location: styles/prosilver/template/overall_header.html
* Purpose: Add links after the navigation links in the header
overall_header_navigation_prepend
===
* Location: styles/prosilver/template/overall_header.html
* Purpose: Add links before the navigation links in the header
posting_editor_options_prepend
===
* Locations:
+ styles/prosilver/template/posting_editor.html
+ styles/prosilver/template/posting_body.html
* Purpose: Add posting options on the posting screen
simple_footer_after
===
* Location: styles/prosilver/template/simple_footer.html
* Purpose: Add content directly prior to the `</body>` tag of the simple footer
ucp_pm_viewmessage_print_head_append
===
* Location: styles/prosilver/template/ucp_pm_viewmessage_print.html
* Purpose: Add asset calls directly before the `</head>` tag of the Print PM screen
viewtopic_print_head_append
===
* Location: styles/prosilver/template/viewtopic_print.html
* Purpose: Add asset calls directly before the `</head>` tag of the Print Topic screen
viewtopic_topic_title_prepend
===
* Locations:
+ styles/prosilver/template/viewtopic_body.html
+ styles/subsilver2/template/viewtopic_body.html
* Purpose: Add content directly before the topic title link on the View topic screen

View file

@ -10,21 +10,36 @@ source source_phpbb_{SPHINX_ID}_main
sql_query_pre = UPDATE phpbb_sphinx SET max_doc_id = MAX(post_id) WHERE counter_id = 1 sql_query_pre = UPDATE phpbb_sphinx SET max_doc_id = MAX(post_id) WHERE counter_id = 1
sql_query_range = SELECT MIN(post_id), MAX(post_id) FROM phpbb_posts sql_query_range = SELECT MIN(post_id), MAX(post_id) FROM phpbb_posts
sql_range_step = 5000 sql_range_step = 5000
sql_query = SELECT \ sql_query = SELECT
p.post_id AS id, \ \
p.forum_id, \ p.post_id AS id,
p.topic_id, \ \
p.poster_id, \ p.forum_id,
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \ \
p.post_time, \ p.topic_id,
p.post_subject, \ \
p.post_subject as title, \ p.poster_id,
p.post_text as data, \ \
t.topic_last_post_time, \ CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
0 as deleted \ \
FROM phpbb_posts p, phpbb_topics t \ p.post_time,
WHERE \ \
p.topic_id = t.topic_id \ p.post_subject,
\
p.post_subject as title,
\
p.post_text as data,
\
t.topic_last_post_time,
\
0 as deleted
\
FROM phpbb_posts p, phpbb_topics t
\
WHERE
\
p.topic_id = t.topic_id
\
AND p.post_id >= $start AND p.post_id <= $end AND p.post_id >= $start AND p.post_id <= $end
sql_query_post = sql_query_post =
sql_query_post_index = UPDATE phpbb_sphinx SET max_doc_id = $maxid WHERE counter_id = 1 sql_query_post_index = UPDATE phpbb_sphinx SET max_doc_id = $maxid WHERE counter_id = 1
@ -42,21 +57,36 @@ source source_phpbb_{SPHINX_ID}_delta : source_phpbb_{SPHINX_ID}_main
{ {
sql_query_range = sql_query_range =
sql_range_step = sql_range_step =
sql_query = SELECT \ sql_query = SELECT
p.post_id AS id, \ \
p.forum_id, \ p.post_id AS id,
p.topic_id, \ \
p.poster_id, \ p.forum_id,
CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post, \ \
p.post_time, \ p.topic_id,
p.post_subject, \ \
p.post_subject as title, \ p.poster_id,
p.post_text as data, \ \
t.topic_last_post_time, \ CASE WHEN p.post_id = t.topic_first_post_id THEN 1 ELSE 0 END as topic_first_post,
0 as deleted \ \
FROM phpbb_posts p, phpbb_topics t \ p.post_time,
WHERE \ \
p.topic_id = t.topic_id \ p.post_subject,
\
p.post_subject as title,
\
p.post_text as data,
\
t.topic_last_post_time,
\
0 as deleted
\
FROM phpbb_posts p, phpbb_topics t
\
WHERE
\
p.topic_id = t.topic_id
\
AND p.post_id >= ( SELECT max_doc_id FROM phpbb_sphinx WHERE counter_id=1 ) AND p.post_id >= ( SELECT max_doc_id FROM phpbb_sphinx WHERE counter_id=1 )
sql_query_pre = sql_query_pre =
} }

View file

@ -43,7 +43,6 @@ if (isset($_GET['avatar']))
require($phpbb_root_path . 'includes/class_loader.' . $phpEx); require($phpbb_root_path . 'includes/class_loader.' . $phpEx);
require($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
require($phpbb_root_path . 'includes/constants.' . $phpEx); require($phpbb_root_path . 'includes/constants.' . $phpEx);
require($phpbb_root_path . 'includes/functions.' . $phpEx); require($phpbb_root_path . 'includes/functions.' . $phpEx);
require($phpbb_root_path . 'includes/functions_container.' . $phpEx); require($phpbb_root_path . 'includes/functions_container.' . $phpEx);
@ -57,18 +56,7 @@ if (isset($_GET['avatar']))
$phpbb_class_loader_ext->register(); $phpbb_class_loader_ext->register();
// Set up container // Set up container
$phpbb_container = phpbb_create_dumped_container_unless_debug( $phpbb_container = phpbb_create_default_container($phpbb_root_path, $phpEx);
array(
new phpbb_di_extension_config($phpbb_root_path . 'config.' . $phpEx),
new phpbb_di_extension_core($phpbb_root_path),
),
array(
new phpbb_di_pass_collection_pass(),
new phpbb_di_pass_kernel_pass(),
),
$phpbb_root_path,
$phpEx
);
$phpbb_class_loader->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader->set_cache($phpbb_container->get('cache.driver'));
$phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver')); $phpbb_class_loader_ext->set_cache($phpbb_container->get('cache.driver'));

View file

@ -413,8 +413,8 @@ class acp_board
'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true),
'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true),
'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true),
'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'email', 'type' => 'text:25:100', 'explain' => true),
'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true),
'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true),

View file

@ -37,7 +37,7 @@ class acp_extensions
$this->template = $template; $this->template = $template;
$this->user = $user; $this->user = $user;
$user->add_lang(array('install', 'acp/extensions')); $user->add_lang(array('install', 'acp/extensions', 'migrator'));
$this->page_title = 'ACP_EXTENSIONS'; $this->page_title = 'ACP_EXTENSIONS';
@ -103,11 +103,18 @@ class acp_extensions
trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action)); trigger_error($user->lang['EXTENSION_NOT_AVAILABLE'] . adm_back_link($this->u_action));
} }
if ($phpbb_extension_manager->enable_step($ext_name)) try
{ {
$template->assign_var('S_NEXT_STEP', true); if ($phpbb_extension_manager->enable_step($ext_name))
{
$template->assign_var('S_NEXT_STEP', true);
meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name)); meta_refresh(0, $this->u_action . '&amp;action=enable&amp;ext_name=' . urlencode($ext_name));
}
}
catch (phpbb_db_migration_exception $e)
{
$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user));
} }
$this->tpl_name = 'acp_ext_enable'; $this->tpl_name = 'acp_ext_enable';
@ -156,11 +163,18 @@ class acp_extensions
break; break;
case 'purge': case 'purge':
if ($phpbb_extension_manager->purge_step($ext_name)) try
{ {
$template->assign_var('S_NEXT_STEP', true); if ($phpbb_extension_manager->purge_step($ext_name))
{
$template->assign_var('S_NEXT_STEP', true);
meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name)); meta_refresh(0, $this->u_action . '&amp;action=purge&amp;ext_name=' . urlencode($ext_name));
}
}
catch (phpbb_db_migration_exception $e)
{
$template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($user));
} }
$this->tpl_name = 'acp_ext_purge'; $this->tpl_name = 'acp_ext_purge';

View file

@ -206,7 +206,7 @@ class acp_forums
($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))))
{ {
copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false); copy_forum_permissions($forum_perm_from, $forum_data['forum_id'], ($action == 'edit') ? true : false);
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
$copied_permissions = true; $copied_permissions = true;
} }
/* Commented out because of questionable UI workflow - re-visit for 3.0.7 /* Commented out because of questionable UI workflow - re-visit for 3.0.7
@ -266,7 +266,7 @@ class acp_forums
add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name);
$cache->destroy('sql', FORUMS_TABLE); $cache->destroy('sql', FORUMS_TABLE);
} }
if ($request->is_ajax()) if ($request->is_ajax())
{ {
$json_response = new phpbb_json_response; $json_response = new phpbb_json_response;
@ -768,7 +768,7 @@ class acp_forums
if (!empty($forum_perm_from) && $forum_perm_from != $forum_id) if (!empty($forum_perm_from) && $forum_perm_from != $forum_id)
{ {
copy_forum_permissions($forum_perm_from, $forum_id, true); copy_forum_permissions($forum_perm_from, $forum_id, true);
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
$auth->acl_clear_prefetch(); $auth->acl_clear_prefetch();
$cache->destroy('sql', FORUMS_TABLE); $cache->destroy('sql', FORUMS_TABLE);

View file

@ -128,13 +128,34 @@ class acp_groups
{ {
trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING);
} }
else if (empty($mark_ary))
{
trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
if (confirm_box(true)) if (confirm_box(true))
{ {
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
if (!sizeof($mark_ary)) break;
case 'set_default_on_all':
if (confirm_box(true))
{ {
$group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'];
$start = 0; $start = 0;
do do
@ -165,28 +186,25 @@ class acp_groups
$db->sql_freeresult($result); $db->sql_freeresult($result);
} }
while ($start); while ($start);
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
} }
else else
{ {
group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
} }
trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id));
}
else
{
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
'mark' => $mark_ary,
'g' => $group_id,
'i' => $id,
'mode' => $mode,
'action' => $action))
);
}
break; break;
case 'deleteusers': case 'deleteusers':
if (empty($mark_ary))
{
trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&amp;action=list&amp;g=' . $group_id), E_USER_WARNING);
}
case 'delete': case 'delete':
if (!$group_id) if (!$group_id)
{ {
@ -441,7 +459,7 @@ class acp_groups
foreach ($test_variables as $test => $type) foreach ($test_variables as $test => $type)
{ {
if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || in_array($test, $set_attributes))) if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test] || isset($group_attributes['group_avatar']) && strpos($test, 'avatar') === 0 || in_array($test, $set_attributes)))
{ {
settype($submit_ary[$test], $type); settype($submit_ary[$test], $type);
$group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test];
@ -700,7 +718,7 @@ class acp_groups
'U_ACTION' => $this->u_action . "&amp;g=$group_id", 'U_ACTION' => $this->u_action . "&amp;g=$group_id",
'U_BACK' => $this->u_action, 'U_BACK' => $this->u_action,
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'), 'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&amp;form=list&amp;field=usernames'),
'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=default&amp;g=$group_id", 'U_DEFAULT_ALL' => "{$this->u_action}&amp;action=set_default_on_all&amp;g=$group_id",
)); ));
// Grab the members // Grab the members

View file

@ -24,7 +24,7 @@ class acp_main
function main($id, $mode) function main($id, $mode)
{ {
global $config, $db, $user, $auth, $template, $request; global $config, $db, $cache, $user, $auth, $template, $request;
global $phpbb_root_path, $phpbb_admin_path, $phpEx; global $phpbb_root_path, $phpbb_admin_path, $phpEx;
// Show restore permissions notice // Show restore permissions notice
@ -129,7 +129,7 @@ class acp_main
set_config('record_online_users', 1, true); set_config('record_online_users', 1, true);
set_config('record_online_date', time(), true); set_config('record_online_date', time(), true);
add_log('admin', 'LOG_RESET_ONLINE'); add_log('admin', 'LOG_RESET_ONLINE');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('RESET_ONLINE_SUCCESS'); trigger_error('RESET_ONLINE_SUCCESS');
@ -184,7 +184,7 @@ class acp_main
update_last_username(); update_last_username();
add_log('admin', 'LOG_RESYNC_STATS'); add_log('admin', 'LOG_RESYNC_STATS');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('RESYNC_STATS_SUCCESS'); trigger_error('RESYNC_STATS_SUCCESS');
@ -251,7 +251,7 @@ class acp_main
} }
add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('RESYNC_POSTCOUNTS_SUCCESS'); trigger_error('RESYNC_POSTCOUNTS_SUCCESS');
@ -266,7 +266,7 @@ class acp_main
set_config('board_startdate', time() - 1); set_config('board_startdate', time() - 1);
add_log('admin', 'LOG_RESET_DATE'); add_log('admin', 'LOG_RESET_DATE');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('RESET_DATE_SUCCESS'); trigger_error('RESET_DATE_SUCCESS');
@ -346,7 +346,7 @@ class acp_main
} }
add_log('admin', 'LOG_RESYNC_POST_MARKING'); add_log('admin', 'LOG_RESYNC_POST_MARKING');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('RESYNC_POST_MARKING_SUCCESS'); trigger_error('RESYNC_POST_MARKING_SUCCESS');
@ -359,10 +359,10 @@ class acp_main
// Clear permissions // Clear permissions
$auth->acl_clear_prefetch(); $auth->acl_clear_prefetch();
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
add_log('admin', 'LOG_PURGE_CACHE'); add_log('admin', 'LOG_PURGE_CACHE');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('PURGE_CACHE_SUCCESS'); trigger_error('PURGE_CACHE_SUCCESS');
@ -413,7 +413,7 @@ class acp_main
$db->sql_query($sql); $db->sql_query($sql);
add_log('admin', 'LOG_PURGE_SESSIONS'); add_log('admin', 'LOG_PURGE_SESSIONS');
if ($request->is_ajax()) if ($request->is_ajax())
{ {
trigger_error('PURGE_SESSIONS_SUCCESS'); trigger_error('PURGE_SESSIONS_SUCCESS');

View file

@ -740,15 +740,15 @@ class acp_modules
*/ */
function remove_cache_file() function remove_cache_file()
{ {
global $cache; global $phpbb_container;
// Sanitise for future path use, it's escaped as appropriate for queries // Sanitise for future path use, it's escaped as appropriate for queries
$p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class));
$cache->destroy('_modules_' . $p_class); $phpbb_container->get('cache.driver')->destroy('_modules_' . $p_class);
// Additionally remove sql cache // Additionally remove sql cache
$cache->destroy('sql', MODULES_TABLE); $phpbb_container->get('cache.driver')->destroy('sql', MODULES_TABLE);
} }
/** /**

View file

@ -656,7 +656,7 @@ class acp_permissions
*/ */
function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id)
{ {
global $user, $auth; global $db, $cache, $user, $auth;
global $request; global $request;
$psubmit = request_var('psubmit', array(0 => array(0 => 0))); $psubmit = request_var('psubmit', array(0 => array(0 => 0)));
@ -726,13 +726,13 @@ class acp_permissions
// Do we need to recache the moderator lists? // Do we need to recache the moderator lists?
if ($permission_type == 'm_') if ($permission_type == 'm_')
{ {
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
} }
// Remove users who are now moderators or admins from everyones foes list // Remove users who are now moderators or admins from everyones foes list
if ($permission_type == 'm_' || $permission_type == 'a_') if ($permission_type == 'm_' || $permission_type == 'a_')
{ {
update_foes($group_id, $user_id); phpbb_update_foes($db, $auth, $group_id, $user_id);
} }
$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id);
@ -745,7 +745,7 @@ class acp_permissions
*/ */
function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id)
{ {
global $user, $auth; global $db, $cache, $user, $auth;
global $request; global $request;
// User or group to be set? // User or group to be set?
@ -794,13 +794,13 @@ class acp_permissions
// Do we need to recache the moderator lists? // Do we need to recache the moderator lists?
if ($permission_type == 'm_') if ($permission_type == 'm_')
{ {
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
} }
// Remove users who are now moderators or admins from everyones foes list // Remove users who are now moderators or admins from everyones foes list
if ($permission_type == 'm_' || $permission_type == 'a_') if ($permission_type == 'm_' || $permission_type == 'a_')
{ {
update_foes($group_id, $user_id); phpbb_update_foes($db, $auth, $group_id, $user_id);
} }
$this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids);
@ -858,7 +858,7 @@ class acp_permissions
*/ */
function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id)
{ {
global $user, $db, $auth; global $user, $db, $cache, $auth;
// User or group to be set? // User or group to be set?
$ug_type = (sizeof($user_id)) ? 'user' : 'group'; $ug_type = (sizeof($user_id)) ? 'user' : 'group';
@ -874,7 +874,7 @@ class acp_permissions
// Do we need to recache the moderator lists? // Do we need to recache the moderator lists?
if ($permission_type == 'm_') if ($permission_type == 'm_')
{ {
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
} }
$this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0)));
@ -952,12 +952,7 @@ class acp_permissions
if ($user_id != $user->data['user_id']) if ($user_id != $user->data['user_id'])
{ {
$sql = 'SELECT user_id, username, user_permissions, user_type $userdata = $auth->obtain_user_data($user_id);
FROM ' . USERS_TABLE . '
WHERE user_id = ' . $user_id;
$result = $db->sql_query($sql);
$userdata = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
} }
else else
{ {
@ -1172,7 +1167,7 @@ class acp_permissions
*/ */
function copy_forum_permissions() function copy_forum_permissions()
{ {
global $auth, $cache, $template, $user; global $db, $auth, $cache, $template, $user;
$user->add_lang('acp/forums'); $user->add_lang('acp/forums');
@ -1187,7 +1182,7 @@ class acp_permissions
{ {
if (copy_forum_permissions($src, $dest)) if (copy_forum_permissions($src, $dest))
{ {
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
$auth->acl_clear_prefetch(); $auth->acl_clear_prefetch();
$cache->destroy('sql', FORUMS_TABLE); $cache->destroy('sql', FORUMS_TABLE);

View file

@ -71,7 +71,7 @@ class acp_ranks
'rank_min' => $min_posts, 'rank_min' => $min_posts,
'rank_image' => htmlspecialchars_decode($rank_image) 'rank_image' => htmlspecialchars_decode($rank_image)
); );
if ($rank_id) if ($rank_id)
{ {
$sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id";
@ -122,7 +122,7 @@ class acp_ranks
$cache->destroy('_ranks'); $cache->destroy('_ranks');
add_log('admin', 'LOG_RANK_REMOVED', $rank_title); add_log('admin', 'LOG_RANK_REMOVED', $rank_title);
if ($request->is_ajax()) if ($request->is_ajax())
{ {
$json_response = new phpbb_json_response; $json_response = new phpbb_json_response;
@ -151,7 +151,7 @@ class acp_ranks
case 'add': case 'add':
$data = $ranks = $existing_imgs = array(); $data = $ranks = $existing_imgs = array();
$sql = 'SELECT * $sql = 'SELECT *
FROM ' . RANKS_TABLE . ' FROM ' . RANKS_TABLE . '
ORDER BY rank_min ASC, rank_special ASC'; ORDER BY rank_min ASC, rank_special ASC';
@ -209,17 +209,17 @@ class acp_ranks
'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '', 'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '',
'S_FILENAME_LIST' => $filename_list, 'S_FILENAME_LIST' => $filename_list,
'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : $phpbb_admin_path . 'images/spacer.gif', 'RANK_IMAGE' => ($edit_img) ? $phpbb_root_path . $config['ranks_path'] . '/' . $edit_img : htmlspecialchars($phpbb_admin_path) . 'images/spacer.gif',
'S_SPECIAL_RANK' => (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false, 'S_SPECIAL_RANK' => (isset($ranks['rank_special']) && $ranks['rank_special']) ? true : false,
'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0)
); );
return; return;
break; break;
} }
$template->assign_vars(array( $template->assign_vars(array(
'U_ACTION' => $this->u_action) 'U_ACTION' => $this->u_action)
); );
@ -241,7 +241,7 @@ class acp_ranks
'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row['rank_id'], 'U_EDIT' => $this->u_action . '&amp;action=edit&amp;id=' . $row['rank_id'],
'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row['rank_id']) 'U_DELETE' => $this->u_action . '&amp;action=delete&amp;id=' . $row['rank_id'])
); );
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);

View file

@ -137,11 +137,13 @@ class acp_styles
*/ */
protected function action_cache() protected function action_cache()
{ {
global $db, $cache, $auth;
$this->cache->purge(); $this->cache->purge();
// Clear permissions // Clear permissions
$this->auth->acl_clear_prefetch(); $this->auth->acl_clear_prefetch();
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
add_log('admin', 'LOG_PURGE_CACHE'); add_log('admin', 'LOG_PURGE_CACHE');

View file

@ -16,10 +16,10 @@ class acp_extensions_info
{ {
return array( return array(
'filename' => 'acp_extensions', 'filename' => 'acp_extensions',
'title' => 'ACP_EXTENSIONS', 'title' => 'ACP_EXTENSION_MANAGEMENT',
'version' => '1.0.0', 'version' => '1.0.0',
'modes' => array( 'modes' => array(
'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_GENERAL_TASKS')), 'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')),
), ),
); );
} }

View file

@ -19,7 +19,7 @@ class acp_language_info
'title' => 'ACP_LANGUAGE', 'title' => 'ACP_LANGUAGE',
'version' => '1.0.0', 'version' => '1.0.0',
'modes' => array( 'modes' => array(
'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_GENERAL_TASKS')), 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')),
), ),
); );
} }

View file

@ -102,6 +102,26 @@ class phpbb_auth
return; return;
} }
/**
* Retrieves data wanted by acl function from the database for the
* specified user.
*
* @param int $user_id User ID
* @return array User attributes
*/
public function obtain_user_data($user_id)
{
global $db;
$sql = 'SELECT user_id, username, user_permissions, user_type
FROM ' . USERS_TABLE . '
WHERE user_id = ' . $user_id;
$result = $db->sql_query($sql);
$user_data = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
return $user_data;
}
/** /**
* Fill ACL array with relevant bitstrings from user_permissions column * Fill ACL array with relevant bitstrings from user_permissions column
* @access private * @access private
@ -191,7 +211,7 @@ class phpbb_auth
/** /**
* Get forums with the specified permission setting * Get forums with the specified permission setting
* if the option is prefixed with !, then the result becomes nagated * if the option is prefixed with !, then the result becomes negated
* *
* @param bool $clean set to true if only values needs to be returned which are set/unset * @param bool $clean set to true if only values needs to be returned which are set/unset
*/ */

View file

@ -134,7 +134,7 @@ class bbcode
$style_resource_locator = new phpbb_style_resource_locator(); $style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
$template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context()); $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
$style->set_style(); $style->set_style();
$template->set_filenames(array('bbcode.html' => 'bbcode.html')); $template->set_filenames(array('bbcode.html' => 'bbcode.html'));

View file

@ -367,12 +367,10 @@ class phpbb_cache_driver_file extends phpbb_cache_driver_base
} }
/** /**
* Save sql query * {@inheritDoc}
*/ */
function sql_save($query, $query_result, $ttl) function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl)
{ {
global $db;
// Remove extra spaces and tabs // Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query); $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);

View file

@ -85,6 +85,7 @@ interface phpbb_cache_driver_interface
* result to persistent storage. In other words, there is no need * result to persistent storage. In other words, there is no need
* to call save() afterwards. * to call save() afterwards.
* *
* @param phpbb_db_driver $db Database connection
* @param string $query SQL query, should be used for generating storage key * @param string $query SQL query, should be used for generating storage key
* @param mixed $query_result The result from dbal::sql_query, to be passed to * @param mixed $query_result The result from dbal::sql_query, to be passed to
* dbal::sql_fetchrow to get all rows and store them * dbal::sql_fetchrow to get all rows and store them
@ -95,7 +96,7 @@ interface phpbb_cache_driver_interface
* representing the query should be returned. Otherwise * representing the query should be returned. Otherwise
* the original $query_result should be returned. * the original $query_result should be returned.
*/ */
public function sql_save($query, $query_result, $ttl); public function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl);
/** /**
* Check if result for a given SQL query exists in cache. * Check if result for a given SQL query exists in cache.

View file

@ -283,12 +283,10 @@ abstract class phpbb_cache_driver_memory extends phpbb_cache_driver_base
} }
/** /**
* Save sql query * {@inheritDoc}
*/ */
function sql_save($query, $query_result, $ttl) function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl)
{ {
global $db;
// Remove extra spaces and tabs // Remove extra spaces and tabs
$query = preg_replace('/[\n\r\s\t]+/', ' ', $query); $query = preg_replace('/[\n\r\s\t]+/', ' ', $query);
$hash = md5($query); $hash = md5($query);

View file

@ -105,9 +105,9 @@ class phpbb_cache_driver_null extends phpbb_cache_driver_base
} }
/** /**
* Save sql query * {@inheritDoc}
*/ */
function sql_save($query, $query_result, $ttl) function sql_save(phpbb_db_driver $db, $query, $query_result, $ttl)
{ {
return $query_result; return $query_result;
} }

View file

@ -21,16 +21,57 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_cache_service class phpbb_cache_service
{ {
private $driver; /**
* Cache driver.
*
* @var phpbb_cache_driver_interface
*/
protected $driver;
/**
* The config.
*
* @var phpbb_config
*/
protected $config;
/**
* Database connection.
*
* @var phpbb_db_driver
*/
protected $db;
/**
* Root path.
*
* @var string
*/
protected $phpbb_root_path;
/**
* PHP extension.
*
* @var string
*/
protected $php_ext;
/** /**
* Creates a cache service around a cache driver * Creates a cache service around a cache driver
* *
* @param phpbb_cache_driver_interface $driver The cache driver * @param phpbb_cache_driver_interface $driver The cache driver
* @param phpbb_config $config The config
* @param phpbb_db_driver $db Database connection
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP extension
*/ */
public function __construct(phpbb_cache_driver_interface $driver = null) public function __construct(phpbb_cache_driver_interface $driver, phpbb_config $config, phpbb_db_driver $db, $phpbb_root_path, $php_ext)
{ {
$this->set_driver($driver); $this->set_driver($driver);
$this->config = $config;
$this->db = $db;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
} }
/** /**
@ -64,21 +105,19 @@ class phpbb_cache_service
*/ */
function obtain_word_list() function obtain_word_list()
{ {
global $db;
if (($censors = $this->driver->get('_word_censors')) === false) if (($censors = $this->driver->get('_word_censors')) === false)
{ {
$sql = 'SELECT word, replacement $sql = 'SELECT word, replacement
FROM ' . WORDS_TABLE; FROM ' . WORDS_TABLE;
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
$censors = array(); $censors = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
$censors['match'][] = get_censor_preg_expression($row['word']); $censors['match'][] = get_censor_preg_expression($row['word']);
$censors['replace'][] = $row['replacement']; $censors['replace'][] = $row['replacement'];
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_word_censors', $censors); $this->driver->put('_word_censors', $censors);
} }
@ -93,23 +132,21 @@ class phpbb_cache_service
{ {
if (($icons = $this->driver->get('_icons')) === false) if (($icons = $this->driver->get('_icons')) === false)
{ {
global $db;
// Topic icons // Topic icons
$sql = 'SELECT * $sql = 'SELECT *
FROM ' . ICONS_TABLE . ' FROM ' . ICONS_TABLE . '
ORDER BY icons_order'; ORDER BY icons_order';
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
$icons = array(); $icons = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
$icons[$row['icons_id']]['img'] = $row['icons_url']; $icons[$row['icons_id']]['img'] = $row['icons_url'];
$icons[$row['icons_id']]['width'] = (int) $row['icons_width']; $icons[$row['icons_id']]['width'] = (int) $row['icons_width'];
$icons[$row['icons_id']]['height'] = (int) $row['icons_height']; $icons[$row['icons_id']]['height'] = (int) $row['icons_height'];
$icons[$row['icons_id']]['display'] = (bool) $row['display_on_posting']; $icons[$row['icons_id']]['display'] = (bool) $row['display_on_posting'];
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_icons', $icons); $this->driver->put('_icons', $icons);
} }
@ -124,15 +161,13 @@ class phpbb_cache_service
{ {
if (($ranks = $this->driver->get('_ranks')) === false) if (($ranks = $this->driver->get('_ranks')) === false)
{ {
global $db;
$sql = 'SELECT * $sql = 'SELECT *
FROM ' . RANKS_TABLE . ' FROM ' . RANKS_TABLE . '
ORDER BY rank_min DESC'; ORDER BY rank_min DESC';
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
$ranks = array(); $ranks = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
if ($row['rank_special']) if ($row['rank_special'])
{ {
@ -150,7 +185,7 @@ class phpbb_cache_service
); );
} }
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_ranks', $ranks); $this->driver->put('_ranks', $ranks);
} }
@ -169,8 +204,6 @@ class phpbb_cache_service
{ {
if (($extensions = $this->driver->get('_extensions')) === false) if (($extensions = $this->driver->get('_extensions')) === false)
{ {
global $db;
$extensions = array( $extensions = array(
'_allowed_post' => array(), '_allowed_post' => array(),
'_allowed_pm' => array(), '_allowed_pm' => array(),
@ -181,9 +214,9 @@ class phpbb_cache_service
FROM ' . EXTENSIONS_TABLE . ' e, ' . EXTENSION_GROUPS_TABLE . ' g FROM ' . EXTENSIONS_TABLE . ' e, ' . EXTENSION_GROUPS_TABLE . ' g
WHERE e.group_id = g.group_id WHERE e.group_id = g.group_id
AND (g.allow_group = 1 OR g.allow_in_pm = 1)'; AND (g.allow_group = 1 OR g.allow_in_pm = 1)';
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
$extension = strtolower(trim($row['extension'])); $extension = strtolower(trim($row['extension']));
@ -210,7 +243,7 @@ class phpbb_cache_service
$extensions['_allowed_pm'][$extension] = 0; $extensions['_allowed_pm'][$extension] = 0;
} }
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_extensions', $extensions); $this->driver->put('_extensions', $extensions);
} }
@ -275,9 +308,7 @@ class phpbb_cache_service
{ {
if (($bots = $this->driver->get('_bots')) === false) if (($bots = $this->driver->get('_bots')) === false)
{ {
global $db; switch ($this->db->sql_layer)
switch ($db->sql_layer)
{ {
case 'mssql': case 'mssql':
case 'mssql_odbc': case 'mssql_odbc':
@ -303,14 +334,14 @@ class phpbb_cache_service
ORDER BY LENGTH(bot_agent) DESC'; ORDER BY LENGTH(bot_agent) DESC';
break; break;
} }
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
$bots = array(); $bots = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
$bots[] = $row; $bots[] = $row;
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_bots', $bots); $this->driver->put('_bots', $bots);
} }
@ -323,8 +354,6 @@ class phpbb_cache_service
*/ */
function obtain_cfg_items($style) function obtain_cfg_items($style)
{ {
global $config, $phpbb_root_path;
$parsed_array = $this->driver->get('_cfg_' . $style['style_path']); $parsed_array = $this->driver->get('_cfg_' . $style['style_path']);
if ($parsed_array === false) if ($parsed_array === false)
@ -332,14 +361,14 @@ class phpbb_cache_service
$parsed_array = array(); $parsed_array = array();
} }
$filename = $phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg'; $filename = $this->phpbb_root_path . 'styles/' . $style['style_path'] . '/style.cfg';
if (!file_exists($filename)) if (!file_exists($filename))
{ {
return $parsed_array; return $parsed_array;
} }
if (!isset($parsed_array['filetime']) || (($config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime']))) if (!isset($parsed_array['filetime']) || (($this->config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime'])))
{ {
// Re-parse cfg file // Re-parse cfg file
$parsed_array = parse_cfg_file($filename); $parsed_array = parse_cfg_file($filename);
@ -358,54 +387,20 @@ class phpbb_cache_service
{ {
if (($usernames = $this->driver->get('_disallowed_usernames')) === false) if (($usernames = $this->driver->get('_disallowed_usernames')) === false)
{ {
global $db;
$sql = 'SELECT disallow_username $sql = 'SELECT disallow_username
FROM ' . DISALLOW_TABLE; FROM ' . DISALLOW_TABLE;
$result = $db->sql_query($sql); $result = $this->db->sql_query($sql);
$usernames = array(); $usernames = array();
while ($row = $db->sql_fetchrow($result)) while ($row = $this->db->sql_fetchrow($result))
{ {
$usernames[] = str_replace('%', '.*?', preg_quote(utf8_clean_string($row['disallow_username']), '#')); $usernames[] = str_replace('%', '.*?', preg_quote(utf8_clean_string($row['disallow_username']), '#'));
} }
$db->sql_freeresult($result); $this->db->sql_freeresult($result);
$this->driver->put('_disallowed_usernames', $usernames); $this->driver->put('_disallowed_usernames', $usernames);
} }
return $usernames; return $usernames;
} }
/**
* Obtain hooks...
*/
function obtain_hooks()
{
global $phpbb_root_path, $phpEx;
if (($hook_files = $this->driver->get('_hooks')) === false)
{
$hook_files = array();
// Now search for hooks...
$dh = @opendir($phpbb_root_path . 'includes/hooks/');
if ($dh)
{
while (($file = readdir($dh)) !== false)
{
if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($phpEx) + 1)) === '.' . $phpEx)
{
$hook_files[] = substr($file, 0, -(strlen($phpEx) + 1));
}
}
closedir($dh);
}
$this->driver->put('_hooks', $hook_files);
}
return $hook_files;
}
} }

View file

@ -118,7 +118,7 @@ class captcha
$new_line = ''; $new_line = '';
$end = strlen($scanline) - ceil($width/2); $end = strlen($scanline) - ceil($width/2);
for ($i = floor($width/2); $i < $end; $i++) for ($i = (int) floor($width / 2); $i < $end; $i++)
{ {
$pixel = ord($scanline{$i}); $pixel = ord($scanline{$i});

View file

@ -29,7 +29,7 @@ class phpbb_config_db extends phpbb_config
/** /**
* Database connection * Database connection
* @var dbal * @var phpbb_db_driver
*/ */
protected $db; protected $db;
@ -42,11 +42,11 @@ class phpbb_config_db extends phpbb_config
/** /**
* Creates a configuration container with a default set of values * Creates a configuration container with a default set of values
* *
* @param dbal $db Database connection * @param phpbb_db_driver $db Database connection
* @param phpbb_cache_driver_interface $cache Cache instance * @param phpbb_cache_driver_interface $cache Cache instance
* @param string $table Configuration table name * @param string $table Configuration table name
*/ */
public function __construct(dbal $db, phpbb_cache_driver_interface $cache, $table) public function __construct(phpbb_db_driver $db, phpbb_cache_driver_interface $cache, $table)
{ {
$this->db = $db; $this->db = $db;
$this->cache = $cache; $this->cache = $cache;

View file

@ -237,6 +237,7 @@ define('ICONS_TABLE', $table_prefix . 'icons');
define('LANG_TABLE', $table_prefix . 'lang'); define('LANG_TABLE', $table_prefix . 'lang');
define('LOG_TABLE', $table_prefix . 'log'); define('LOG_TABLE', $table_prefix . 'log');
define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts'); define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts');
define('MIGRATIONS_TABLE', $table_prefix . 'migrations');
define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache'); define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache');
define('MODULES_TABLE', $table_prefix . 'modules'); define('MODULES_TABLE', $table_prefix . 'modules');
define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options'); define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options');

View file

@ -37,9 +37,9 @@ class phpbb_cron_task_core_prune_all_forums extends phpbb_cron_task_base
* @param string $phpbb_root_path The root path * @param string $phpbb_root_path The root path
* @param string $php_ext The PHP extension * @param string $php_ext The PHP extension
* @param phpbb_config $config The config * @param phpbb_config $config The config
* @param dbal $db The db connection * @param phpbb_db_driver $db The db connection
*/ */
public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, dbal $db) public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db)
{ {
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;

View file

@ -47,9 +47,9 @@ class phpbb_cron_task_core_prune_forum extends phpbb_cron_task_base implements p
* @param string $phpbb_root_path The root path * @param string $phpbb_root_path The root path
* @param string $php_ext The PHP extension * @param string $php_ext The PHP extension
* @param phpbb_config $config The config * @param phpbb_config $config The config
* @param dbal $db The db connection * @param phpbb_db_driver $db The db connection
*/ */
public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, dbal $db) public function __construct($phpbb_root_path, $php_ext, phpbb_config $config, phpbb_db_driver $db)
{ {
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;

View file

@ -38,10 +38,10 @@ class phpbb_cron_task_core_tidy_search extends phpbb_cron_task_base
* @param string $php_ext The PHP extension * @param string $php_ext The PHP extension
* @param phpbb_auth $auth The auth * @param phpbb_auth $auth The auth
* @param phpbb_config $config The config * @param phpbb_config $config The config
* @param dbal $db The db connection * @param phpbb_db_driver $db The db connection
* @param phpbb_user $user The user * @param phpbb_user $user The user
*/ */
public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, dbal $db, phpbb_user $user) public function __construct($phpbb_root_path, $php_ext, phpbb_auth $auth, phpbb_config $config, phpbb_db_driver $db, phpbb_user $user)
{ {
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;

View file

@ -143,7 +143,7 @@ class phpbb_datetime extends DateTime
'is_short' => strpos($format, self::RELATIVE_WRAPPER) !== false, 'is_short' => strpos($format, self::RELATIVE_WRAPPER) !== false,
'format_short' => substr($format, 0, strpos($format, self::RELATIVE_WRAPPER)) . self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER . substr(strrchr($format, self::RELATIVE_WRAPPER), 1), 'format_short' => substr($format, 0, strpos($format, self::RELATIVE_WRAPPER)) . self::RELATIVE_WRAPPER . self::RELATIVE_WRAPPER . substr(strrchr($format, self::RELATIVE_WRAPPER), 1),
'format_long' => str_replace(self::RELATIVE_WRAPPER, '', $format), 'format_long' => str_replace(self::RELATIVE_WRAPPER, '', $format),
'lang' => $user->lang['datetime'], 'lang' => array_filter($user->lang['datetime'], 'is_string'),
); );
// Short representation of month in format? Some languages use different terms for the long and short format of May // Short representation of month in format? Some languages use different terms for the long and short format of May

View file

@ -300,10 +300,10 @@ class phpbb_db_tools
/** /**
* Constructor. Set DB Object and set {@link $return_statements return_statements}. * Constructor. Set DB Object and set {@link $return_statements return_statements}.
* *
* @param phpbb_dbal $db DBAL object * @param phpbb_db_driver $db Database connection
* @param bool $return_statements True if only statements should be returned and no SQL being executed * @param bool $return_statements True if only statements should be returned and no SQL being executed
*/ */
function phpbb_db_tools(&$db, $return_statements = false) function phpbb_db_tools(phpbb_db_driver $db, $return_statements = false)
{ {
$this->db = $db; $this->db = $db;
$this->return_statements = $return_statements; $this->return_statements = $return_statements;
@ -345,6 +345,17 @@ class phpbb_db_tools
} }
} }
/**
* Setter for {@link $return_statements return_statements}.
*
* @param bool $return_statements True if SQL should not be executed but returned as strings
* @return null
*/
public function set_return_statements($return_statements)
{
$this->return_statements = $return_statements;
}
/** /**
* Gets a list of tables in the database. * Gets a list of tables in the database.
* *
@ -674,6 +685,8 @@ class phpbb_db_tools
* Handle passed database update array. * Handle passed database update array.
* Expected structure... * Expected structure...
* Key being one of the following * Key being one of the following
* drop_tables: Drop tables
* add_tables: Add tables
* change_columns: Column changes (only type, not name) * change_columns: Column changes (only type, not name)
* add_columns: Add columns to a table * add_columns: Add columns to a table
* drop_keys: Dropping keys * drop_keys: Dropping keys
@ -1817,6 +1830,22 @@ class phpbb_db_tools
case 'mssql': case 'mssql':
case 'mssqlnative': case 'mssqlnative':
// remove default cosntraints first
// http://msdn.microsoft.com/en-us/library/aa175912%28v=sql.80%29.aspx
$statements[] = "DECLARE @drop_default_name VARCHAR(100), @cmd VARCHAR(1000)
SET @drop_default_name =
(SELECT so.name FROM sysobjects so
JOIN sysconstraints sc ON so.id = sc.constid
WHERE object_name(so.parent_obj) = '{$table_name}'
AND so.xtype = 'D'
AND sc.colid = (SELECT colid FROM syscolumns
WHERE id = object_id('{$table_name}')
AND name = '{$column_name}'))
IF @drop_default_name <> ''
BEGIN
SET @cmd = 'ALTER TABLE [{$table_name}] DROP CONSTRAINT [' + @drop_default_name + ']'
EXEC(@cmd)
END";
$statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']';
break; break;

View file

@ -19,7 +19,7 @@ if (!defined('IN_PHPBB'))
* Database Abstraction Layer * Database Abstraction Layer
* @package dbal * @package dbal
*/ */
class dbal class phpbb_db_driver
{ {
var $db_connect_id; var $db_connect_id;
var $query_result; var $query_result;
@ -72,17 +72,17 @@ class dbal
/** /**
* Constructor * Constructor
*/ */
function dbal() function __construct()
{ {
$this->num_queries = array( $this->num_queries = array(
'cached' => 0, 'cached' => 0,
'normal' => 0, 'normal' => 0,
'total' => 0, 'total' => 0,
); );
// Fill default sql layer based on the class being called. // Fill default sql layer based on the class being called.
// This can be changed by the specified layer itself later if needed. // This can be changed by the specified layer itself later if needed.
$this->sql_layer = substr(get_class($this), 5); $this->sql_layer = substr(get_class($this), strlen('phpbb_db_driver_'));
// Do not change this please! This variable is used to easy the use of it - and is hardcoded. // Do not change this please! This variable is used to easy the use of it - and is hardcoded.
$this->any_char = chr(0) . '%'; $this->any_char = chr(0) . '%';
@ -206,7 +206,7 @@ class dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -256,7 +256,7 @@ class dbal
$this->sql_rowseek($rownum, $query_id); $this->sql_rowseek($rownum, $query_id);
} }
if (!is_object($query_id) && $cache->sql_exists($query_id)) if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchfield($query_id, $field); return $cache->sql_fetchfield($query_id, $field);
} }
@ -822,7 +822,7 @@ class dbal
*/ */
function sql_report($mode, $query = '') function sql_report($mode, $query = '')
{ {
global $cache, $starttime, $phpbb_root_path, $user; global $cache, $starttime, $phpbb_root_path, $phpbb_admin_path, $user;
global $request; global $request;
if (is_object($request) && !$request->variable('explain', false)) if (is_object($request) && !$request->variable('explain', false))
@ -852,7 +852,7 @@ class dbal
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>SQL Report</title> <title>SQL Report</title>
<link href="' . $phpbb_root_path . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> <link href="' . htmlspecialchars($phpbb_admin_path) . 'style/admin.css" rel="stylesheet" type="text/css" media="screen" />
</head> </head>
<body id="errorpage"> <body id="errorpage">
<div id="wrap"> <div id="wrap">
@ -1042,8 +1042,3 @@ class dbal
return $rows_total; return $rows_total;
} }
} }
/**
* This variable holds the class name to use later
*/
$sql_db = (!empty($dbms)) ? 'dbal_' . basename($dbms) : 'dbal';

View file

@ -15,14 +15,12 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* Firebird/Interbase Database Abstraction Layer * Firebird/Interbase Database Abstraction Layer
* Minimum Requirement is Firebird 2.1 * Minimum Requirement is Firebird 2.1
* @package dbal * @package dbal
*/ */
class dbal_firebird extends dbal class phpbb_db_driver_firebird extends phpbb_db_driver
{ {
var $last_query_text = ''; var $last_query_text = '';
var $service_handle = false; var $service_handle = false;
@ -156,7 +154,7 @@ class dbal_firebird extends dbal
} }
$this->last_query_text = $query; $this->last_query_text = $query;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -269,10 +267,10 @@ class dbal_firebird extends dbal
} }
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -332,7 +330,7 @@ class dbal_firebird extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -398,7 +396,7 @@ class dbal_firebird extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }

View file

@ -15,20 +15,26 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* MSSQL Database Abstraction Layer * MSSQL Database Abstraction Layer
* Minimum Requirement is MSSQL 2000+ * Minimum Requirement is MSSQL 2000+
* @package dbal * @package dbal
*/ */
class dbal_mssql extends dbal class phpbb_db_driver_mssql extends phpbb_db_driver
{ {
var $connect_error = '';
/** /**
* Connect to server * Connect to server
*/ */
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{ {
if (!function_exists('mssql_connect'))
{
$this->connect_error = 'mssql_connect function does not exist, is mssql extension installed?';
return $this->sql_error('');
}
$this->persistency = $persistency; $this->persistency = $persistency;
$this->user = $sqluser; $this->user = $sqluser;
$this->dbname = $database; $this->dbname = $database;
@ -144,7 +150,7 @@ class dbal_mssql extends dbal
$this->sql_report('start', $query); $this->sql_report('start', $query);
} }
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -159,10 +165,10 @@ class dbal_mssql extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -234,7 +240,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -271,7 +277,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -310,7 +316,7 @@ class dbal_mssql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -355,34 +361,44 @@ class dbal_mssql extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
$error = array( if (function_exists('mssql_get_last_message'))
'message' => @mssql_get_last_message(),
'code' => ''
);
// Get error code number
$result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id);
if ($result_id)
{ {
$row = @mssql_fetch_assoc($result_id); $error = array(
$error['code'] = $row['code']; 'message' => @mssql_get_last_message(),
@mssql_free_result($result_id); 'code' => '',
} );
// Get full error message if possible // Get error code number
$sql = 'SELECT CAST(description as varchar(255)) as message $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id);
FROM master.dbo.sysmessages if ($result_id)
WHERE error = ' . $error['code'];
$result_id = @mssql_query($sql);
if ($result_id)
{
$row = @mssql_fetch_assoc($result_id);
if (!empty($row['message']))
{ {
$error['message'] .= '<br />' . $row['message']; $row = @mssql_fetch_assoc($result_id);
$error['code'] = $row['code'];
@mssql_free_result($result_id);
} }
@mssql_free_result($result_id);
// Get full error message if possible
$sql = 'SELECT CAST(description as varchar(255)) as message
FROM master.dbo.sysmessages
WHERE error = ' . $error['code'];
$result_id = @mssql_query($sql);
if ($result_id)
{
$row = @mssql_fetch_assoc($result_id);
if (!empty($row['message']))
{
$error['message'] .= '<br />' . $row['message'];
}
@mssql_free_result($result_id);
}
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
} }
return $error; return $error;

View file

@ -15,8 +15,6 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* Unified ODBC functions * Unified ODBC functions
* Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... * Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere...
@ -28,9 +26,10 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
* *
* @package dbal * @package dbal
*/ */
class dbal_mssql_odbc extends dbal class phpbb_db_driver_mssql_odbc extends phpbb_db_driver
{ {
var $last_query_text = ''; var $last_query_text = '';
var $connect_error = '';
/** /**
* Connect to server * Connect to server
@ -67,7 +66,24 @@ class dbal_mssql_odbc extends dbal
@ini_set('odbc.defaultlrl', $max_size); @ini_set('odbc.defaultlrl', $max_size);
} }
$this->db_connect_id = ($this->persistency) ? @odbc_pconnect($this->server, $this->user, $sqlpassword) : @odbc_connect($this->server, $this->user, $sqlpassword); if ($this->persistency)
{
if (!function_exists('odbc_pconnect'))
{
$this->connect_error = 'odbc_pconnect function does not exist, is odbc extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @odbc_pconnect($this->server, $this->user, $sqlpassword);
}
else
{
if (!function_exists('odbc_connect'))
{
$this->connect_error = 'odbc_connect function does not exist, is odbc extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @odbc_connect($this->server, $this->user, $sqlpassword);
}
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
} }
@ -163,7 +179,7 @@ class dbal_mssql_odbc extends dbal
} }
$this->last_query_text = $query; $this->last_query_text = $query;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -178,10 +194,10 @@ class dbal_mssql_odbc extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -254,7 +270,7 @@ class dbal_mssql_odbc extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -295,7 +311,7 @@ class dbal_mssql_odbc extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -349,10 +365,22 @@ class dbal_mssql_odbc extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
return array( if (function_exists('odbc_errormsg'))
'message' => @odbc_errormsg(), {
'code' => @odbc_error() $error = array(
); 'message' => @odbc_errormsg(),
'code' => @odbc_error(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
} }
/** /**

View file

@ -19,8 +19,6 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array * Prior to version 1.1 the SQL Server Native PHP driver didn't support sqlsrv_num_rows, or cursor based seeking so we recall all rows into an array
* and maintain our own cursor index into that array. * and maintain our own cursor index into that array.
@ -193,21 +191,23 @@ class result_mssqlnative
/** /**
* @package dbal * @package dbal
*/ */
class dbal_mssqlnative extends dbal class phpbb_db_driver_mssqlnative extends phpbb_db_driver
{ {
var $m_insert_id = NULL; var $m_insert_id = NULL;
var $last_query_text = ''; var $last_query_text = '';
var $query_options = array(); var $query_options = array();
var $connect_error = '';
/** /**
* Connect to server * Connect to server
*/ */
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false) function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false, $new_link = false)
{ {
# Test for driver support, to avoid suppressed fatal error // Test for driver support, to avoid suppressed fatal error
if (!function_exists('sqlsrv_connect')) if (!function_exists('sqlsrv_connect'))
{ {
trigger_error('Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx\n', E_USER_ERROR); $this->connect_error = 'Native MS SQL Server driver for PHP is missing or needs to be updated. Version 1.1 or later is required to install phpBB3. You can download the driver from: http://www.microsoft.com/sqlserver/2005/en/us/PHP-Driver.aspx';
return $this->sql_error('');
} }
//set up connection variables //set up connection variables
@ -317,7 +317,7 @@ class dbal_mssqlnative extends dbal
} }
$this->last_query_text = $query; $this->last_query_text = $query;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -337,7 +337,7 @@ class dbal_mssqlnative extends dbal
if ($cache_ttl) if ($cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -521,31 +521,43 @@ class dbal_mssqlnative extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
$errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS); if (function_exists('sqlsrv_errors'))
$error_message = '';
$code = 0;
if ($errors != null)
{ {
foreach ($errors as $error) $errors = @sqlsrv_errors(SQLSRV_ERR_ERRORS);
$error_message = '';
$code = 0;
if ($errors != null)
{ {
$error_message .= "SQLSTATE: ".$error[ 'SQLSTATE']."\n"; foreach ($errors as $error)
$error_message .= "code: ".$error[ 'code']."\n"; {
$code = $error['code']; $error_message .= "SQLSTATE: " . $error[ 'SQLSTATE'] . "\n";
$error_message .= "message: ".$error[ 'message']."\n"; $error_message .= "code: " . $error[ 'code'] . "\n";
$code = $error['code'];
$error_message .= "message: " . $error[ 'message'] . "\n";
}
$this->last_error_result = $error_message;
$error = $this->last_error_result;
} }
$this->last_error_result = $error_message; else
$error = $this->last_error_result; {
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
}
$error = array(
'message' => $error,
'code' => $code,
);
} }
else else
{ {
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); $error = array(
'message' => $this->connect_error,
'code' => '',
);
} }
return array( return $error;
'message' => $error,
'code' => $code,
);
} }
/** /**

View file

@ -15,8 +15,6 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* MySQL4 Database Abstraction Layer * MySQL4 Database Abstraction Layer
* Compatible with: * Compatible with:
@ -26,9 +24,10 @@ include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
* MySQL 5.0+ * MySQL 5.0+
* @package dbal * @package dbal
*/ */
class dbal_mysql extends dbal class phpbb_db_driver_mysql extends phpbb_db_driver
{ {
var $multi_insert = true; var $multi_insert = true;
var $connect_error = '';
/** /**
* Connect to server * Connect to server
@ -43,7 +42,24 @@ class dbal_mysql extends dbal
$this->sql_layer = 'mysql4'; $this->sql_layer = 'mysql4';
$this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $sqlpassword) : @mysql_connect($this->server, $this->user, $sqlpassword, $new_link); if ($this->persistency)
{
if (!function_exists('mysql_pconnect'))
{
$this->connect_error = 'mysql_pconnect function does not exist, is mysql extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @mysql_pconnect($this->server, $this->user, $sqlpassword);
}
else
{
if (!function_exists('mysql_connect'))
{
$this->connect_error = 'mysql_connect function does not exist, is mysql extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @mysql_connect($this->server, $this->user, $sqlpassword, $new_link);
}
if ($this->db_connect_id && $this->dbname != '') if ($this->db_connect_id && $this->dbname != '')
{ {
@ -172,7 +188,7 @@ class dbal_mysql extends dbal
$this->sql_report('start', $query); $this->sql_report('start', $query);
} }
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -187,10 +203,10 @@ class dbal_mysql extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -249,7 +265,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -270,7 +286,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -298,7 +314,7 @@ class dbal_mysql extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -426,18 +442,29 @@ class dbal_mysql extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
if (!$this->db_connect_id) if ($this->db_connect_id)
{ {
return array( $error = array(
'message' => @mysql_error($this->db_connect_id),
'code' => @mysql_errno($this->db_connect_id),
);
}
else if (function_exists('mysql_error'))
{
$error = array(
'message' => @mysql_error(), 'message' => @mysql_error(),
'code' => @mysql_errno() 'code' => @mysql_errno(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
); );
} }
return array( return $error;
'message' => @mysql_error($this->db_connect_id),
'code' => @mysql_errno($this->db_connect_id)
);
} }
/** /**

View file

@ -15,23 +15,28 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* MySQLi Database Abstraction Layer * MySQLi Database Abstraction Layer
* mysqli-extension has to be compiled with: * mysqli-extension has to be compiled with:
* MySQL 4.1+ or MySQL 5.0+ * MySQL 4.1+ or MySQL 5.0+
* @package dbal * @package dbal
*/ */
class dbal_mysqli extends dbal class phpbb_db_driver_mysqli extends phpbb_db_driver
{ {
var $multi_insert = true; var $multi_insert = true;
var $connect_error = '';
/** /**
* Connect to server * Connect to server
*/ */
function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false) function sql_connect($sqlserver, $sqluser, $sqlpassword, $database, $port = false, $persistency = false , $new_link = false)
{ {
if (!function_exists('mysqli_connect'))
{
$this->connect_error = 'mysqli_connect function does not exist, is mysqli extension installed?';
return $this->sql_error('');
}
// Mysqli extension supports persistent connection since PHP 5.3.0 // Mysqli extension supports persistent connection since PHP 5.3.0
$this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false; $this->persistency = (version_compare(PHP_VERSION, '5.3.0', '>=')) ? $persistency : false;
$this->user = $sqluser; $this->user = $sqluser;
@ -179,7 +184,7 @@ class dbal_mysqli extends dbal
$this->sql_report('start', $query); $this->sql_report('start', $query);
} }
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -194,9 +199,9 @@ class dbal_mysqli extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
} }
else if (defined('DEBUG')) else if (defined('DEBUG'))
@ -251,7 +256,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if (!is_object($query_id) && $cache->sql_exists($query_id)) if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -278,7 +283,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if (!is_object($query_id) && $cache->sql_exists($query_id)) if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -306,7 +311,7 @@ class dbal_mysqli extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if (!is_object($query_id) && $cache->sql_exists($query_id)) if ($cache && !is_object($query_id) && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -423,18 +428,29 @@ class dbal_mysqli extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
if (!$this->db_connect_id) if ($this->db_connect_id)
{ {
return array( $error = array(
'message' => @mysqli_error($this->db_connect_id),
'code' => @mysqli_errno($this->db_connect_id)
);
}
else if (function_exists('mysqli_connect_error'))
{
$error = array(
'message' => @mysqli_connect_error(), 'message' => @mysqli_connect_error(),
'code' => @mysqli_connect_errno() 'code' => @mysqli_connect_errno(),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
); );
} }
return array( return $error;
'message' => @mysqli_error($this->db_connect_id),
'code' => @mysqli_errno($this->db_connect_id)
);
} }
/** /**

View file

@ -15,15 +15,14 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* Oracle Database Abstraction Layer * Oracle Database Abstraction Layer
* @package dbal * @package dbal
*/ */
class dbal_oracle extends dbal class phpbb_db_driver_oracle extends phpbb_db_driver
{ {
var $last_query_text = ''; var $last_query_text = '';
var $connect_error = '';
/** /**
* Connect to server * Connect to server
@ -47,7 +46,33 @@ class dbal_oracle extends dbal
$connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database; $connect = $sqlserver . (($port) ? ':' . $port : '') . '/' . $database;
} }
$this->db_connect_id = ($new_link) ? @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8') : (($this->persistency) ? @ociplogon($this->user, $sqlpassword, $connect, 'UTF8') : @ocilogon($this->user, $sqlpassword, $connect, 'UTF8')); if ($new_link)
{
if (!function_exists('ocinlogon'))
{
$this->connect_error = 'ocinlogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ocinlogon($this->user, $sqlpassword, $connect, 'UTF8');
}
else if ($this->persistency)
{
if (!function_exists('ociplogon'))
{
$this->connect_error = 'ociplogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ociplogon($this->user, $sqlpassword, $connect, 'UTF8');
}
else
{
if (!function_exists('ocilogon'))
{
$this->connect_error = 'ocilogon function does not exist, is oci extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @ocilogon($this->user, $sqlpassword, $connect, 'UTF8');
}
return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error('');
} }
@ -242,7 +267,7 @@ class dbal_oracle extends dbal
} }
$this->last_query_text = $query; $this->last_query_text = $query;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -418,10 +443,10 @@ class dbal_oracle extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -473,7 +498,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -525,7 +550,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -594,7 +619,7 @@ class dbal_oracle extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -646,17 +671,27 @@ class dbal_oracle extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
$error = @ocierror(); if (function_exists('ocierror'))
$error = (!$error) ? @ocierror($this->query_result) : $error;
$error = (!$error) ? @ocierror($this->db_connect_id) : $error;
if ($error)
{ {
$this->last_error_result = $error; $error = @ocierror();
$error = (!$error) ? @ocierror($this->query_result) : $error;
$error = (!$error) ? @ocierror($this->db_connect_id) : $error;
if ($error)
{
$this->last_error_result = $error;
}
else
{
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array();
}
} }
else else
{ {
$error = (isset($this->last_error_result) && $this->last_error_result) ? $this->last_error_result : array(); $error = array(
'message' => $this->connect_error,
'code' => '',
);
} }
return $error; return $error;

View file

@ -15,19 +15,12 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
if (!class_exists('phpbb_error_collector'))
{
include($phpbb_root_path . 'includes/error_collector.' . $phpEx);
}
/** /**
* PostgreSQL Database Abstraction Layer * PostgreSQL Database Abstraction Layer
* Minimum Requirement is Version 7.3+ * Minimum Requirement is Version 7.3+
* @package dbal * @package dbal
*/ */
class dbal_postgres extends dbal class phpbb_db_driver_postgres extends phpbb_db_driver
{ {
var $last_query_text = ''; var $last_query_text = '';
var $connect_error = ''; var $connect_error = '';
@ -200,7 +193,7 @@ class dbal_postgres extends dbal
} }
$this->last_query_text = $query; $this->last_query_text = $query;
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -215,10 +208,10 @@ class dbal_postgres extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -285,7 +278,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -306,7 +299,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -355,7 +348,7 @@ class dbal_postgres extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }

View file

@ -15,15 +15,15 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
include_once($phpbb_root_path . 'includes/db/dbal.' . $phpEx);
/** /**
* Sqlite Database Abstraction Layer * Sqlite Database Abstraction Layer
* Minimum Requirement: 2.8.2+ * Minimum Requirement: 2.8.2+
* @package dbal * @package dbal
*/ */
class dbal_sqlite extends dbal class phpbb_db_driver_sqlite extends phpbb_db_driver
{ {
var $connect_error = '';
/** /**
* Connect to server * Connect to server
*/ */
@ -35,7 +35,24 @@ class dbal_sqlite extends dbal
$this->dbname = $database; $this->dbname = $database;
$error = ''; $error = '';
$this->db_connect_id = ($this->persistency) ? @sqlite_popen($this->server, 0666, $error) : @sqlite_open($this->server, 0666, $error); if ($this->persistency)
{
if (!function_exists('sqlite_popen'))
{
$this->connect_error = 'sqlite_popen function does not exist, is sqlite extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @sqlite_popen($this->server, 0666, $error);
}
else
{
if (!function_exists('sqlite_open'))
{
$this->connect_error = 'sqlite_open function does not exist, is sqlite extension installed?';
return $this->sql_error('');
}
$this->db_connect_id = @sqlite_open($this->server, 0666, $error);
}
if ($this->db_connect_id) if ($this->db_connect_id)
{ {
@ -117,7 +134,7 @@ class dbal_sqlite extends dbal
$this->sql_report('start', $query); $this->sql_report('start', $query);
} }
$this->query_result = ($cache_ttl) ? $cache->sql_load($query) : false; $this->query_result = ($cache && $cache_ttl) ? $cache->sql_load($query) : false;
$this->sql_add_num_queries($this->query_result); $this->sql_add_num_queries($this->query_result);
if ($this->query_result === false) if ($this->query_result === false)
@ -132,10 +149,10 @@ class dbal_sqlite extends dbal
$this->sql_report('stop', $query); $this->sql_report('stop', $query);
} }
if ($cache_ttl) if ($cache && $cache_ttl)
{ {
$this->open_queries[(int) $this->query_result] = $this->query_result; $this->open_queries[(int) $this->query_result] = $this->query_result;
$this->query_result = $cache->sql_save($query, $this->query_result, $cache_ttl); $this->query_result = $cache->sql_save($this, $query, $this->query_result, $cache_ttl);
} }
else if (strpos($query, 'SELECT') === 0 && $this->query_result) else if (strpos($query, 'SELECT') === 0 && $this->query_result)
{ {
@ -193,7 +210,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_fetchrow($query_id); return $cache->sql_fetchrow($query_id);
} }
@ -214,7 +231,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_rowseek($rownum, $query_id); return $cache->sql_rowseek($rownum, $query_id);
} }
@ -242,7 +259,7 @@ class dbal_sqlite extends dbal
$query_id = $this->query_result; $query_id = $this->query_result;
} }
if ($cache->sql_exists($query_id)) if ($cache && $cache->sql_exists($query_id))
{ {
return $cache->sql_freeresult($query_id); return $cache->sql_freeresult($query_id);
} }
@ -280,10 +297,22 @@ class dbal_sqlite extends dbal
*/ */
function _sql_error() function _sql_error()
{ {
return array( if (function_exists('sqlite_error_string'))
'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), {
'code' => @sqlite_last_error($this->db_connect_id) $error = array(
); 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)),
'code' => @sqlite_last_error($this->db_connect_id),
);
}
else
{
$error = array(
'message' => $this->connect_error,
'code' => '',
);
}
return $error;
} }
/** /**

View file

@ -0,0 +1,79 @@
<?php
/**
*
* @package db
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* The migrator is responsible for applying new migrations in the correct order.
*
* @package db
*/
class phpbb_db_migration_exception extends \Exception
{
/**
* Extra parameters sent to exception to aid in debugging
* @var array
*/
protected $parameters;
/**
* Throw an exception.
*
* First argument is the error message.
* Additional arguments will be output with the error message.
*/
public function __construct()
{
$parameters = func_get_args();
$message = array_shift($parameters);
parent::__construct($message);
$this->parameters = $parameters;
}
/**
* Output the error as a string
*
* @return string
*/
public function __toString()
{
return $this->message . ': ' . var_export($this->parameters, true);
}
/**
* Get the parameters
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Get localised message (with $user->lang())
*
* @param phpbb_user $user
* @return string
*/
public function getLocalisedMessage(phpbb_user $user)
{
$parameters = $this->getParameters();
array_unshift($parameters, $this->getMessage());
return call_user_func_array(array($user, 'lang'), $parameters);
}
}

View file

@ -0,0 +1,190 @@
<?php
/**
*
* @package db
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Abstract base class for database migrations
*
* Each migration consists of a set of schema and data changes to be implemented
* in a subclass. This class provides various utility methods to simplify editing
* a phpBB.
*
* @package db
*/
abstract class phpbb_db_migration
{
/** @var phpbb_config */
protected $config;
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_db_tools */
protected $db_tools;
/** @var string */
protected $table_prefix;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/** @var array Errors, if any occured */
protected $errors;
/** @var array List of queries executed through $this->sql_query() */
protected $queries = array();
/**
* Constructor
*
* @param phpbb_config $config
* @param phpbb_db_driver $db
* @param phpbb_db_tools $db_tools
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $table_prefix
*/
public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $phpbb_root_path, $php_ext, $table_prefix)
{
$this->config = $config;
$this->db = $db;
$this->db_tools = $db_tools;
$this->table_prefix = $table_prefix;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->errors = array();
}
/**
* Defines other migrations to be applied first
*
* @return array An array of migration class names
*/
static public function depends_on()
{
return array();
}
/**
* Allows you to check if the migration is effectively installed (entirely optional)
*
* This is checked when a migration is installed. If true is returned, the migration will be set as
* installed without performing the database changes.
* This function is intended to help moving to migrations from a previous database updater, where some
* migrations may have been installed already even though they are not yet listed in the migrations table.
*
* @return bool True if this migration is installed, False if this migration is not installed (checked on install)
*/
public function effectively_installed()
{
return false;
}
/**
* Updates the database schema by providing a set of change instructions
*
* @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
*/
public function update_schema()
{
return array();
}
/**
* Reverts the database schema by providing a set of change instructions
*
* @return array Array of schema changes (compatible with db_tools->perform_schema_changes())
*/
public function revert_schema()
{
return array();
}
/**
* Updates data by returning a list of instructions to be executed
*
* @return array Array of data update instructions
*/
public function update_data()
{
return array();
}
/**
* Reverts data by returning a list of instructions to be executed
*
* @return array Array of data instructions that will be performed on revert
* NOTE: calls to tools (such as config.add) are automatically reverted when
* possible, so you should not attempt to revert those, this is mostly for
* otherwise unrevertable calls (custom functions for example)
*/
public function revert_data()
{
return array();
}
/**
* Wrapper for running queries to generate user feedback on updates
*
* @param string $sql SQL query to run on the database
* @return mixed Query result from db->sql_query()
*/
protected function sql_query($sql)
{
$this->queries[] = $sql;
$this->db->sql_return_on_error(true);
if ($sql === 'begin')
{
$result = $this->db->sql_transaction('begin');
}
else if ($sql === 'commit')
{
$result = $this->db->sql_transaction('commit');
}
else
{
$result = $this->db->sql_query($sql);
if ($this->db->sql_error_triggered)
{
$this->errors[] = array(
'sql' => $this->db->sql_error_sql,
'code' => $this->db->sql_error_returned,
);
}
}
$this->db->sql_return_on_error(false);
return $result;
}
/**
* Get the list of queries run
*
* @return array
*/
public function get_queries()
{
return $this->queries;
}
}

View file

@ -0,0 +1,150 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* Migration config tool
*
* @package db
*/
class phpbb_db_migration_tool_config implements phpbb_db_migration_tool_interface
{
/** @var phpbb_config */
protected $config;
/**
* Constructor
*
* @param phpbb_config $config
*/
public function __construct(phpbb_config $config)
{
$this->config = $config;
}
/**
* {@inheritdoc}
*/
public function get_name()
{
return 'config';
}
/**
* Add a config setting.
*
* @param string $config_name The name of the config setting
* you would like to add
* @param mixed $config_value The value of the config setting
* @param bool $is_dynamic True if it is dynamic (changes very often)
* and should not be stored in the cache, false if not.
* @return null
*/
public function add($config_name, $config_value, $is_dynamic = false)
{
if (isset($this->config[$config_name]))
{
throw new phpbb_db_migration_exception('CONFIG_ALREADY_EXIST', $config_name);
}
$this->config->set($config_name, $config_value, !$is_dynamic);
}
/**
* Update an existing config setting.
*
* @param string $config_name The name of the config setting you would
* like to update
* @param mixed $config_value The value of the config setting
* @return null
*/
public function update($config_name, $config_value)
{
if (!isset($this->config[$config_name]))
{
throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name);
}
$this->config->set($config_name, $config_value);
}
/**
* Update a config setting if the first argument equal to the
* current config value
*
* @param string $compare If equal to the current config value, will be
* updated to the new config value, otherwise not
* @param string $config_name The name of the config setting you would
* like to update
* @param mixed $config_value The value of the config setting
* @return null
*/
public function update_if_equals($compare, $config_name, $config_value)
{
if (!isset($this->config[$config_name]))
{
throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name);
}
$this->config->set_atomic($config_name, $compare, $config_value);
}
/**
* Remove an existing config setting.
*
* @param string $config_name The name of the config setting you would
* like to remove
* @return null
*/
public function remove($config_name)
{
if (!isset($this->config[$config_name]))
{
throw new phpbb_db_migration_exception('CONFIG_NOT_EXIST', $config_name);
}
$this->config->delete($config_name);
}
/**
* {@inheritdoc}
*/
public function reverse()
{
$arguments = func_get_args();
$original_call = array_shift($arguments);
$call = false;
switch ($original_call)
{
case 'add':
$call = 'remove';
break;
case 'remove':
$call = 'add';
break;
case 'update_if_equals':
$call = 'update_if_equals';
// Set to the original value if the current value is what we compared to originally
$arguments = array(
$arguments[2],
$arguments[1],
$arguments[0],
);
break;
}
if ($call)
{
return call_user_func_array(array(&$this, $call), $arguments);
}
}
}

View file

@ -0,0 +1,33 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* Migration tool interface
*
* @package db
*/
interface phpbb_db_migration_tool_interface
{
/**
* Retrieve a short name used for commands in migrations.
*
* @return string short name
*/
public function get_name();
/**
* Reverse an original install action
*
* First argument is the original call to the class (e.g. add, remove)
* After the first argument, send the original arguments to the function in the original call
*
* @return null
*/
public function reverse();
}

View file

@ -0,0 +1,513 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* Migration module management tool
*
* @package db
*/
class phpbb_db_migration_tool_module implements phpbb_db_migration_tool_interface
{
/** @var phpbb_cache_service */
protected $cache;
/** @var dbal */
protected $db;
/** @var phpbb_user */
protected $user;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/** @var string */
protected $modules_table;
/**
* Constructor
*
* @param phpbb_db_driver $db
* @param mixed $cache
* @param phpbb_user $user
* @param string $phpbb_root_path
* @param string $php_ext
* @param string $modules_table
*/
public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_user $user, $phpbb_root_path, $php_ext, $modules_table)
{
$this->db = $db;
$this->cache = $cache;
$this->user = $user;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->modules_table = $modules_table;
}
/**
* {@inheritdoc}
*/
public function get_name()
{
return 'module';
}
/**
* Module Exists
*
* Check if a module exists
*
* @param string $class The module class(acp|mcp|ucp)
* @param int|string|bool $parent The parent module_id|module_langname (0 for no parent).
* Use false to ignore the parent check and check class wide.
* @param int|string $module The module_id|module_langname you would like to
* check for to see if it exists
* @return bool true/false if module exists
*/
public function exists($class, $parent, $module)
{
// the main root directory should return true
if (!$module)
{
return true;
}
$parent_sql = '';
if ($parent !== false)
{
// Allows '' to be sent as 0
$parent = $parent ?: 0;
if (!is_numeric($parent))
{
$sql = 'SELECT module_id
FROM ' . $this->modules_table . "
WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
AND module_class = '" . $this->db->sql_escape($class) . "'";
$result = $this->db->sql_query($sql);
$module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
if (!$module_id)
{
return false;
}
$parent_sql = 'AND parent_id = ' . (int) $module_id;
}
else
{
$parent_sql = 'AND parent_id = ' . (int) $parent;
}
}
$sql = 'SELECT module_id
FROM ' . $this->modules_table . "
WHERE module_class = '" . $this->db->sql_escape($class) . "'
$parent_sql
AND " . ((is_numeric($module)) ? 'module_id = ' . (int) $module : "module_langname = '" . $this->db->sql_escape($module) . "'");
$result = $this->db->sql_query($sql);
$module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
if ($module_id)
{
return true;
}
return false;
}
/**
* Module Add
*
* Add a new module
*
* @param string $class The module class(acp|mcp|ucp)
* @param int|string $parent The parent module_id|module_langname (0 for no parent)
* @param array $data an array of the data on the new module.
* This can be setup in two different ways.
* 1. The "manual" way. For inserting a category or one at a time.
* It will be merged with the base array shown a bit below,
* but at the least requires 'module_langname' to be sent, and,
* if you want to create a module (instead of just a category) you must
* send module_basename and module_mode.
* array(
* 'module_enabled' => 1,
* 'module_display' => 1,
* 'module_basename' => '',
* 'module_class' => $class,
* 'parent_id' => (int) $parent,
* 'module_langname' => '',
* 'module_mode' => '',
* 'module_auth' => '',
* )
* 2. The "automatic" way. For inserting multiple at a time based on the
* specs in the info file for the module(s). For this to work the
* modules must be correctly setup in the info file.
* An example follows (this would insert the settings, log, and flag
* modes from the includes/acp/info/acp_asacp.php file):
* array(
* 'module_basename' => 'asacp',
* 'modes' => array('settings', 'log', 'flag'),
* )
* Optionally you may not send 'modes' and it will insert all of the
* modules in that info file.
* @param string|bool $include_path If you would like to use a custom include
* path, specify that here
* @return null
*/
public function add($class, $parent = 0, $data = array(), $include_path = false)
{
// Allows '' to be sent as 0
$parent = $parent ?: 0;
// allow sending the name as a string in $data to create a category
if (!is_array($data))
{
$data = array('module_langname' => $data);
}
if (!isset($data['module_langname']))
{
// The "automatic" way
$basename = (isset($data['module_basename'])) ? $data['module_basename'] : '';
$basename = str_replace(array('/', '\\'), '', $basename);
$class = str_replace(array('/', '\\'), '', $class);
$include_path = ($include_path === false) ? $this->phpbb_root_path . 'includes/' : $include_path;
$info_file = "$class/info/$basename.{$this->php_ext}";
// The manual and automatic ways both failed...
if (!file_exists($include_path . $info_file))
{
throw new phpbb_db_migration_exception('MODULE_INFO_FILE_NOT_EXIST', $class, $info_file);
}
$classname = "{$basename}_info";
if (!class_exists($classname))
{
include($include_path . $info_file);
}
$info = new $classname;
$module = $info->module();
unset($info);
$result = '';
foreach ($module['modes'] as $mode => $module_info)
{
if (!isset($data['modes']) || in_array($mode, $data['modes']))
{
$new_module = array(
'module_basename' => $basename,
'module_langname' => $module_info['title'],
'module_mode' => $mode,
'module_auth' => $module_info['auth'],
'module_display' => (isset($module_info['display'])) ? $module_info['display'] : true,
'before' => (isset($module_info['before'])) ? $module_info['before'] : false,
'after' => (isset($module_info['after'])) ? $module_info['after'] : false,
);
// Run the "manual" way with the data we've collected.
$this->add($class, $parent, $new_module);
}
}
return;
}
// The "manual" way
$module_log_name = ((isset($this->user->lang[$data['module_langname']])) ? $this->user->lang[$data['module_langname']] : $data['module_langname']);
add_log('admin', 'LOG_MODULE_ADD', $module_log_name);
if (!is_numeric($parent))
{
$sql = 'SELECT module_id
FROM ' . $this->modules_table . "
WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
AND module_class = '" . $this->db->sql_escape($class) . "'";
$result = $this->db->sql_query($sql);
$module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
if (!$module_id)
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent);
}
$parent = $data['parent_id'] = $module_id;
}
else if (!$this->exists($class, false, $parent))
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $parent);
}
if ($this->exists($class, $parent, $data['module_langname']))
{
throw new phpbb_db_migration_exception('MODULE_ALREADY_EXIST', $data['module_langname']);
}
if (!class_exists('acp_modules'))
{
include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
$this->user->add_lang('acp/modules');
}
$acp_modules = new acp_modules();
$module_data = array(
'module_enabled' => (isset($data['module_enabled'])) ? $data['module_enabled'] : 1,
'module_display' => (isset($data['module_display'])) ? $data['module_display'] : 1,
'module_basename' => (isset($data['module_basename'])) ? $data['module_basename'] : '',
'module_class' => $class,
'parent_id' => (int) $parent,
'module_langname' => (isset($data['module_langname'])) ? $data['module_langname'] : '',
'module_mode' => (isset($data['module_mode'])) ? $data['module_mode'] : '',
'module_auth' => (isset($data['module_auth'])) ? $data['module_auth'] : '',
);
$result = $acp_modules->update_module_data($module_data, true);
// update_module_data can either return a string or an empty array...
if (is_string($result))
{
// Error
throw new phpbb_db_migration_exception('MODULE_ERROR', $result);
}
else
{
// Success
// Move the module if requested above/below an existing one
if (isset($data['before']) && $data['before'])
{
$sql = 'SELECT left_id
FROM ' . $this->modules_table . "
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND parent_id = " . (int) $parent . "
AND module_langname = '" . $this->db->sql_escape($data['before']) . "'";
$this->db->sql_query($sql);
$to_left = (int) $this->db->sql_fetchfield('left_id');
$sql = 'UPDATE ' . $this->modules_table . "
SET left_id = left_id + 2, right_id = right_id + 2
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND left_id >= $to_left
AND left_id < {$module_data['left_id']}";
$this->db->sql_query($sql);
$sql = 'UPDATE ' . $this->modules_table . "
SET left_id = $to_left, right_id = " . ($to_left + 1) . "
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND module_id = {$module_data['module_id']}";
$this->db->sql_query($sql);
}
else if (isset($data['after']) && $data['after'])
{
$sql = 'SELECT right_id
FROM ' . $this->modules_table . "
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND parent_id = " . (int) $parent . "
AND module_langname = '" . $this->db->sql_escape($data['after']) . "'";
$this->db->sql_query($sql);
$to_right = (int) $this->db->sql_fetchfield('right_id');
$sql = 'UPDATE ' . $this->modules_table . "
SET left_id = left_id + 2, right_id = right_id + 2
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND left_id >= $to_right
AND left_id < {$module_data['left_id']}";
$this->db->sql_query($sql);
$sql = 'UPDATE ' . $this->modules_table . '
SET left_id = ' . ($to_right + 1) . ', right_id = ' . ($to_right + 2) . "
WHERE module_class = '" . $this->db->sql_escape($class) . "'
AND module_id = {$module_data['module_id']}";
$this->db->sql_query($sql);
}
}
// Clear the Modules Cache
$this->cache->destroy("_modules_$class");
}
/**
* Module Remove
*
* Remove a module
*
* @param string $class The module class(acp|mcp|ucp)
* @param int|string|bool $parent The parent module_id|module_langname(0 for no parent).
* Use false to ignore the parent check and check class wide.
* @param int|string $module The module id|module_langname
* @param string|bool $include_path If you would like to use a custom include path,
* specify that here
* @return null
*/
public function remove($class, $parent = 0, $module = '', $include_path = false)
{
// Imitation of module_add's "automatic" and "manual" method so the uninstaller works from the same set of instructions for umil_auto
if (is_array($module))
{
if (isset($module['module_langname']))
{
// Manual Method
return $this->remove($class, $parent, $module['module_langname'], $include_path);
}
// Failed.
if (!isset($module['module_basename']))
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST');
}
// Automatic method
$basename = str_replace(array('/', '\\'), '', $module['module_basename']);
$class = str_replace(array('/', '\\'), '', $class);
$include_path = ($include_path === false) ? $this->phpbb_root_path . 'includes/' : $include_path;
$info_file = "$class/info/$basename.{$this->php_ext}";
if (!file_exists($include_path . $info_file))
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', $info_file);
}
$classname = "{$basename}_info";
if (!class_exists($classname))
{
include($include_path . $info_file);
}
$info = new $classname;
$module_info = $info->module();
unset($info);
foreach ($module_info['modes'] as $mode => $info)
{
if (!isset($module['modes']) || in_array($mode, $module['modes']))
{
$this->remove($class, $parent, $info['title']) . '<br />';
}
}
}
else
{
if (!$this->exists($class, $parent, $module))
{
throw new phpbb_db_migration_exception('MODULE_NOT_EXIST', ((isset($this->user->lang[$module])) ? $this->user->lang[$module] : $module));
}
$parent_sql = '';
if ($parent !== false)
{
// Allows '' to be sent as 0
$parent = ($parent) ?: 0;
if (!is_numeric($parent))
{
$sql = 'SELECT module_id
FROM ' . $this->modules_table . "
WHERE module_langname = '" . $this->db->sql_escape($parent) . "'
AND module_class = '" . $this->db->sql_escape($class) . "'";
$result = $this->db->sql_query($sql);
$module_id = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
// we know it exists from the module_exists check
$parent_sql = 'AND parent_id = ' . (int) $module_id;
}
else
{
$parent_sql = 'AND parent_id = ' . (int) $parent;
}
}
$module_ids = array();
if (!is_numeric($module))
{
$sql = 'SELECT module_id
FROM ' . $this->modules_table . "
WHERE module_langname = '" . $this->db->sql_escape($module) . "'
AND module_class = '" . $this->db->sql_escape($class) . "'
$parent_sql";
$result = $this->db->sql_query($sql);
while ($module_id = $this->db->sql_fetchfield('module_id'))
{
$module_ids[] = (int) $module_id;
}
$this->db->sql_freeresult($result);
$module_name = $module;
}
else
{
$module = (int) $module;
$sql = 'SELECT module_langname
FROM ' . $this->modules_table . "
WHERE module_id = $module
AND module_class = '" . $this->db->sql_escape($class) . "'
$parent_sql";
$result = $this->db->sql_query($sql);
$module_name = $this->db->sql_fetchfield('module_id');
$this->db->sql_freeresult($result);
$module_ids[] = $module;
}
if (!class_exists('acp_modules'))
{
include($this->phpbb_root_path . 'includes/acp/acp_modules.' . $this->php_ext);
$this->user->add_lang('acp/modules');
}
$acp_modules = new acp_modules();
$acp_modules->module_class = $class;
foreach ($module_ids as $module_id)
{
$result = $acp_modules->delete_module($module_id);
if (!empty($result))
{
throw new phpbb_db_migration_exception('MODULE_NOT_REMOVABLE', $module_id, $result);
}
}
$this->cache->destroy("_modules_$class");
}
}
/**
* {@inheritdoc}
*/
public function reverse()
{
$arguments = func_get_args();
$original_call = array_shift($arguments);
$call = false;
switch ($original_call)
{
case 'add':
$call = 'remove';
break;
case 'remove':
$call = 'add';
break;
}
if ($call)
{
return call_user_func_array(array(&$this, $call), $arguments);
}
}
}

View file

@ -0,0 +1,622 @@
<?php
/**
*
* @package migration
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License v2
*
*/
/**
* Migration permission management tool
*
* @package db
*/
class phpbb_db_migration_tool_permission implements phpbb_db_migration_tool_interface
{
/** @var phpbb_auth */
protected $auth;
/** @var phpbb_cache_service */
protected $cache;
/** @var dbal */
protected $db;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/**
* Constructor
*
* @param phpbb_db_driver $db
* @param mixed $cache
* @param phpbb_auth $auth
* @param string $phpbb_root_path
* @param string $php_ext
*/
public function __construct(phpbb_db_driver $db, phpbb_cache_service $cache, phpbb_auth $auth, $phpbb_root_path, $php_ext)
{
$this->db = $db;
$this->cache = $cache;
$this->auth = $auth;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
}
/**
* {@inheritdoc}
*/
public function get_name()
{
return 'permission';
}
/**
* Permission Exists
*
* Check if a permission (auth) setting exists
*
* @param string $auth_option The name of the permission (auth) option
* @param bool $global True for checking a global permission setting,
* False for a local permission setting
* @return bool true if it exists, false if not
*/
public function exists($auth_option, $global = true)
{
if ($global)
{
$type_sql = ' AND is_global = 1';
}
else
{
$type_sql = ' AND is_local = 1';
}
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'"
. $type_sql;
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
if ($row)
{
return true;
}
return false;
}
/**
* Permission Add
*
* Add a permission (auth) option
*
* @param string $auth_option The name of the permission (auth) option
* @param bool $global True for checking a global permission setting,
* False for a local permission setting
* @return null
*/
public function add($auth_option, $global = true, $copy_from = false)
{
if ($this->exists($auth_option, $global))
{
throw new phpbb_db_migration_exception('PERMISSION_ALREADY_EXIST', $auth_option);
}
// We've added permissions, so set to true to notify the user.
$this->permissions_added = true;
if (!class_exists('auth_admin'))
{
include($this->phpbb_root_path . 'includes/acp/auth.' . $this->php_ext);
}
$auth_admin = new auth_admin();
// We have to add a check to see if the !$global (if global, local, and if local, global) permission already exists. If it does, acl_add_option currently has a bug which would break the ACL system, so we are having a work-around here.
if ($this->exists($auth_option, !$global))
{
$sql_ary = array(
'is_global' => 1,
'is_local' => 1,
);
$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
SET ' . $this->db->sql_build_array('UPDATE', $sql_ary) . "
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'";
$this->db->sql_query($sql);
}
else
{
if ($global)
{
$auth_admin->acl_add_option(array('global' => array($auth_option)));
}
else
{
$auth_admin->acl_add_option(array('local' => array($auth_option)));
}
}
// The permission has been added, now we can copy it if needed
if ($copy_from && isset($auth_admin->acl_options['id'][$copy_from]))
{
$old_id = $auth_admin->acl_options['id'][$copy_from];
$new_id = $auth_admin->acl_options['id'][$auth_option];
$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE);
foreach ($tables as $table)
{
$sql = 'SELECT *
FROM ' . $table . '
WHERE auth_option_id = ' . $old_id;
$result = $this->db->sql_query($sql);
$sql_ary = array();
while ($row = $this->db->sql_fetchrow($result))
{
$row['auth_option_id'] = $new_id;
$sql_ary[] = $row;
}
$this->db->sql_freeresult($result);
if (!empty($sql_ary))
{
$this->db->sql_multi_insert($table, $sql_ary);
}
}
$auth_admin->acl_clear_prefetch();
}
}
/**
* Permission Remove
*
* Remove a permission (auth) option
*
* @param string $auth_option The name of the permission (auth) option
* @param bool $global True for checking a global permission setting,
* False for a local permission setting
* @return null
*/
public function remove($auth_option, $global = true)
{
if (!$this->exists($auth_option, $global))
{
throw new phpbb_db_migration_exception('PERMISSION_NOT_EXIST', $auth_option);
}
if ($global)
{
$type_sql = ' AND is_global = 1';
}
else
{
$type_sql = ' AND is_local = 1';
}
$sql = 'SELECT auth_option_id, is_global, is_local
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option = '" . $this->db->sql_escape($auth_option) . "'" .
$type_sql;
$result = $this->db->sql_query($sql);
$row = $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);
$id = (int) $row['auth_option_id'];
// If it is a local and global permission, do not remove the row! :P
if ($row['is_global'] && $row['is_local'])
{
$sql = 'UPDATE ' . ACL_OPTIONS_TABLE . '
SET ' . (($global) ? 'is_global = 0' : 'is_local = 0') . '
WHERE auth_option_id = ' . $id;
$this->db->sql_query($sql);
}
else
{
// Delete time
$tables = array(ACL_GROUPS_TABLE, ACL_ROLES_DATA_TABLE, ACL_USERS_TABLE, ACL_OPTIONS_TABLE);
foreach ($tables as $table)
{
$this->db->sql_query('DELETE FROM ' . $table . '
WHERE auth_option_id = ' . $id);
}
}
// Purge the auth cache
$this->cache->destroy('_acl_options');
$this->auth->acl_clear_prefetch();
}
/**
* Add a new permission role
*
* @param string $role_name The new role name
* @param sting $role_type The type (u_, m_, a_)
* @return null
*/
public function role_add($role_name, $role_type, $role_description = '')
{
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = '" . $this->db->sql_escape($role_name) . "'";
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('role_id');
if ($role_id)
{
return;
}
$sql = 'SELECT MAX(role_order) AS max_role_order
FROM ' . ACL_ROLES_TABLE . "
WHERE role_type = '" . $this->db->sql_escape($role_type) . "'";
$this->db->sql_query($sql);
$role_order = (int) $this->db->sql_fetchfield('max_role_order');
$role_order = (!$role_order) ? 1 : $role_order + 1;
$sql_ary = array(
'role_name' => $role_name,
'role_description' => $role_description,
'role_type' => $role_type,
'role_order' => $role_order,
);
$sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
$this->db->sql_query($sql);
}
/**
* Update the name on a permission role
*
* @param string $old_role_name The old role name
* @param string $new_role_name The new role name
* @return null
*/
public function role_update($old_role_name, $new_role_name)
{
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'";
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('role_id');
if (!$role_id)
{
throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $old_role_name);
}
$sql = 'UPDATE ' . ACL_ROLES_TABLE . "
SET role_name = '" . $this->db->sql_escape($new_role_name) . "'
WHERE role_name = '" . $this->db->sql_escape($old_role_name) . "'";
$this->db->sql_query($sql);
}
/**
* Remove a permission role
*
* @param string $role_name The role name to remove
* @return null
*/
public function role_remove($role_name)
{
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = '" . $this->db->sql_escape($role_name) . "'";
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('role_id');
if (!$role_id)
{
throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $role_name);
}
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
WHERE role_id = ' . $role_id;
$this->db->sql_query($sql);
$sql = 'DELETE FROM ' . ACL_ROLES_TABLE . '
WHERE role_id = ' . $role_id;
$this->db->sql_query($sql);
$this->auth->acl_clear_prefetch();
}
/**
* Permission Set
*
* Allows you to set permissions for a certain group/role
*
* @param string $name The name of the role/group
* @param string|array $auth_option The auth_option or array of
* auth_options you would like to set
* @param string $type The type (role|group)
* @param bool $has_permission True if you want to give them permission,
* false if you want to deny them permission
* @return null
*/
public function permission_set($name, $auth_option, $type = 'role', $has_permission = true)
{
if (!is_array($auth_option))
{
$auth_option = array($auth_option);
}
$new_auth = array();
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . '
WHERE ' . $this->db->sql_in_set('auth_option', $auth_option);
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$new_auth[] = (int) $row['auth_option_id'];
}
$this->db->sql_freeresult($result);
if (empty($new_auth))
{
return;
}
$current_auth = array();
$type = (string) $type; // Prevent PHP bug.
switch ($type)
{
case 'role':
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('role_id');
if (!$role_id)
{
throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name);
}
$sql = 'SELECT auth_option_id, auth_setting
FROM ' . ACL_ROLES_DATA_TABLE . '
WHERE role_id = ' . $role_id;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$current_auth[$row['auth_option_id']] = $row['auth_setting'];
}
$this->db->sql_freeresult($result);
break;
case 'group':
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$group_id = (int) $this->db->sql_fetchfield('group_id');
if (!$group_id)
{
throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name);
}
// If the group has a role set for them we will add the requested permissions to that role.
$sql = 'SELECT auth_role_id
FROM ' . ACL_GROUPS_TABLE . '
WHERE group_id = ' . $group_id . '
AND auth_role_id <> 0
AND forum_id = 0';
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('auth_role_id');
if ($role_id)
{
$sql = 'SELECT role_name
FROM ' . ACL_ROLES_TABLE . '
WHERE role_id = ' . $role_id;
$this->db->sql_query($sql);
$role_name = $this->db->sql_fetchfield('role_name');
return $this->set($role_name, $auth_option, 'role', $has_permission);
}
$sql = 'SELECT auth_option_id, auth_setting
FROM ' . ACL_GROUPS_TABLE . '
WHERE group_id = ' . $group_id;
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$current_auth[$row['auth_option_id']] = $row['auth_setting'];
}
$this->db->sql_freeresult($result);
break;
}
$sql_ary = array();
switch ($type)
{
case 'role':
foreach ($new_auth as $auth_option_id)
{
if (!isset($current_auth[$auth_option_id]))
{
$sql_ary[] = array(
'role_id' => $role_id,
'auth_option_id' => $auth_option_id,
'auth_setting' => $has_permission,
);
}
}
$this->db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary);
break;
case 'group':
foreach ($new_auth as $auth_option_id)
{
if (!isset($current_auth[$auth_option_id]))
{
$sql_ary[] = array(
'group_id' => $group_id,
'auth_option_id' => $auth_option_id,
'auth_setting' => $has_permission,
);
}
}
$this->db->sql_multi_insert(ACL_GROUPS_TABLE, $sql_ary);
break;
}
$this->auth->acl_clear_prefetch();
}
/**
* Permission Unset
*
* Allows you to unset (remove) permissions for a certain group/role
*
* @param string $name The name of the role/group
* @param string|array $auth_option The auth_option or array of
* auth_options you would like to set
* @param string $type The type (role|group)
* @return null
*/
public function permission_unset($name, $auth_option, $type = 'role')
{
if (!is_array($auth_option))
{
$auth_option = array($auth_option);
}
$to_remove = array();
$sql = 'SELECT auth_option_id
FROM ' . ACL_OPTIONS_TABLE . '
WHERE ' . $this->db->sql_in_set('auth_option', $auth_option);
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$to_remove[] = (int) $row['auth_option_id'];
}
$this->db->sql_freeresult($result);
if (empty($to_remove))
{
return;
}
$type = (string) $type; // Prevent PHP bug.
switch ($type)
{
case 'role':
$sql = 'SELECT role_id
FROM ' . ACL_ROLES_TABLE . "
WHERE role_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('role_id');
if (!$role_id)
{
throw new phpbb_db_migration_exception('ROLE_NOT_EXIST', $name);
}
$sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . '
WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove);
$this->db->sql_query($sql);
break;
case 'group':
$sql = 'SELECT group_id
FROM ' . GROUPS_TABLE . "
WHERE group_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$group_id = (int) $this->db->sql_fetchfield('group_id');
if (!$group_id)
{
throw new phpbb_db_migration_exception('GROUP_NOT_EXIST', $name);
}
// If the group has a role set for them we will remove the requested permissions from that role.
$sql = 'SELECT auth_role_id
FROM ' . ACL_GROUPS_TABLE . '
WHERE group_id = ' . $group_id . '
AND auth_role_id <> 0';
$this->db->sql_query($sql);
$role_id = (int) $this->db->sql_fetchfield('auth_role_id');
if ($role_id)
{
$sql = 'SELECT role_name
FROM ' . ACL_ROLES_TABLE . '
WHERE role_id = ' . $role_id;
$this->db->sql_query($sql);
$role_name = $this->db->sql_fetchfield('role_name');
return $this->permission_unset($role_name, $auth_option, 'role');
}
$sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . '
WHERE ' . $this->db->sql_in_set('auth_option_id', $to_remove);
$this->db->sql_query($sql);
break;
}
$this->auth->acl_clear_prefetch();
}
/**
* {@inheritdoc}
*/
public function reverse()
{
$arguments = func_get_args();
$original_call = array_shift($arguments);
$call = false;
switch ($original_call)
{
case 'add':
$call = 'remove';
break;
case 'remove':
$call = 'add';
break;
case 'permission_set':
$call = 'permission_unset';
break;
case 'permission_unset':
$call = 'permission_set';
break;
case 'role_add':
$call = 'role_remove';
break;
case 'role_remove':
$call = 'role_add';
break;
case 'role_update':
// Set to the original value if the current value is what we compared to originally
$arguments = array(
$arguments[1],
$arguments[0],
);
break;
}
if ($call)
{
return call_user_func_array(array(&$this, $call), $arguments);
}
}
}

View file

@ -0,0 +1,764 @@
<?php
/**
*
* @package db
* @copyright (c) 2011 phpBB Group
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* The migrator is responsible for applying new migrations in the correct order.
*
* @package db
*/
class phpbb_db_migrator
{
/** @var phpbb_config */
protected $config;
/** @var phpbb_db_driver */
protected $db;
/** @var phpbb_db_tools */
protected $db_tools;
/** @var string */
protected $table_prefix;
/** @var string */
protected $phpbb_root_path;
/** @var string */
protected $php_ext;
/** @var string */
protected $migrations_table;
/**
* State of all migrations
*
* (SELECT * FROM migrations table)
*
* @var array
*/
protected $migration_state = array();
/**
* Array of all migrations available to be run
*
* @var array
*/
protected $migrations = array();
/**
* 'name' and 'class' of the last migration run
*
* @var array
*/
public $last_run_migration = false;
/**
* Constructor of the database migrator
*/
public function __construct(phpbb_config $config, phpbb_db_driver $db, phpbb_db_tools $db_tools, $migrations_table, $phpbb_root_path, $php_ext, $table_prefix, $tools)
{
$this->config = $config;
$this->db = $db;
$this->db_tools = $db_tools;
$this->migrations_table = $migrations_table;
$this->phpbb_root_path = $phpbb_root_path;
$this->php_ext = $php_ext;
$this->table_prefix = $table_prefix;
foreach ($tools as $tool)
{
$this->tools[$tool->get_name()] = $tool;
}
$this->load_migration_state();
}
/**
* Loads all migrations and their application state from the database.
*
* @return null
*/
public function load_migration_state()
{
$this->migration_state = array();
$sql = "SELECT *
FROM " . $this->migrations_table;
$result = $this->db->sql_query($sql);
while ($migration = $this->db->sql_fetchrow($result))
{
$this->migration_state[$migration['migration_name']] = $migration;
$this->migration_state[$migration['migration_name']]['migration_depends_on'] = unserialize($migration['migration_depends_on']);
}
$this->db->sql_freeresult($result);
}
/**
* Sets the list of available migration class names to the given array.
*
* @param array $class_names An array of migration class names
* @return null
*/
public function set_migrations($class_names)
{
$this->migrations = $class_names;
}
/**
* This function adds all migrations in a specified directory to the migrations table
*
* THIS SHOULD NOT GENERALLY BE USED! THIS IS FOR THE PHPBB INSTALLER.
* THIS WILL THROW ERRORS IF MIGRATIONS ALREADY EXIST IN THE TABLE, DO NOT CALL MORE THAN ONCE!
*
* @param string $path Path to migration data files
* @param bool $recursive Set to true to also load data files from subdirectories
* @return null
*/
public function populate_migrations_from_directory($path, $recursive = true)
{
$existing_migrations = $this->migrations;
$this->migrations = array();
$this->load_migrations($path, true, $recursive);
foreach ($this->migrations as $name)
{
if ($this->migration_state($name) === false)
{
$state = array(
'migration_depends_on' => $name::depends_on(),
'migration_schema_done' => true,
'migration_data_done' => true,
'migration_data_state' => '',
'migration_start_time' => time(),
'migration_end_time' => time(),
);
$this->insert_migration($name, $state);
}
}
$this->migrations = $existing_migrations;
}
/**
* Load migration data files from a directory
*
* Migration data files loaded with this function MUST contain
* ONLY ONE class in them (or an exception will be thrown).
*
* @param string $path Path to migration data files
* @param bool $check_fulfillable If TRUE (default), we will check
* if all of the migrations are fulfillable after loading them.
* If FALSE, we will not check. You SHOULD check at least once
* to prevent errors (if including multiple directories, check
* with the last call to prevent throwing errors unnecessarily).
* @param bool $recursive Set to true to also load data files from subdirectories
* @return array Array of migration names
*/
public function load_migrations($path, $check_fulfillable = true, $recursive = true)
{
if (!is_dir($path))
{
throw new phpbb_db_migration_exception('DIRECTORY INVALID', $path);
}
$handle = opendir($path);
while (($file = readdir($handle)) !== false)
{
if ($file == '.' || $file == '..')
{
continue;
}
// Recursion through subdirectories
if (is_dir($path . $file) && $recursive)
{
$this->load_migrations($path . $file . '/', $check_fulfillable, $recursive);
}
if (strpos($file, '_') !== 0 && strrpos($file, '.' . $this->php_ext) === (strlen($file) - strlen($this->php_ext) - 1))
{
// We try to find what class existed by comparing the classes declared before and after including the file.
$declared_classes = get_declared_classes();
include ($path . $file);
$added_classes = array_diff(get_declared_classes(), $declared_classes);
if (
// If two classes have been added and phpbb_db_migration is one of them, we've only added one real migration
!(sizeof($added_classes) == 2 && in_array('phpbb_db_migration', $added_classes)) &&
// Otherwise there should only be one class added
sizeof($added_classes) != 1
)
{
throw new phpbb_db_migration_exception('MIGRATION DATA FILE INVALID', $path . $file);
}
$name = array_pop($added_classes);
if (!in_array($name, $this->migrations))
{
$this->migrations[] = $name;
}
}
}
if ($check_fulfillable)
{
foreach ($this->migrations as $name)
{
$unfulfillable = $this->unfulfillable($name);
if ($unfulfillable !== false)
{
throw new phpbb_db_migration_exception('MIGRATION_NOT_FULFILLABLE', $name, $unfulfillable);
}
}
}
return $this->migrations;
}
/**
* Runs a single update step from the next migration to be applied.
*
* The update step can either be a schema or a (partial) data update. To
* check if update() needs to be called again use the finished() method.
*
* @return null
*/
public function update()
{
foreach ($this->migrations as $name)
{
if (!isset($this->migration_state[$name]) ||
!$this->migration_state[$name]['migration_schema_done'] ||
!$this->migration_state[$name]['migration_data_done'])
{
if (!$this->try_apply($name))
{
continue;
}
else
{
return;
}
}
}
}
/**
* Attempts to apply a step of the given migration or one of its dependencies
*
* @param string The class name of the migration
* @return bool Whether any update step was successfully run
*/
protected function try_apply($name)
{
if (!class_exists($name))
{
return false;
}
$migration = $this->get_migration($name);
$state = (isset($this->migration_state[$name])) ?
$this->migration_state[$name] :
array(
'migration_depends_on' => $migration->depends_on(),
'migration_schema_done' => false,
'migration_data_done' => false,
'migration_data_state' => '',
'migration_start_time' => 0,
'migration_end_time' => 0,
);
foreach ($state['migration_depends_on'] as $depend)
{
if (!isset($this->migration_state[$depend]) ||
!$this->migration_state[$depend]['migration_schema_done'] ||
!$this->migration_state[$depend]['migration_data_done'])
{
return $this->try_apply($depend);
}
}
$this->last_run_migration = array(
'name' => $name,
'class' => $migration,
);
if ($migration->effectively_installed())
{
$state = array(
'migration_depends_on' => $migration->depends_on(),
'migration_schema_done' => true,
'migration_data_done' => true,
'migration_data_state' => '',
'migration_start_time' => 0,
'migration_end_time' => 0,
);
}
else
{
if (!isset($this->migration_state[$name]))
{
$state['migration_start_time'] = time();
$this->insert_migration($name, $state);
}
}
if (!$state['migration_schema_done'])
{
$this->apply_schema_changes($migration->update_schema());
$state['migration_schema_done'] = true;
}
else if (!$state['migration_data_done'])
{
try
{
$result = $this->process_data_step($migration->update_data(), $state['migration_data_state']);
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true);
$state['migration_end_time'] = ($result === true) ? time() : 0;
}
catch (phpbb_db_migration_exception $e)
{
// Revert the schema changes
$this->revert($name);
// Rethrow exception
throw $e;
}
}
$insert = $state;
$insert['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'UPDATE ' . $this->migrations_table . '
SET ' . $this->db->sql_build_array('UPDATE', $insert) . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$this->migration_state[$name] = $state;
return true;
}
/**
* Runs a single revert step from the last migration installed
*
* YOU MUST ADD/SET ALL MIGRATIONS THAT COULD BE DEPENDENT ON THE MIGRATION TO REVERT TO BEFORE CALLING THIS METHOD!
* The revert step can either be a schema or a (partial) data revert. To
* check if revert() needs to be called again use the migration_state() method.
*
* @param string $migration String migration name to revert (including any that depend on this migration)
* @return null
*/
public function revert($migration)
{
if (!isset($this->migration_state[$migration]))
{
// Not installed
return;
}
foreach ($this->migration_state as $name => $state)
{
if (!empty($state['migration_depends_on']) && in_array($migration, $state['migration_depends_on']))
{
$this->revert($name);
}
}
$this->try_revert($migration);
}
/**
* Attempts to revert a step of the given migration or one of its dependencies
*
* @param string The class name of the migration
* @return bool Whether any update step was successfully run
*/
protected function try_revert($name)
{
if (!class_exists($name))
{
return false;
}
$migration = $this->get_migration($name);
$state = $this->migration_state[$name];
$this->last_run_migration = array(
'name' => $name,
'class' => $migration,
);
if ($state['migration_data_done'])
{
if ($state['migration_data_state'] !== 'revert_data')
{
$result = $this->process_data_step($migration->update_data(), $state['migration_data_state'], true);
$state['migration_data_state'] = ($result === true) ? 'revert_data' : $result;
}
else
{
$result = $this->process_data_step($migration->revert_data(), $state['migration_data_state'], false);
$state['migration_data_state'] = ($result === true) ? '' : $result;
$state['migration_data_done'] = ($result === true) ? false : true;
}
$insert = $state;
$insert['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'UPDATE ' . $this->migrations_table . '
SET ' . $this->db->sql_build_array('UPDATE', $insert) . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
$this->migration_state[$name] = $state;
}
else
{
$this->apply_schema_changes($migration->revert_schema());
$sql = 'DELETE FROM ' . $this->migrations_table . "
WHERE migration_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
unset($this->migration_state[$name]);
}
return true;
}
/**
* Apply schema changes from a migration
*
* Just calls db_tools->perform_schema_changes
*
* @param array $schema_changes from migration
*/
protected function apply_schema_changes($schema_changes)
{
$this->db_tools->perform_schema_changes($schema_changes);
}
/**
* Process the data step of the migration
*
* @param array $steps The steps to run
* @param bool|string $state Current state of the migration
* @param bool $revert true to revert a data step
* @return bool|string migration state. True if completed, serialized array if not finished
*/
protected function process_data_step($steps, $state, $revert = false)
{
$state = ($state) ? unserialize($state) : false;
foreach ($steps as $step_identifier => $step)
{
$last_result = false;
if ($state)
{
// Continue until we reach the step that matches the last step called
if ($state['step'] != $step_identifier)
{
continue;
}
// We send the result from last time to the callable function
$last_result = $state['result'];
// Set state to false since we reached the point we were at
$state = false;
}
try
{
// Result will be null or true if everything completed correctly
$result = $this->run_step($step, $last_result, $revert);
if ($result !== null && $result !== true)
{
return serialize(array(
'result' => $result,
'step' => $step_identifier,
));
}
}
catch (phpbb_db_migration_exception $e)
{
// We should try rolling back here
foreach ($steps as $reverse_step_identifier => $reverse_step)
{
// If we've reached the current step we can break because we reversed everything that was run
if ($reverse_step_identifier == $step_identifier)
{
break;
}
// Reverse the step that was run
$result = $this->run_step($reverse_step, false, !$revert);
}
// rethrow the exception
throw $e;
}
}
return true;
}
/**
* Run a single step
*
* An exception should be thrown if an error occurs
*
* @param mixed $step Data step from migration
* @param mixed $last_result Result to pass to the callable (only for 'custom' method)
* @param bool $reverse False to install, True to attempt uninstallation by reversing the call
* @return null
*/
protected function run_step($step, $last_result = false, $reverse = false)
{
$callable_and_parameters = $this->get_callable_from_step($step, $last_result, $reverse);
if ($callable_and_parameters === false)
{
return;
}
$callable = $callable_and_parameters[0];
$parameters = $callable_and_parameters[1];
return call_user_func_array($callable, $parameters);
}
/**
* Get a callable statement from a data step
*
* @param array $step Data step from migration
* @param mixed $last_result Result to pass to the callable (only for 'custom' method)
* @param bool $reverse False to install, True to attempt uninstallation by reversing the call
* @return array Array with parameters for call_user_func_array(), 0 is the callable, 1 is parameters
*/
protected function get_callable_from_step(array $step, $last_result = false, $reverse = false)
{
$type = $step[0];
$parameters = $step[1];
$parts = explode('.', $type);
$class = $parts[0];
$method = false;
if (isset($parts[1]))
{
$method = $parts[1];
}
switch ($class)
{
case 'if':
if (!isset($parameters[0]))
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_CONDITION', $step);
}
if (!isset($parameters[1]))
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_MISSING_STEP', $step);
}
$condition = $parameters[0];
if (!$condition)
{
return false;
}
$step = $parameters[1];
return $this->get_callable_from_step($step);
break;
case 'custom':
if (!is_callable($parameters[0]))
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_CUSTOM_NOT_CALLABLE', $step);
}
return array(
$parameters[0],
array($last_result),
);
break;
default:
if (!$method)
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNKNOWN_TYPE', $step);
}
if (!isset($this->tools[$class]))
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_TOOL', $step);
}
if (!method_exists(get_class($this->tools[$class]), $method))
{
throw new phpbb_db_migration_exception('MIGRATION_INVALID_DATA_UNDEFINED_METHOD', $step);
}
// Attempt to reverse operations
if ($reverse)
{
array_unshift($parameters, $method);
return array(
array($this->tools[$class], 'reverse'),
$parameters,
);
}
return array(
array($this->tools[$class], $method),
$parameters,
);
break;
}
}
/**
* Insert migration row into the database
*
* @param string $name Name of the migration
* @param array $state
* @return null
*/
protected function insert_migration($name, $state)
{
$migration_row = $state;
$migration_row['migration_name'] = $name;
$migration_row['migration_depends_on'] = serialize($state['migration_depends_on']);
$sql = 'INSERT INTO ' . $this->migrations_table . '
' . $this->db->sql_build_array('INSERT', $migration_row);
$this->db->sql_query($sql);
$this->migration_state[$name] = $state;
}
/**
* Checks if a migration's dependencies can even theoretically be satisfied.
*
* @param string $name The class name of the migration
* @return bool|string False if fulfillable, string of missing migration name if unfulfillable
*/
public function unfulfillable($name)
{
if (isset($this->migration_state[$name]))
{
return false;
}
if (!class_exists($name))
{
return $name;
}
$migration = $this->get_migration($name);
$depends = $migration->depends_on();
foreach ($depends as $depend)
{
$unfulfillable = $this->unfulfillable($depend);
if ($unfulfillable !== false)
{
return $unfulfillable;
}
}
return false;
}
/**
* Checks whether all available, fulfillable migrations have been applied.
*
* @return bool Whether the migrations have been applied
*/
public function finished()
{
foreach ($this->migrations as $name)
{
if (!isset($this->migration_state[$name]))
{
// skip unfulfillable migrations, but fulfillables mean we
// are not finished yet
if ($this->unfulfillable($name) !== false)
{
continue;
}
return false;
}
$migration = $this->migration_state[$name];
if (!$migration['migration_schema_done'] || !$migration['migration_data_done'])
{
return false;
}
}
return true;
}
/**
* Gets a migration state (whether it is installed and to what extent)
*
* @param string $migration String migration name to check if it is installed
* @return bool|array False if the migration has not at all been installed, array
*/
public function migration_state($migration)
{
if (!isset($this->migration_state[$migration]))
{
return false;
}
return $this->migration_state[$migration];
}
/**
* Helper to get a migration
*
* @param string $name Name of the migration
* @return phpbb_db_migration
*/
protected function get_migration($name)
{
return new $name($this->config, $this->db, $this->db_tools, $this->phpbb_root_path, $this->php_ext, $this->table_prefix);
}
}

View file

@ -42,9 +42,10 @@ class phpbb_di_extension_config extends Extension
{ {
require($this->config_file); require($this->config_file);
$container->setParameter('core.adm_relative_path', (isset($phpbb_adm_relative_path) ? $phpbb_adm_relative_path : 'adm/'));
$container->setParameter('core.table_prefix', $table_prefix); $container->setParameter('core.table_prefix', $table_prefix);
$container->setParameter('cache.driver.class', $this->fix_acm_type($acm_type)); $container->setParameter('cache.driver.class', $this->convert_30_acm_type($acm_type));
$container->setParameter('dbal.driver.class', 'dbal_'.$dbms); $container->setParameter('dbal.driver.class', phpbb_convert_30_dbms_to_31($dbms));
$container->setParameter('dbal.dbhost', $dbhost); $container->setParameter('dbal.dbhost', $dbhost);
$container->setParameter('dbal.dbuser', $dbuser); $container->setParameter('dbal.dbuser', $dbuser);
$container->setParameter('dbal.dbpasswd', $dbpasswd); $container->setParameter('dbal.dbpasswd', $dbpasswd);
@ -66,12 +67,12 @@ class phpbb_di_extension_config extends Extension
} }
/** /**
* Convert old (3.0) values to 3.1 class names * Convert 3.0 ACM type to 3.1 cache driver class name
* *
* @param style $acm_type ACM type * @param string $acm_type ACM type
* @return ACM type class * @return cache driver class
*/ */
protected function fix_acm_type($acm_type) protected function convert_30_acm_type($acm_type)
{ {
if (preg_match('#^[a-z]+$#', $acm_type)) if (preg_match('#^[a-z]+$#', $acm_type))
{ {

View file

@ -43,7 +43,7 @@ class phpbb_di_service_collection extends ArrayObject
public function add($name) public function add($name)
{ {
$task = $this->container->get($name); $task = $this->container->get($name);
$task->set_name($name);
$this->offsetSet($name, $task); $this->offsetSet($name, $task);
} }
} }

View file

@ -15,6 +15,8 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* A base class for extensions without custom enable/disable/purge code. * A base class for extensions without custom enable/disable/purge code.
* *
@ -22,6 +24,19 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_extension_base implements phpbb_extension_interface class phpbb_extension_base implements phpbb_extension_interface
{ {
/** @var ContainerInterface */
protected $container;
/**
* Constructor
*
* @param ContainerInterface $container Container object
*/
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
/** /**
* Single enable step that does nothing * Single enable step that does nothing
* *

View file

@ -45,7 +45,9 @@ interface phpbb_extension_interface
* *
* @param mixed $old_state The return value of the previous call * @param mixed $old_state The return value of the previous call
* of this method, or false on the first call * of this method, or false on the first call
* @return null * @return mixed Returns false after last step, otherwise
* temporary state which is passed as an
* argument to the next step
*/ */
public function disable_step($old_state); public function disable_step($old_state);

View file

@ -15,6 +15,8 @@ if (!defined('IN_PHPBB'))
exit; exit;
} }
use Symfony\Component\DependencyInjection\ContainerInterface;
/** /**
* The extension manager provides means to activate/deactivate extensions. * The extension manager provides means to activate/deactivate extensions.
* *
@ -22,8 +24,12 @@ if (!defined('IN_PHPBB'))
*/ */
class phpbb_extension_manager class phpbb_extension_manager
{ {
/** @var ContainerInterface */
protected $container;
protected $db; protected $db;
protected $config; protected $config;
protected $migrator;
protected $cache; protected $cache;
protected $php_ext; protected $php_ext;
protected $extensions; protected $extensions;
@ -34,7 +40,8 @@ class phpbb_extension_manager
/** /**
* Creates a manager and loads information from database * Creates a manager and loads information from database
* *
* @param dbal $db A database connection * @param ContainerInterface $container A container
* @param phpbb_db_driver $db A database connection
* @param phpbb_config $config phpbb_config * @param phpbb_config $config phpbb_config
* @param string $extension_table The name of the table holding extensions * @param string $extension_table The name of the table holding extensions
* @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $phpbb_root_path Path to the phpbb includes directory.
@ -42,11 +49,13 @@ class phpbb_extension_manager
* @param phpbb_cache_driver_interface $cache A cache instance or null * @param phpbb_cache_driver_interface $cache A cache instance or null
* @param string $cache_name The name of the cache variable, defaults to _ext * @param string $cache_name The name of the cache variable, defaults to _ext
*/ */
public function __construct(dbal $db, phpbb_config $config, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext') public function __construct(ContainerInterface $container, phpbb_db_driver $db, phpbb_config $config, phpbb_db_migrator $migrator, $extension_table, $phpbb_root_path, $php_ext = '.php', phpbb_cache_driver_interface $cache = null, $cache_name = '_ext')
{ {
$this->container = $container;
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->db = $db; $this->db = $db;
$this->config = $config; $this->config = $config;
$this->migrator = $migrator;
$this->cache = $cache; $this->cache = $cache;
$this->php_ext = $php_ext; $this->php_ext = $php_ext;
$this->extension_table = $extension_table; $this->extension_table = $extension_table;
@ -126,11 +135,11 @@ class phpbb_extension_manager
if (class_exists($extension_class_name)) if (class_exists($extension_class_name))
{ {
return new $extension_class_name; return new $extension_class_name($this->container);
} }
else else
{ {
return new phpbb_extension_base; return new phpbb_extension_base($this->container);
} }
} }
@ -166,6 +175,12 @@ class phpbb_extension_manager
$old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false; $old_state = (isset($this->extensions[$name]['ext_state'])) ? unserialize($this->extensions[$name]['ext_state']) : false;
// Returns false if not completed
if (!$this->handle_migrations($name, 'enable'))
{
return true;
}
$extension = $this->get_extension($name); $extension = $this->get_extension($name);
$state = $extension->enable_step($old_state); $state = $extension->enable_step($old_state);
@ -317,6 +332,12 @@ class phpbb_extension_manager
$old_state = unserialize($this->extensions[$name]['ext_state']); $old_state = unserialize($this->extensions[$name]['ext_state']);
// Returns false if not completed
if (!$this->handle_migrations($name, 'purge'))
{
return true;
}
$extension = $this->get_extension($name); $extension = $this->get_extension($name);
$state = $extension->purge_step($old_state); $state = $extension->purge_step($old_state);
@ -384,7 +405,7 @@ class phpbb_extension_manager
} }
$iterator = new RecursiveIteratorIterator( $iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/'), new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/', FilesystemIterator::NEW_CURRENT_AND_KEY | FilesystemIterator::FOLLOW_SYMLINKS),
RecursiveIteratorIterator::SELF_FIRST); RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file_info) foreach ($iterator as $file_info)
{ {
@ -490,4 +511,58 @@ class phpbb_extension_manager
{ {
return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder'); return new phpbb_extension_finder($this, $this->phpbb_root_path, $this->cache, $this->php_ext, $this->cache_name . '_finder');
} }
/**
* Handle installing/reverting migrations
*
* @param string $extension_name Name of the extension
* @param string $mode enable or purge
* @return bool True if completed, False if not completed
*/
protected function handle_migrations($extension_name, $mode)
{
$migrations_path = $this->phpbb_root_path . $this->get_extension_path($extension_name) . 'migrations/';
if (!file_exists($migrations_path) || !is_dir($migrations_path))
{
return true;
}
$migrations = $this->migrator->load_migrations($migrations_path);
// What is a safe limit of execution time? Half the max execution time should be safe.
$safe_time_limit = (ini_get('max_execution_time') / 2);
$start_time = time();
if ($mode == 'enable')
{
while (!$this->migrator->finished())
{
$this->migrator->update();
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
if ((time() - $start_time) >= $safe_time_limit)
{
return false;
}
}
}
else if ($mode == 'purge')
{
foreach ($migrations as $migration)
{
while ($this->migrator->migration_state($migration) !== false)
{
$this->migrator->revert($migration);
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
if ((time() - $start_time) >= $safe_time_limit)
{
return false;
}
}
}
}
return true;
}
} }

View file

@ -34,12 +34,12 @@ class phpbb_extension_metadata_manager
/** /**
* Creates the metadata manager * Creates the metadata manager
* *
* @param dbal $db A database connection * @param phpbb_db_driver $db A database connection
* @param string $extension_manager An instance of the phpbb extension manager * @param string $extension_manager An instance of the phpbb extension manager
* @param string $phpbb_root_path Path to the phpbb includes directory. * @param string $phpbb_root_path Path to the phpbb includes directory.
* @param string $phpEx php file extension * @param string $phpEx php file extension
*/ */
public function __construct($ext_name, dbal $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config) public function __construct($ext_name, phpbb_db_driver $db, phpbb_extension_manager $extension_manager, $phpbb_root_path, $phpEx = '.php', phpbb_template $template, phpbb_config $config)
{ {
$this->phpbb_root_path = $phpbb_root_path; $this->phpbb_root_path = $phpbb_root_path;
$this->db = $db; $this->db = $db;

View file

@ -97,7 +97,18 @@ function request_var($var_name, $default, $multibyte = false, $cookie = false, $
} }
/** /**
* Set config value. Creates missing config entry. * Sets a configuration option's value.
*
* Please note that this function does not update the is_dynamic value for
* an already existing config option.
*
* @param string $config_name The configuration option's name
* @param string $config_value New configuration value
* @param bool $is_dynamic Whether this variable should be cached (false) or
* if it changes too frequently (true) to be
* efficiently cached.
*
* @return null
* *
* @deprecated * @deprecated
*/ */
@ -119,7 +130,15 @@ function set_config($config_name, $config_value, $is_dynamic = false, phpbb_conf
} }
/** /**
* Set dynamic config value with arithmetic operation. * Increments an integer config value directly in the database.
*
* @param string $config_name The configuration option's name
* @param int $increment Amount to increment by
* @param bool $is_dynamic Whether this variable should be cached (false) or
* if it changes too frequently (true) to be
* efficiently cached.
*
* @return null
* *
* @deprecated * @deprecated
*/ */
@ -4893,13 +4912,108 @@ function phpbb_http_login($param)
trigger_error('NOT_AUTHORISED'); trigger_error('NOT_AUTHORISED');
} }
/**
* Escapes and quotes a string for use as an HTML/XML attribute value.
*
* This is a port of Python xml.sax.saxutils quoteattr.
*
* The function will attempt to choose a quote character in such a way as to
* avoid escaping quotes in the string. If this is not possible the string will
* be wrapped in double quotes and double quotes will be escaped.
*
* @param string $data The string to be escaped
* @param array $entities Associative array of additional entities to be escaped
* @return string Escaped and quoted string
*/
function phpbb_quoteattr($data, $entities = null)
{
$data = str_replace('&', '&amp;', $data);
$data = str_replace('>', '&gt;', $data);
$data = str_replace('<', '&lt;', $data);
$data = str_replace("\n", '&#10;', $data);
$data = str_replace("\r", '&#13;', $data);
$data = str_replace("\t", '&#9;', $data);
if (!empty($entities))
{
$data = str_replace(array_keys($entities), array_values($entities), $data);
}
if (strpos($data, '"') !== false)
{
if (strpos($data, "'") !== false)
{
$data = '"' . str_replace('"', '&quot;', $data) . '"';
}
else
{
$data = "'" . $data . "'";
}
}
else
{
$data = '"' . $data . '"';
}
return $data;
}
/**
* Converts query string (GET) parameters in request into hidden fields.
*
* Useful for forwarding GET parameters when submitting forms with GET method.
*
* It is possible to omit some of the GET parameters, which is useful if
* they are specified in the form being submitted.
*
* sid is always omitted.
*
* @param phpbb_request $request Request object
* @param array $exclude A list of variable names that should not be forwarded
* @return string HTML with hidden fields
*/
function phpbb_build_hidden_fields_for_query_params($request, $exclude = null)
{
$names = $request->variable_names(phpbb_request_interface::GET);
$hidden = '';
foreach ($names as $name)
{
// Sessions are dealt with elsewhere, omit sid always
if ($name == 'sid')
{
continue;
}
// Omit any additional parameters requested
if (!empty($exclude) && in_array($name, $exclude))
{
continue;
}
$escaped_name = phpbb_quoteattr($name);
// Note: we might retrieve the variable from POST or cookies
// here. To avoid exposing cookies, skip variables that are
// overwritten somewhere other than GET entirely.
$value = $request->variable($name, '', true);
$get_value = $request->variable($name, '', true, phpbb_request_interface::GET);
if ($value === $get_value)
{
$escaped_value = phpbb_quoteattr($value);
$hidden .= "<input type='hidden' name=$escaped_name value=$escaped_value />";
}
}
return $hidden;
}
/** /**
* Generate page header * Generate page header
*/ */
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{ {
global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
global $phpbb_dispatcher; global $phpbb_dispatcher, $request;
if (defined('HEADER_INC')) if (defined('HEADER_INC'))
{ {
@ -5088,6 +5202,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
$timezone_name = $user->lang['timezones'][$timezone_name]; $timezone_name = $user->lang['timezones'][$timezone_name];
} }
$hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f'));
// The following assigns all _common_ variables that may be used at any point in a template. // The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array( $template->assign_vars(array(
'SITENAME' => $config['sitename'], 'SITENAME' => $config['sitename'],
@ -5102,6 +5218,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'RECORD_USERS' => $l_online_record, 'RECORD_USERS' => $l_online_record,
'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text, 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text,
'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread, 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox,
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],
@ -5241,7 +5358,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
function page_footer($run_cron = true, $display_template = true, $exit_handler = true) function page_footer($run_cron = true, $display_template = true, $exit_handler = true)
{ {
global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx; global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx;
global $request, $phpbb_dispatcher; global $request, $phpbb_dispatcher, $phpbb_admin_path;
// A listener can set this variable to `true` when it overrides this function // A listener can set this variable to `true` when it overrides this function
$page_footer_override = false; $page_footer_override = false;
@ -5297,7 +5414,7 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler =
'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '', 'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group'), 'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>&reg; Forum Software &copy; phpBB Group'),
'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_root_path}adm/index.$phpEx", false, true, $user->session_id) : '') 'U_ACP' => ($auth->acl_get('a_') && !empty($user->data['is_registered'])) ? append_sid("{$phpbb_admin_path}index.$phpEx", false, true, $user->session_id) : '')
); );
// Call cron-type script // Call cron-type script
@ -5451,6 +5568,52 @@ function phpbb_to_numeric($input)
return ($input > PHP_INT_MAX) ? (float) $input : (int) $input; return ($input > PHP_INT_MAX) ? (float) $input : (int) $input;
} }
/**
* Convert either 3.0 dbms or 3.1 db driver class name to 3.1 db driver class name.
*
* If $dbms is a valid 3.1 db driver class name, returns it unchanged.
* Otherwise prepends phpbb_db_driver_ to the dbms to convert a 3.0 dbms
* to 3.1 db driver class name.
*
* @param string $dbms dbms parameter
* @return db driver class
*/
function phpbb_convert_30_dbms_to_31($dbms)
{
// Note: this check is done first because mysqli extension
// supplies a mysqli class, and class_exists($dbms) would return
// true for mysqli class.
// However, per the docblock any valid 3.1 driver name should be
// recognized by this function, and have priority over 3.0 dbms.
if (class_exists('phpbb_db_driver_' . $dbms))
{
return 'phpbb_db_driver_' . $dbms;
}
if (class_exists($dbms))
{
// Additionally we could check that $dbms extends phpbb_db_driver.
// http://php.net/manual/en/class.reflectionclass.php
// Beware of possible performance issues:
// http://stackoverflow.com/questions/294582/php-5-reflection-api-performance
// We could check for interface implementation in all paths or
// only when we do not prepend phpbb_db_driver_.
/*
$reflection = new \ReflectionClass($dbms);
if ($reflection->isSubclassOf('phpbb_db_driver'))
{
return $dbms;
}
*/
return $dbms;
}
throw new \RuntimeException("You have specified an invalid dbms driver: $dbms");
}
/** /**
* Create a Symfony Request object from phpbb_request object * Create a Symfony Request object from phpbb_request object
* *

View file

@ -82,16 +82,16 @@ function adm_page_header($page_title)
'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/", 'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/", 'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/",
'ICON_MOVE_UP' => '<img src="' . $phpbb_admin_path . 'images/icon_up.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', 'ICON_MOVE_UP' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />',
'ICON_MOVE_UP_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_up_disabled.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />', 'ICON_MOVE_UP_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up_disabled.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />',
'ICON_MOVE_DOWN' => '<img src="' . $phpbb_admin_path . 'images/icon_down.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', 'ICON_MOVE_DOWN' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />',
'ICON_MOVE_DOWN_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_down_disabled.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />', 'ICON_MOVE_DOWN_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down_disabled.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />',
'ICON_EDIT' => '<img src="' . $phpbb_admin_path . 'images/icon_edit.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', 'ICON_EDIT' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />',
'ICON_EDIT_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_edit_disabled.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />', 'ICON_EDIT_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit_disabled.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />',
'ICON_DELETE' => '<img src="' . $phpbb_admin_path . 'images/icon_delete.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', 'ICON_DELETE' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />',
'ICON_DELETE_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_delete_disabled.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />', 'ICON_DELETE_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete_disabled.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />',
'ICON_SYNC' => '<img src="' . $phpbb_admin_path . 'images/icon_sync.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', 'ICON_SYNC' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />',
'ICON_SYNC_DISABLED' => '<img src="' . $phpbb_admin_path . 'images/icon_sync_disabled.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />', 'ICON_SYNC_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync_disabled.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />',
'S_USER_LANG' => $user->lang['USER_LANG'], 'S_USER_LANG' => $user->lang['USER_LANG'],
'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'], 'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
@ -443,6 +443,13 @@ function validate_config_vars($config_vars, &$cfg_array, &$error)
} }
break; break;
case 'email':
if (!preg_match('/^' . get_preg_expression('email') . '$/i', $cfg_array[$config_name]))
{
$error[] = $user->lang['EMAIL_INVALID_EMAIL'];
}
break;
// Absolute path // Absolute path
case 'script_path': case 'script_path':
if (!$cfg_array[$config_name]) if (!$cfg_array[$config_name])

View file

@ -2292,13 +2292,17 @@ function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_fr
} }
/** /**
* Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username * Cache moderators. Called whenever permissions are changed
* and group names must be carried through for the moderators table * via admin_permissions. Changes of usernames and group names
* must be carried through for the moderators table.
*
* @param phpbb_db_driver $db Database connection
* @param phpbb_cache_driver_interface Cache driver
* @param phpbb_auth $auth Authentication object
* @return null
*/ */
function cache_moderators() function phpbb_cache_moderators($db, $cache, $auth)
{ {
global $db, $cache, $auth, $phpbb_root_path, $phpEx;
// Remove cached sql results // Remove cached sql results
$cache->destroy('sql', MODERATOR_CACHE_TABLE); $cache->destroy('sql', MODERATOR_CACHE_TABLE);
@ -2468,6 +2472,20 @@ function cache_moderators()
$db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary); $db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary);
} }
/**
* Cache moderators. Called whenever permissions are changed
* via admin_permissions. Changes of usernames and group names
* must be carried through for the moderators table.
*
* @deprecated 3.1
* @return null
*/
function cache_moderators()
{
global $db, $cache, $auth;
return phpbb_cache_moderators($db, $cache, $auth);
}
/** /**
* View log * View log
* If $log_count is set to false, we will skip counting all entries in the database. * If $log_count is set to false, we will skip counting all entries in the database.
@ -2740,12 +2758,16 @@ function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id
} }
/** /**
* Update foes - remove moderators and administrators from foe lists... * Removes moderators and administrators from foe lists.
*
* @param phpbb_db_driver $db Database connection
* @param phpbb_auth $auth Authentication object
* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore
* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore
* @return null
*/ */
function update_foes($group_id = false, $user_id = false) function phpbb_update_foes($db, $auth, $group_id = false, $user_id = false)
{ {
global $db, $auth;
// update foes for some user // update foes for some user
if (is_array($user_id) && sizeof($user_id)) if (is_array($user_id) && sizeof($user_id))
{ {
@ -2854,6 +2876,20 @@ function update_foes($group_id = false, $user_id = false)
unset($perms); unset($perms);
} }
/**
* Removes moderators and administrators from foe lists.
*
* @deprecated 3.1
* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore
* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore
* @return null
*/
function update_foes($group_id = false, $user_id = false)
{
global $db, $auth;
return phpbb_update_foes($db, $auth, $group_id, $user_id);
}
/** /**
* Lists inactive users * Lists inactive users
*/ */

View file

@ -105,6 +105,15 @@ function phpbb_create_compiled_container(array $extensions, array $passes, $phpb
return $container; return $container;
} }
/**
* Create a compiled and dumped ContainerBuilder object
*
* @param array $extensions Array of Container extension objects
* @param array $passes Array of Compiler Pass objects
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_root_path, $php_ext) function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_root_path, $php_ext)
{ {
// Check for our cached container; if it exists, use it // Check for our cached container; if it exists, use it
@ -129,12 +138,60 @@ function phpbb_create_dumped_container(array $extensions, array $passes, $phpbb_
return $container; return $container;
} }
/**
* Create an environment-specific ContainerBuilder object
*
* If debug is enabled, the container is re-compiled every time.
* This ensures that the latest changes will always be reflected
* during development.
*
* Otherwise it will get the existing dumped container and use
* that one instead.
*
* @param array $extensions Array of Container extension objects
* @param array $passes Array of Compiler Pass objects
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP Extension
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_dumped_container_unless_debug(array $extensions, array $passes, $phpbb_root_path, $php_ext) function phpbb_create_dumped_container_unless_debug(array $extensions, array $passes, $phpbb_root_path, $php_ext)
{ {
$container_factory = defined('DEBUG') ? 'phpbb_create_compiled_container' : 'phpbb_create_dumped_container'; $container_factory = defined('DEBUG') ? 'phpbb_create_compiled_container' : 'phpbb_create_dumped_container';
return $container_factory($extensions, $passes, $phpbb_root_path, $php_ext); return $container_factory($extensions, $passes, $phpbb_root_path, $php_ext);
} }
/**
* Create a default ContainerBuilder object
*
* Contains the default configuration of the phpBB container.
*
* @param array $extensions Array of Container extension objects
* @param array $passes Array of Compiler Pass objects
* @return ContainerBuilder object (compiled)
*/
function phpbb_create_default_container($phpbb_root_path, $php_ext)
{
return phpbb_create_dumped_container_unless_debug(
array(
new phpbb_di_extension_config($phpbb_root_path . 'config.' . $php_ext),
new phpbb_di_extension_core($phpbb_root_path),
),
array(
new phpbb_di_pass_collection_pass(),
new phpbb_di_pass_kernel_pass(),
),
$phpbb_root_path,
$php_ext
);
}
/**
* Get the filename under which the dumped container will be stored.
*
* @param string $phpbb_root_path Root path
* @param string $php_ext PHP Extension
* @return Path for dumped container
*/
function phpbb_container_filename($phpbb_root_path, $php_ext) function phpbb_container_filename($phpbb_root_path, $php_ext)
{ {
$filename = str_replace(array('/', '.'), array('slash', 'dot'), $phpbb_root_path); $filename = str_replace(array('/', '.'), array('slash', 'dot'), $phpbb_root_path);

View file

@ -0,0 +1,206 @@
<?php
/**
*
* @package phpBB3
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* Updates rows in given table from a set of values to a new value.
* If this results in rows violating uniqueness constraints, the duplicate
* rows are eliminated.
*
* The only supported table is bookmarks.
*
* @param phpbb_db_driver $db Database object
* @param string $table Table on which to perform the update
* @param string $column Column whose values to change
* @param array $from_values An array of values that should be changed
* @param int $to_value The new value
* @return null
*/
function phpbb_update_rows_avoiding_duplicates(phpbb_db_driver $db, $table, $column, $from_values, $to_value)
{
$sql = "SELECT $column, user_id
FROM $table
WHERE " . $db->sql_in_set($column, $from_values);
$result = $db->sql_query($sql);
$old_user_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$old_user_ids[$row[$column]][] = (int) $row['user_id'];
}
$db->sql_freeresult($result);
$sql = "SELECT $column, user_id
FROM $table
WHERE $column = " . (int) $to_value;
$result = $db->sql_query($sql);
$new_user_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$new_user_ids[$row[$column]][] = (int) $row['user_id'];
}
$db->sql_freeresult($result);
$queries = array();
foreach ($from_values as $from_value)
{
if (!isset($old_user_ids[$from_value]))
{
continue;
}
if (empty($new_user_ids))
{
$sql = "UPDATE $table
SET $column = " . (int) $to_value . "
WHERE $column = '" . $db->sql_escape($from_value) . "'";
$queries[] = $sql;
}
else
{
$different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]);
if (!empty($different_user_ids))
{
$sql = "UPDATE $table
SET $column = " . (int) $to_value . "
WHERE $column = '" . $db->sql_escape($from_value) . "'
AND " . $db->sql_in_set('user_id', $different_user_ids);
$queries[] = $sql;
}
}
}
if (!empty($queries))
{
$db->sql_transaction('begin');
foreach ($queries as $sql)
{
$db->sql_query($sql);
}
$sql = "DELETE FROM $table
WHERE " . $db->sql_in_set($column, $from_values);
$db->sql_query($sql);
$db->sql_transaction('commit');
}
}
/**
* Updates rows in given table from a set of values to a new value.
* If this results in rows violating uniqueness constraints, the duplicate
* rows are merged respecting notify_status (0 takes precedence over 1).
*
* The only supported table is topics_watch.
*
* @param phpbb_db_driver $db Database object
* @param string $table Table on which to perform the update
* @param string $column Column whose values to change
* @param array $from_values An array of values that should be changed
* @param int $to_value The new value
* @return null
*/
function phpbb_update_rows_avoiding_duplicates_notify_status(phpbb_db_driver $db, $table, $column, $from_values, $to_value)
{
$sql = "SELECT $column, user_id, notify_status
FROM $table
WHERE " . $db->sql_in_set($column, $from_values);
$result = $db->sql_query($sql);
$old_user_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id'];
}
$db->sql_freeresult($result);
$sql = "SELECT $column, user_id
FROM $table
WHERE $column = " . (int) $to_value;
$result = $db->sql_query($sql);
$new_user_ids = array();
while ($row = $db->sql_fetchrow($result))
{
$new_user_ids[$row[$column]][] = (int) $row['user_id'];
}
$db->sql_freeresult($result);
$queries = array();
$extra_updates = array(
0 => 'notify_status = 0',
1 => '',
);
foreach ($from_values as $from_value)
{
foreach ($extra_updates as $notify_status => $extra_update)
{
if (!isset($old_user_ids[$notify_status][$from_value]))
{
continue;
}
if (empty($new_user_ids))
{
$sql = "UPDATE $table
SET $column = " . (int) $to_value . "
WHERE $column = '" . $db->sql_escape($from_value) . "'";
$queries[] = $sql;
}
else
{
$different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]);
if (!empty($different_user_ids))
{
$sql = "UPDATE $table
SET $column = " . (int) $to_value . "
WHERE $column = '" . $db->sql_escape($from_value) . "'
AND " . $db->sql_in_set('user_id', $different_user_ids);
$queries[] = $sql;
}
if ($extra_update)
{
$same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids);
if (!empty($same_user_ids))
{
$sql = "UPDATE $table
SET $extra_update
WHERE $column = '" . (int) $to_value . "'
AND " . $db->sql_in_set('user_id', $same_user_ids);
$queries[] = $sql;
}
}
}
}
}
if (!empty($queries))
{
$db->sql_transaction('begin');
foreach ($queries as $sql)
{
$db->sql_query($sql);
}
$sql = "DELETE FROM $table
WHERE " . $db->sql_in_set($column, $from_values);
$db->sql_query($sql);
$db->sql_transaction('commit');
}
}

View file

@ -61,6 +61,20 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
{ {
markread('all', false, false, request_var('mark_time', 0)); markread('all', false, false, request_var('mark_time', 0));
if ($request->is_ajax())
{
// Tell the ajax script what language vars and URL need to be replaced
$data = array(
'NO_UNREAD_POSTS' => $user->lang['NO_UNREAD_POSTS'],
'UNREAD_POSTS' => $user->lang['UNREAD_POSTS'],
'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}index.$phpEx", 'hash=' . generate_link_hash('global') . '&mark=forums&mark_time=' . time()) : '',
'MESSAGE_TITLE' => $user->lang['INFORMATION'],
'MESSAGE_TEXT' => $user->lang['FORUMS_MARKED']
);
$json_response = new phpbb_json_response();
$json_response->send($data);
}
trigger_error( trigger_error(
$user->lang['FORUMS_MARKED'] . '<br /><br />' . $user->lang['FORUMS_MARKED'] . '<br /><br />' .
sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>') sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect . '">', '</a>')
@ -313,6 +327,20 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
$message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>'); $message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
meta_refresh(3, $redirect); meta_refresh(3, $redirect);
if ($request->is_ajax())
{
// Tell the ajax script what language vars and URL need to be replaced
$data = array(
'NO_UNREAD_POSTS' => $user->lang['NO_UNREAD_POSTS'],
'UNREAD_POSTS' => $user->lang['UNREAD_POSTS'],
'U_MARK_FORUMS' => ($user->data['is_registered'] || $config['load_anon_lastread']) ? append_sid("{$phpbb_root_path}viewforum.$phpEx", 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums&mark_time=' . time()) : '',
'MESSAGE_TITLE' => $user->lang['INFORMATION'],
'MESSAGE_TEXT' => $user->lang['FORUMS_MARKED']
);
$json_response = new phpbb_json_response();
$json_response->send($data);
}
trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message);
} }
else else

View file

@ -596,7 +596,7 @@ function phpbb_parse_range_request($request_array, $filesize)
/** /**
* Increments the download count of all provided attachments * Increments the download count of all provided attachments
* *
* @param dbal $db The database object * @param phpbb_db_driver $db The database object
* @param array|int $ids The attach_id of each attachment * @param array|int $ids The attach_id of each attachment
* *
* @return null * @return null
@ -617,7 +617,7 @@ function phpbb_increment_downloads($db, $ids)
/** /**
* Handles authentication when downloading attachments from a post or topic * Handles authentication when downloading attachments from a post or topic
* *
* @param dbal $db The database object * @param phpbb_db_driver $db The database object
* @param phpbb_auth $auth The authentication object * @param phpbb_auth $auth The authentication object
* @param int $topic_id The id of the topic that we are downloading from * @param int $topic_id The id of the topic that we are downloading from
* *
@ -651,7 +651,7 @@ function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
/** /**
* Handles authentication when downloading attachments from PMs * Handles authentication when downloading attachments from PMs
* *
* @param dbal $db The database object * @param phpbb_db_driver $db The database object
* @param phpbb_auth $auth The authentication object * @param phpbb_auth $auth The authentication object
* @param int $user_id The user id * @param int $user_id The user id
* @param int $msg_id The id of the PM that we are downloading from * @param int $msg_id The id of the PM that we are downloading from
@ -678,7 +678,7 @@ function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
/** /**
* Checks whether a user can download from a particular PM * Checks whether a user can download from a particular PM
* *
* @param dbal $db The database object * @param phpbb_db_driver $db The database object
* @param int $user_id The user id * @param int $user_id The user id
* @param int $msg_id The id of the PM that we are downloading from * @param int $msg_id The id of the PM that we are downloading from
* *

View file

@ -28,16 +28,18 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'firebird', 'SCHEMA' => 'firebird',
'MODULE' => 'interbase', 'MODULE' => 'interbase',
'DELIM' => ';;', 'DELIM' => ';;',
'DRIVER' => 'firebird', 'DRIVER' => 'phpbb_db_driver_firebird',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => false, '2.0.x' => false,
), ),
// Note: php 5.5 alpha 2 deprecated mysql.
// Keep mysqli before mysql in this list.
'mysqli' => array( 'mysqli' => array(
'LABEL' => 'MySQL with MySQLi Extension', 'LABEL' => 'MySQL with MySQLi Extension',
'SCHEMA' => 'mysql_41', 'SCHEMA' => 'mysql_41',
'MODULE' => 'mysqli', 'MODULE' => 'mysqli',
'DELIM' => ';', 'DELIM' => ';',
'DRIVER' => 'mysqli', 'DRIVER' => 'phpbb_db_driver_mysqli',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => true, '2.0.x' => true,
), ),
@ -46,7 +48,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'mysql', 'SCHEMA' => 'mysql',
'MODULE' => 'mysql', 'MODULE' => 'mysql',
'DELIM' => ';', 'DELIM' => ';',
'DRIVER' => 'mysql', 'DRIVER' => 'phpbb_db_driver_mysql',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => true, '2.0.x' => true,
), ),
@ -55,7 +57,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'mssql', 'SCHEMA' => 'mssql',
'MODULE' => 'mssql', 'MODULE' => 'mssql',
'DELIM' => 'GO', 'DELIM' => 'GO',
'DRIVER' => 'mssql', 'DRIVER' => 'phpbb_db_driver_mssql',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => true, '2.0.x' => true,
), ),
@ -64,7 +66,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'mssql', 'SCHEMA' => 'mssql',
'MODULE' => 'odbc', 'MODULE' => 'odbc',
'DELIM' => 'GO', 'DELIM' => 'GO',
'DRIVER' => 'mssql_odbc', 'DRIVER' => 'phpbb_db_driver_mssql_odbc',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => true, '2.0.x' => true,
), ),
@ -73,7 +75,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'mssql', 'SCHEMA' => 'mssql',
'MODULE' => 'sqlsrv', 'MODULE' => 'sqlsrv',
'DELIM' => 'GO', 'DELIM' => 'GO',
'DRIVER' => 'mssqlnative', 'DRIVER' => 'phpbb_db_driver_mssqlnative',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => false, '2.0.x' => false,
), ),
@ -82,7 +84,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'oracle', 'SCHEMA' => 'oracle',
'MODULE' => 'oci8', 'MODULE' => 'oci8',
'DELIM' => '/', 'DELIM' => '/',
'DRIVER' => 'oracle', 'DRIVER' => 'phpbb_db_driver_oracle',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => false, '2.0.x' => false,
), ),
@ -91,7 +93,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'postgres', 'SCHEMA' => 'postgres',
'MODULE' => 'pgsql', 'MODULE' => 'pgsql',
'DELIM' => ';', 'DELIM' => ';',
'DRIVER' => 'postgres', 'DRIVER' => 'phpbb_db_driver_postgres',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => true, '2.0.x' => true,
), ),
@ -100,7 +102,7 @@ function get_available_dbms($dbms = false, $return_unavailable = false, $only_20
'SCHEMA' => 'sqlite', 'SCHEMA' => 'sqlite',
'MODULE' => 'sqlite', 'MODULE' => 'sqlite',
'DELIM' => ';', 'DELIM' => ';',
'DRIVER' => 'sqlite', 'DRIVER' => 'phpbb_db_driver_sqlite',
'AVAILABLE' => true, 'AVAILABLE' => true,
'2.0.x' => false, '2.0.x' => false,
), ),
@ -205,26 +207,19 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
$dbms = $dbms_details['DRIVER']; $dbms = $dbms_details['DRIVER'];
if ($load_dbal)
{
// Include the DB layer
include($phpbb_root_path . 'includes/db/' . $dbms . '.' . $phpEx);
}
// Instantiate it and set return on error true // Instantiate it and set return on error true
$sql_db = 'dbal_' . $dbms; $db = new $dbms();
$db = new $sql_db();
$db->sql_return_on_error(true); $db->sql_return_on_error(true);
// Check that we actually have a database name before going any further..... // Check that we actually have a database name before going any further.....
if ($dbms_details['DRIVER'] != 'sqlite' && $dbms_details['DRIVER'] != 'oracle' && $dbname === '') if ($dbms_details['DRIVER'] != 'phpbb_db_driver_sqlite' && $dbms_details['DRIVER'] != 'phpbb_db_driver_oracle' && $dbname === '')
{ {
$error[] = $lang['INST_ERR_DB_NO_NAME']; $error[] = $lang['INST_ERR_DB_NO_NAME'];
return false; return false;
} }
// Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea
if ($dbms_details['DRIVER'] == 'sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0) if ($dbms_details['DRIVER'] == 'phpbb_db_driver_sqlite' && stripos(phpbb_realpath($dbhost), phpbb_realpath('../')) === 0)
{ {
$error[] = $lang['INST_ERR_DB_FORUM_PATH']; $error[] = $lang['INST_ERR_DB_FORUM_PATH'];
return false; return false;
@ -233,8 +228,8 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
// Check the prefix length to ensure that index names are not too long and does not contain invalid characters // Check the prefix length to ensure that index names are not too long and does not contain invalid characters
switch ($dbms_details['DRIVER']) switch ($dbms_details['DRIVER'])
{ {
case 'mysql': case 'phpbb_db_driver_mysql':
case 'mysqli': case 'phpbb_db_driver_mysqli':
if (strspn($table_prefix, '-./\\') !== 0) if (strspn($table_prefix, '-./\\') !== 0)
{ {
$error[] = $lang['INST_ERR_PREFIX_INVALID']; $error[] = $lang['INST_ERR_PREFIX_INVALID'];
@ -243,22 +238,22 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
// no break; // no break;
case 'postgres': case 'phpbb_db_driver_postgres':
$prefix_length = 36; $prefix_length = 36;
break; break;
case 'mssql': case 'phpbb_db_driver_mssql':
case 'mssql_odbc': case 'phpbb_db_driver_mssql_odbc':
case 'mssqlnative': case 'phpbb_db_driver_mssqlnative':
$prefix_length = 90; $prefix_length = 90;
break; break;
case 'sqlite': case 'phpbb_db_driver_sqlite':
$prefix_length = 200; $prefix_length = 200;
break; break;
case 'firebird': case 'phpbb_db_driver_firebird':
case 'oracle': case 'phpbb_db_driver_oracle':
$prefix_length = 6; $prefix_length = 6;
break; break;
} }
@ -296,21 +291,21 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
// Make sure that the user has selected a sensible DBAL for the DBMS actually installed // Make sure that the user has selected a sensible DBAL for the DBMS actually installed
switch ($dbms_details['DRIVER']) switch ($dbms_details['DRIVER'])
{ {
case 'mysqli': case 'phpbb_db_driver_mysqli':
if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<')) if (version_compare(mysqli_get_server_info($db->db_connect_id), '4.1.3', '<'))
{ {
$error[] = $lang['INST_ERR_DB_NO_MYSQLI']; $error[] = $lang['INST_ERR_DB_NO_MYSQLI'];
} }
break; break;
case 'sqlite': case 'phpbb_db_driver_sqlite':
if (version_compare(sqlite_libversion(), '2.8.2', '<')) if (version_compare(sqlite_libversion(), '2.8.2', '<'))
{ {
$error[] = $lang['INST_ERR_DB_NO_SQLITE']; $error[] = $lang['INST_ERR_DB_NO_SQLITE'];
} }
break; break;
case 'firebird': case 'phpbb_db_driver_firebird':
// check the version of FB, use some hackery if we can't get access to the server info // check the version of FB, use some hackery if we can't get access to the server info
if ($db->service_handle !== false && function_exists('ibase_server_info')) if ($db->service_handle !== false && function_exists('ibase_server_info'))
{ {
@ -391,7 +386,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
} }
break; break;
case 'oracle': case 'phpbb_db_driver_oracle':
if ($unicode_check) if ($unicode_check)
{ {
$sql = "SELECT * $sql = "SELECT *
@ -413,7 +408,7 @@ function connect_check_db($error_connect, &$error, $dbms_details, $table_prefix,
} }
break; break;
case 'postgres': case 'phpbb_db_driver_postgres':
if ($unicode_check) if ($unicode_check)
{ {
$sql = "SHOW server_encoding;"; $sql = "SHOW server_encoding;";
@ -515,6 +510,9 @@ function phpbb_create_config_file_data($data, $dbms, $debug = false, $debug_test
'dbuser' => $data['dbuser'], 'dbuser' => $data['dbuser'],
'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']), 'dbpasswd' => htmlspecialchars_decode($data['dbpasswd']),
'table_prefix' => $data['table_prefix'], 'table_prefix' => $data['table_prefix'],
'adm_relative_path' => 'adm/',
'acm_type' => 'phpbb_cache_driver_file', 'acm_type' => 'phpbb_cache_driver_file',
); );

View file

@ -210,7 +210,7 @@ class messenger
{ {
$style_resource_locator = new phpbb_style_resource_locator(); $style_resource_locator = new phpbb_style_resource_locator();
$style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider()); $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
$tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context()); $tpl = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, new phpbb_template_context(), $phpbb_extension_manager);
$style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl); $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl);
$this->tpl_msg[$template_lang . $template_file] = $tpl; $this->tpl_msg[$template_lang . $template_file] = $tpl;
@ -231,7 +231,7 @@ class messenger
} }
} }
$style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), ''); $style->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), array(), '');
$tpl->set_filenames(array( $tpl->set_filenames(array(
'body' => $template_file . '.txt', 'body' => $template_file . '.txt',
@ -392,6 +392,28 @@ class messenger
} }
} }
/**
* Generates a valid message id to be used in emails
*
* @return string message id
*/
function generate_message_id()
{
global $config;
$domain = 'phpbb.generated';
if ($config['server_name'])
{
$domain = $config['server_name'];
}
else if (!empty($_SERVER['SERVER_NAME']))
{
$domain = $_SERVER['SERVER_NAME'];
}
return md5(unique_id(time())) . '@' . $domain;
}
/** /**
* Return email header * Return email header
*/ */
@ -418,7 +440,7 @@ class messenger
$headers[] = 'Return-Path: <' . $config['board_email'] . '>'; $headers[] = 'Return-Path: <' . $config['board_email'] . '>';
$headers[] = 'Sender: <' . $config['board_email'] . '>'; $headers[] = 'Sender: <' . $config['board_email'] . '>';
$headers[] = 'MIME-Version: 1.0'; $headers[] = 'MIME-Version: 1.0';
$headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . $config['server_name'] . '>'; $headers[] = 'Message-ID: <' . $this->generate_message_id() . '>';
$headers[] = 'Date: ' . date('r', time()); $headers[] = 'Date: ' . date('r', time());
$headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed
$headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit

View file

@ -1695,8 +1695,9 @@ function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $u
// The variable name should be $post_approved, because it indicates if the post is approved or not // The variable name should be $post_approved, because it indicates if the post is approved or not
$post_approval = 1; $post_approval = 1;
// Check the permissions for post approval. Moderators are not affected. // Check the permissions for post approval.
if (!$auth->acl_get('f_noapprove', $data['forum_id']) && !$auth->acl_get('m_approve', $data['forum_id'])) // Moderators must go through post approval like ordinary users.
if (!$auth->acl_get('f_noapprove', $data['forum_id']))
{ {
// Post not approved, but in queue // Post not approved, but in queue
$post_approval = 0; $post_approval = 0;

View file

@ -70,7 +70,7 @@ class filespec
$this->mimetype = 'application/octetstream'; $this->mimetype = 'application/octetstream';
} }
$this->extension = strtolower($this->get_extension($this->realname)); $this->extension = strtolower(self::get_extension($this->realname));
// Try to get real filesize from temporary folder (not always working) ;) // Try to get real filesize from temporary folder (not always working) ;)
$this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize; $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize;
@ -187,8 +187,11 @@ class filespec
/** /**
* Get file extension * Get file extension
*
* @param string Filename that needs to be checked
* @return string Extension of the supplied filename
*/ */
function get_extension($filename) static public function get_extension($filename)
{ {
if (strpos($filename, '.') === false) if (strpos($filename, '.') === false)
{ {
@ -369,7 +372,7 @@ class filespec
} }
// Check image type // Check image type
$types = $this->upload->image_types(); $types = fileupload::image_types();
if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]]))
{ {
@ -1019,9 +1022,11 @@ class fileupload
} }
/** /**
* Return image type/extension mapping * Get image type/extension mapping
*
* @return array Array containing the image types and their extensions
*/ */
function image_types() static public function image_types()
{ {
return array( return array(
IMAGETYPE_GIF => array('gif'), IMAGETYPE_GIF => array('gif'),

View file

@ -2676,12 +2676,12 @@ function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow
} }
$db->sql_freeresult($result); $db->sql_freeresult($result);
if (isset($sql_ary['group_avatar']) && !$sql_ary['group_avatar']) if (isset($sql_ary['group_avatar']))
{ {
remove_default_avatar($group_id, $user_ary); remove_default_avatar($group_id, $user_ary);
} }
if (isset($sql_ary['group_rank']) && !$sql_ary['group_rank']) if (isset($sql_ary['group_rank']))
{ {
remove_default_rank($group_id, $user_ary); remove_default_rank($group_id, $user_ary);
} }
@ -2845,7 +2845,7 @@ function avatar_remove_db($avatar_name)
*/ */
function group_delete($group_id, $group_name = false) function group_delete($group_id, $group_name = false)
{ {
global $db, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container; global $db, $cache, $auth, $user, $phpbb_root_path, $phpEx, $phpbb_dispatcher, $phpbb_container;
if (!$group_name) if (!$group_name)
{ {
@ -2917,12 +2917,12 @@ function group_delete($group_id, $group_name = false)
extract($phpbb_dispatcher->trigger_event('core.delete_group_after', compact($vars))); extract($phpbb_dispatcher->trigger_event('core.delete_group_after', compact($vars)));
// Re-cache moderators // Re-cache moderators
if (!function_exists('cache_moderators')) if (!function_exists('phpbb_cache_moderators'))
{ {
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
} }
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
add_log('admin', 'LOG_GROUP_DELETE', $group_name); add_log('admin', 'LOG_GROUP_DELETE', $group_name);
@ -3212,8 +3212,8 @@ function remove_default_avatar($group_id, $user_ids)
user_avatar_width = 0, user_avatar_width = 0,
user_avatar_height = 0 user_avatar_height = 0
WHERE group_id = " . (int) $group_id . " WHERE group_id = " . (int) $group_id . "
AND user_avatar = '" . $db->sql_escape($row['group_avatar']) . "' AND user_avatar = '" . $db->sql_escape($row['group_avatar']) . "'
AND " . $db->sql_in_set('user_id', $user_ids); AND " . $db->sql_in_set('user_id', $user_ids);
$db->sql_query($sql); $db->sql_query($sql);
} }
@ -3250,9 +3250,9 @@ function remove_default_rank($group_id, $user_ids)
$sql = 'UPDATE ' . USERS_TABLE . ' $sql = 'UPDATE ' . USERS_TABLE . '
SET user_rank = 0 SET user_rank = 0
WHERE group_id = ' . (int)$group_id . ' WHERE group_id = ' . (int)$group_id . '
AND user_rank <> 0 AND user_rank <> 0
AND user_rank = ' . (int)$row['group_rank'] . ' AND user_rank = ' . (int)$row['group_rank'] . '
AND ' . $db->sql_in_set('user_id', $user_ids); AND ' . $db->sql_in_set('user_id', $user_ids);
$db->sql_query($sql); $db->sql_query($sql);
} }
@ -3281,7 +3281,8 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
case 'demote': case 'demote':
case 'promote': case 'promote':
$sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . " $sql = 'SELECT user_id
FROM ' . USER_GROUP_TABLE . "
WHERE group_id = $group_id WHERE group_id = $group_id
AND user_pending = 1 AND user_pending = 1
AND " . $db->sql_in_set('user_id', $user_id_ary); AND " . $db->sql_in_set('user_id', $user_id_ary);
@ -3379,7 +3380,8 @@ function group_user_attributes($action, $group_id, $user_id_ary = false, $userna
return 'NO_USERS'; return 'NO_USERS';
} }
$sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . ' $sql = 'SELECT user_id, group_id
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true); WHERE ' . $db->sql_in_set('user_id', $user_id_ary, false, true);
$result = $db->sql_query($sql); $result = $db->sql_query($sql);
@ -3467,7 +3469,7 @@ function group_validate_groupname($group_id, $group_name)
*/ */
function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false)
{ {
global $cache, $db, $phpbb_dispatcher; global $phpbb_container, $db, $phpbb_dispatcher;
if (empty($user_id_ary)) if (empty($user_id_ary))
{ {
@ -3513,45 +3515,69 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
} }
} }
// Before we update the user attributes, we will make a list of those having now the group avatar assigned $updated_sql_ary = $sql_ary;
// Before we update the user attributes, we will update the rank for users that don't have a custom rank
if (isset($sql_ary['user_rank']))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', array('user_rank' => $sql_ary['user_rank'])) . '
WHERE user_rank = 0
AND ' . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
unset($sql_ary['user_rank']);
}
// Before we update the user attributes, we will update the avatar for users that don't have a custom avatar
$avatar_options = array('user_avatar', 'user_avatar_type', 'user_avatar_height', 'user_avatar_width');
if (isset($sql_ary['user_avatar'])) if (isset($sql_ary['user_avatar']))
{ {
// Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem) $avatar_sql_ary = array();
$sql = 'SELECT user_id, group_id, user_avatar foreach ($avatar_options as $avatar_option)
FROM ' . USERS_TABLE . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary) . '
AND user_avatar_type = ' . AVATAR_UPLOAD;
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{ {
avatar_delete('user', $row); if (isset($sql_ary[$avatar_option]))
} {
$db->sql_freeresult($result); $avatar_sql_ary[$avatar_option] = $sql_ary[$avatar_option];
} }
else }
{
unset($sql_ary['user_avatar_type']); $sql = 'UPDATE ' . USERS_TABLE . '
unset($sql_ary['user_avatar_height']); SET ' . $db->sql_build_array('UPDATE', $avatar_sql_ary) . "
unset($sql_ary['user_avatar_width']); WHERE user_avatar = ''
AND " . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
} }
$sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' // Remove the avatar options, as we already updated them
WHERE ' . $db->sql_in_set('user_id', $user_id_ary); foreach ($avatar_options as $avatar_option)
$db->sql_query($sql); {
unset($sql_ary[$avatar_option]);
}
if (!empty($sql_ary))
{
$sql = 'UPDATE ' . USERS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $sql_ary) . '
WHERE ' . $db->sql_in_set('user_id', $user_id_ary);
$db->sql_query($sql);
}
if (isset($sql_ary['user_colour'])) if (isset($sql_ary['user_colour']))
{ {
// Update any cached colour information for these users // Update any cached colour information for these users
$sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' $sql = 'UPDATE ' . FORUMS_TABLE . "
SET forum_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary); WHERE " . $db->sql_in_set('forum_last_poster_id', $user_id_ary);
$db->sql_query($sql); $db->sql_query($sql);
$sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' $sql = 'UPDATE ' . TOPICS_TABLE . "
SET topic_first_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
WHERE " . $db->sql_in_set('topic_poster', $user_id_ary); WHERE " . $db->sql_in_set('topic_poster', $user_id_ary);
$db->sql_query($sql); $db->sql_query($sql);
$sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "' $sql = 'UPDATE ' . TOPICS_TABLE . "
SET topic_last_poster_colour = '" . $db->sql_escape($sql_ary['user_colour']) . "'
WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary); WHERE " . $db->sql_in_set('topic_last_poster_id', $user_id_ary);
$db->sql_query($sql); $db->sql_query($sql);
@ -3563,6 +3589,9 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
} }
} }
// Make all values available for the event
$sql_ary = $updated_sql_ary;
/** /**
* Event when the default group is set for an array of users * Event when the default group is set for an array of users
* *
@ -3583,7 +3612,7 @@ function group_set_user_default($group_id, $user_id_ary, $group_attributes = fal
} }
// Because some tables/caches use usercolour-specific data we need to purge this here. // Because some tables/caches use usercolour-specific data we need to purge this here.
$cache->destroy('sql', MODERATOR_CACHE_TABLE); $phpbb_container->get('cache.driver')->destroy('sql', MODERATOR_CACHE_TABLE);
} }
/** /**
@ -3682,7 +3711,7 @@ function group_memberships($group_id_ary = false, $user_id_ary = false, $return_
*/ */
function group_update_listings($group_id) function group_update_listings($group_id)
{ {
global $auth; global $db, $cache, $auth;
$hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_')); $hold_ary = $auth->acl_group_raw_data($group_id, array('a_', 'm_'));
@ -3724,22 +3753,22 @@ function group_update_listings($group_id)
if ($mod_permissions) if ($mod_permissions)
{ {
if (!function_exists('cache_moderators')) if (!function_exists('phpbb_cache_moderators'))
{ {
global $phpbb_root_path, $phpEx; global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
} }
cache_moderators(); phpbb_cache_moderators($db, $cache, $auth);
} }
if ($mod_permissions || $admin_permissions) if ($mod_permissions || $admin_permissions)
{ {
if (!function_exists('update_foes')) if (!function_exists('phpbb_update_foes'))
{ {
global $phpbb_root_path, $phpEx; global $phpbb_root_path, $phpEx;
include($phpbb_root_path . 'includes/functions_admin.' . $phpEx); include($phpbb_root_path . 'includes/functions_admin.' . $phpEx);
} }
update_foes(array($group_id)); phpbb_update_foes($db, $auth, array($group_id));
} }
} }

View file

@ -0,0 +1,84 @@
<?php
/**
*
* @package extension
* @copyright (c) 2013 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
/**
* The hook finder locates installed hooks.
*
* @package phpBB3
*/
class phpbb_hook_finder
{
protected $phpbb_root_path;
protected $cache;
protected $php_ext;
/**
* Creates a new finder instance.
*
* @param string $phpbb_root_path Path to the phpbb root directory
* @param string $php_ext php file extension
* @param phpbb_cache_driver_interface $cache A cache instance or null
*/
public function __construct($phpbb_root_path, $php_ext, phpbb_cache_driver_interface $cache = null)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->cache = $cache;
$this->php_ext = $php_ext;
}
/**
* Finds all hook files.
*
* @param bool $cache Whether the result should be cached
* @return array An array of paths to found hook files
*/
public function find($cache = true)
{
if (!defined('DEBUG') && $cache && $this->cache)
{
$hook_files = $this->cache->get('_hooks');
if ($hook_files !== false)
{
return $hook_files;
}
}
$hook_files = array();
// Now search for hooks...
$dh = @opendir($this->phpbb_root_path . 'includes/hooks/');
if ($dh)
{
while (($file = readdir($dh)) !== false)
{
if (strpos($file, 'hook_') === 0 && substr($file, -(strlen($this->php_ext) + 1)) === '.' . $this->php_ext)
{
$hook_files[] = substr($file, 0, -(strlen($this->php_ext) + 1));
}
}
closedir($dh);
}
if ($cache && $this->cache)
{
$this->cache->put('_hooks', $hook_files);
}
return $hook_files;
}
}

View file

@ -48,7 +48,7 @@ class phpbb_lock_db
/** /**
* A database connection * A database connection
* @var dbal * @var phpbb_db_driver
*/ */
private $db; private $db;
@ -59,9 +59,9 @@ class phpbb_lock_db
* *
* @param string $config_name A config variable to be used for locking * @param string $config_name A config variable to be used for locking
* @param array $config The phpBB configuration * @param array $config The phpBB configuration
* @param dbal $db A database connection * @param phpbb_db_driver $db A database connection
*/ */
public function __construct($config_name, phpbb_config $config, dbal $db) public function __construct($config_name, phpbb_config $config, phpbb_db_driver $db)
{ {
$this->config_name = $config_name; $this->config_name = $config_name;
$this->config = $config; $this->config = $config;

View file

@ -430,13 +430,16 @@ function merge_topics($forum_id, $topic_ids, $to_topic_id)
// Message and return links // Message and return links
$success_msg = 'POSTS_MERGED_SUCCESS'; $success_msg = 'POSTS_MERGED_SUCCESS';
// If the topic no longer exist, we will update the topic watch table. if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status'))
// To not let it error out on users watching both topics, we just return on an error... {
$db->sql_return_on_error(true); include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx);
$db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); }
$db->sql_return_on_error(false);
$db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); // Update the topic watch table.
phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id);
// Update the bookmarks table.
phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_ids, $to_topic_id);
// Link to the new topic // Link to the new topic
$return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>'); $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid("{$phpbb_root_path}viewtopic.$phpEx", 'f=' . $to_forum_id . '&amp;t=' . $to_topic_id) . '">', '</a>');

View file

@ -1080,6 +1080,7 @@ function mcp_fork_topic($topic_ids)
} }
} }
// Copy topic subscriptions to new topic
$sql = 'SELECT user_id, notify_status $sql = 'SELECT user_id, notify_status
FROM ' . TOPICS_WATCH_TABLE . ' FROM ' . TOPICS_WATCH_TABLE . '
WHERE topic_id = ' . $topic_id; WHERE topic_id = ' . $topic_id;
@ -1100,6 +1101,27 @@ function mcp_fork_topic($topic_ids)
{ {
$db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
} }
// Copy bookmarks to new topic
$sql = 'SELECT user_id
FROM ' . BOOKMARKS_TABLE . '
WHERE topic_id = ' . $topic_id;
$result = $db->sql_query($sql);
$sql_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$sql_ary[] = array(
'topic_id' => (int) $new_topic_id,
'user_id' => (int) $row['user_id'],
);
}
$db->sql_freeresult($result);
if (sizeof($sql_ary))
{
$db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
}
} }
// Sync new topics, parent forums and board stats // Sync new topics, parent forums and board stats

View file

@ -122,6 +122,7 @@ class mcp_pm_reports
$message = bbcode_nl2br($message); $message = bbcode_nl2br($message);
$message = smiley_text($message); $message = smiley_text($message);
$report['report_text'] = make_clickable(bbcode_nl2br($report['report_text']));
if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download')) if ($pm_info['message_attachment'] && $auth->acl_get('u_pm_download'))
{ {

View file

@ -71,7 +71,7 @@ class mcp_reports
// closed reports are accessed by report id // closed reports are accessed by report id
$report_id = request_var('r', 0); $report_id = request_var('r', 0);
$sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, r.reported_post_uid, r.reported_post_bitfield, r.reported_post_enable_magic_url, r.reported_post_enable_smilies, r.reported_post_enable_bbcode, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour
FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u
WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . '
AND rr.reason_id = r.reason_id AND rr.reason_id = r.reason_id
@ -94,6 +94,10 @@ class mcp_reports
$post_id = $report['post_id']; $post_id = $report['post_id'];
$report_id = $report['report_id']; $report_id = $report['report_id'];
$parse_post_flags = $report['reported_post_enable_bbcode'] ? OPTION_FLAG_BBCODE : 0;
$parse_post_flags += $report['reported_post_enable_smilies'] ? OPTION_FLAG_SMILIES : 0;
$parse_post_flags += $report['reported_post_enable_magic_url'] ? OPTION_FLAG_LINKS : 0;
$post_info = get_post_data(array($post_id), 'm_report', true); $post_info = get_post_data(array($post_id), 'm_report', true);
@ -136,18 +140,7 @@ class mcp_reports
$post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false;
// Process message, leave it uncensored
$message = $post_info['post_text'];
if ($post_info['bbcode_bitfield'])
{
include_once($phpbb_root_path . 'includes/bbcode.' . $phpEx);
$bbcode = new bbcode($post_info['bbcode_bitfield']);
$bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']);
}
$message = bbcode_nl2br($message);
$message = smiley_text($message);
$report['report_text'] = make_clickable(bbcode_nl2br($report['report_text'])); $report['report_text'] = make_clickable(bbcode_nl2br($report['report_text']));
if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id']))
@ -168,7 +161,7 @@ class mcp_reports
if (sizeof($attachments)) if (sizeof($attachments))
{ {
$update_count = array(); $update_count = array();
parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); parse_attachments($post_info['forum_id'], $report['reported_post_text'], $attachments, $update_count);
} }
// Display not already displayed Attachments for this post, we already parsed them. ;) // Display not already displayed Attachments for this post, we already parsed them. ;)
@ -227,7 +220,7 @@ class mcp_reports
'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']),
'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']),
'POST_PREVIEW' => generate_text_for_display($report['reported_post_text'], $report['reported_post_uid'], $report['reported_post_bitfield'], OPTION_FLAG_BBCODE | OPTION_FLAG_SMILIES, false), 'POST_PREVIEW' => generate_text_for_display($report['reported_post_text'], $report['reported_post_uid'], $report['reported_post_bitfield'], $parse_post_flags, false),
'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'], 'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'],
'POST_DATE' => $user->format_date($post_info['post_time']), 'POST_DATE' => $user->format_date($post_info['post_time']),
'POST_IP' => $post_info['poster_ip'], 'POST_IP' => $post_info['poster_ip'],

View file

@ -521,6 +521,49 @@ function split_topic($action, $topic_id, $to_forum_id, $subject)
WHERE post_id = {$post_id_list[0]}"; WHERE post_id = {$post_id_list[0]}";
$db->sql_query($sql); $db->sql_query($sql);
// Copy topic subscriptions to new topic
$sql = 'SELECT user_id, notify_status
FROM ' . TOPICS_WATCH_TABLE . '
WHERE topic_id = ' . $topic_id;
$result = $db->sql_query($sql);
$sql_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$sql_ary[] = array(
'topic_id' => (int) $to_topic_id,
'user_id' => (int) $row['user_id'],
'notify_status' => (int) $row['notify_status'],
);
}
$db->sql_freeresult($result);
if (sizeof($sql_ary))
{
$db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary);
}
// Copy bookmarks to new topic
$sql = 'SELECT user_id
FROM ' . BOOKMARKS_TABLE . '
WHERE topic_id = ' . $topic_id;
$result = $db->sql_query($sql);
$sql_ary = array();
while ($row = $db->sql_fetchrow($result))
{
$sql_ary[] = array(
'topic_id' => (int) $to_topic_id,
'user_id' => (int) $row['user_id'],
);
}
$db->sql_freeresult($result);
if (sizeof($sql_ary))
{
$db->sql_multi_insert(BOOKMARKS_TABLE, $sql_ary);
}
$success_msg = 'TOPIC_SPLIT_SUCCESS'; $success_msg = 'TOPIC_SPLIT_SUCCESS';
// Update forum statistics // Update forum statistics
@ -623,13 +666,16 @@ function merge_posts($topic_id, $to_topic_id)
} }
else else
{ {
// If the topic no longer exist, we will update the topic watch table. if (!function_exists('phpbb_update_rows_avoiding_duplicates_notify_status'))
// To not let it error out on users watching both topics, we just return on an error... {
$db->sql_return_on_error(true); include($phpbb_root_path . 'includes/functions_database_helper.' . $phpEx);
$db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id); }
$db->sql_return_on_error(false);
$db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id); // If the topic no longer exist, we will update the topic watch table.
phpbb_update_rows_avoiding_duplicates_notify_status($db, TOPICS_WATCH_TABLE, 'topic_id', $topic_ids, $to_topic_id);
// If the topic no longer exist, we will update the bookmarks table.
phpbb_update_rows_avoiding_duplicates($db, BOOKMARKS_TABLE, 'topic_id', $topic_id, $to_topic_id);
} }
// Link to the new topic // Link to the new topic

View file

@ -702,17 +702,6 @@ class bbcode_firstpass extends bbcode
{ {
global $config, $user; global $config, $user;
/**
* If you change this code, make sure the cases described within the following reports are still working:
* #3572 - [quote="[test]test"]test [ test[/quote] - (correct: parsed)
* #14667 - [quote]test[/quote] test ] and [ test [quote]test[/quote] (correct: parsed)
* #14770 - [quote="["]test[/quote] (correct: parsed)
* [quote="[i]test[/i]"]test[/quote] (correct: parsed)
* [quote="[quote]test[/quote]"]test[/quote] (correct: parsed - Username displayed as [quote]test[/quote])
* #20735 - [quote]test[/[/b]quote] test [/quote][/quote] test - (correct: quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted)
* #40565 - [quote="a"]a[/quote][quote="a]a[/quote] (correct: first quote tag parsed, second quote tag unparsed)
*/
$in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in)));
if (!$in) if (!$in)

View file

@ -260,6 +260,8 @@ class phpbb_questionnaire_phpbb_data_provider
include("{$phpbb_root_path}config.$phpEx"); include("{$phpbb_root_path}config.$phpEx");
unset($dbhost, $dbport, $dbname, $dbuser, $dbpasswd); // Just a precaution unset($dbhost, $dbport, $dbname, $dbuser, $dbpasswd); // Just a precaution
$dbms = phpbb_convert_30_dbms_to_31($dbms);
// Only send certain config vars // Only send certain config vars
$config_vars = array( $config_vars = array(
'active_sessions' => true, 'active_sessions' => true,

Some files were not shown because too many files have changed in this diff Show more