diff options
Diffstat (limited to 'phpBB')
55 files changed, 6927 insertions, 444 deletions
diff --git a/phpBB/.htaccess b/phpBB/.htaccess index 1ae74ed825..53bce762ea 100644 --- a/phpBB/.htaccess +++ b/phpBB/.htaccess @@ -2,6 +2,16 @@ RewriteEngine on # +# Uncomment the statement below if URL rewriting doesn't +# work properly. If you installed phpBB in a subdirectory +# of your site, properly set the argument for the statement. +# e.g.: if your domain is test.com and you installed phpBB +# in http://www.test.com/phpBB/index.php you have to set +# the statement RewriteBase /phpBB/ +# +#RewriteBase / + +# # Uncomment the statement below if you want to make use of # HTTP authentication and it does not already work. # This could be required if you are for example using PHP via Apache CGI. diff --git a/phpBB/adm/style/installer_convert.html b/phpBB/adm/style/installer_convert.html new file mode 100644 index 0000000000..aa16542b6b --- /dev/null +++ b/phpBB/adm/style/installer_convert.html @@ -0,0 +1,87 @@ +<!-- INCLUDE installer_header.html --> +<!-- IF TITLE --><h1>{TITLE}</h1><!-- ENDIF --> +<!-- IF S_ERROR_BOX --> +<div class="errorbox"> + <h3>{ERROR_TITLE}</h3> + <p>{ERROR_MSG}</p> +</div> +<!-- ENDIF --> +<!-- IF .errors --> +<div id="error-container"> +<!-- BEGIN errors --> + <strong>{errors.TITLE}</strong> + <!-- IF errors.DESCRIPTION --><p>{errors.DESCRIPTION}</p><!-- ENDIF --> +<!-- END errors --> +</div> +<!-- ENDIF --> +<!-- IF BODY --><p>{BODY}</p><!-- ENDIF --> +<!-- IF CONTENT -->{CONTENT}<!-- ENDIF --> +<!-- IF S_CONV_IN_PROGRESS --> +<p class="centered-text"><a href="{U_ACTION}" class="button1<!-- IF S_REFRESH --> disabled<!-- ENDIF -->"<!-- IF S_REFRESH --> onclick="return false;"<!-- ENDIF -->>{L_SUBMIT}</a></p> +<!-- ENDIF --> +<!-- IF S_CONTINUE --> +<div id="download-wrapper" class="download-box"> + <p class="centered-text"> + <a href="{U_NEW_ACTION}" class="button1">{L_CONVERT_NEW_CONVERSION}</a> + <a href="{U_CONTINUE_ACTION}" class="button1">{L_CONTINUE_OLD_CONVERSION}</a> + </p> +</div> +<!-- ENDIF --> +<!-- IF S_LIST --> +<table class="table1"> + <caption>{L_AVAILABLE_CONVERTORS}</caption> + <col class="col1" /><col class="col2" /><col class="col1" /><col class="col2" /> + <thead> + <tr> + <th>{L_SOFTWARE}</th> + <th>{L_VERSION}</th> + <th>{L_AUTHOR}</th> + <th>{L_CONVERT_OPTIONS}</th> + </tr> + </thead> + <tbody> + <!-- IF .convertors --> + <!-- BEGIN convertors --> + <tr> + <td>{convertors.SOFTWARE}</td> + <td>{convertors.VERSION}</td> + <td>{convertors.AUTHOR}</td> + <td><a href="{convertors.U_CONVERT}">{L_CONVERT}</a></td> + </tr> + <!-- END convertors --> + <!-- ELSE --> + <tr> + <td>{L_NO_CONVERTORS}</td> + <td>-</td> + <td>-</td> + <td>-</td> + </tr> + <!-- ENDIF --> + </tbody> +</table> +<!-- ENDIF --> +<!-- IF .checks --> +<fieldset> + + <!-- BEGIN checks --> + <!-- IF checks.S_LEGEND --> + <!-- IF not checks.S_FIRST_ROW --> +</fieldset> + +<fieldset> + <!-- ENDIF --> + <legend>{checks.LEGEND}</legend> + <!-- IF checks.LEGEND_EXPLAIN --><p>{checks.LEGEND_EXPLAIN}</p><!-- ENDIF --> + <!-- ELSE --> + + <dl> + <dt><label>{checks.TITLE}{L_COLON}</label><!-- IF checks.S_EXPLAIN --><br /><span class="explain">{checks.TITLE_EXPLAIN}</span><!-- ENDIF --></dt> + <dd>{checks.RESULT}</dd> + </dl> + <!-- ENDIF --> + <!-- END checks --> + +</fieldset> +<!-- ENDIF --> +<!-- INCLUDEJS {T_ASSETS_PATH}/javascript/installer.js --> +<!-- INCLUDE installer_footer.html --> diff --git a/phpBB/assets/javascript/core.js b/phpBB/assets/javascript/core.js index 91f5521c7a..5844537fc8 100644 --- a/phpBB/assets/javascript/core.js +++ b/phpBB/assets/javascript/core.js @@ -1032,7 +1032,7 @@ phpbb.resizeTextArea = function($items, options) { function autoResize(item) { function setHeight(height) { - height += parseInt($item.css('height'), 10) - $item.height(); + height += parseInt($item.css('height'), 10) - $item.innerHeight(); $item .css({ height: height + 'px', resize: 'none' }) .addClass('auto-resized'); @@ -1051,7 +1051,7 @@ phpbb.resizeTextArea = function($items, options) { configuration.maxHeight ), $item = $(item), - height = parseInt($item.height(), 10), + height = parseInt($item.innerHeight(), 10), scrollHeight = (item.scrollHeight) ? item.scrollHeight : 0; if (height < 0) { diff --git a/phpBB/assets/javascript/installer.js b/phpBB/assets/javascript/installer.js index 5f2c65c776..4a4f381844 100644 --- a/phpBB/assets/javascript/installer.js +++ b/phpBB/assets/javascript/installer.js @@ -211,6 +211,7 @@ clearInterval(progressTimer); $progressFiller = $('#progress-bar-filler'); + $progressFillerText = $('#progress-bar-filler-text'); $progressText = $('#progress-bar-text'); $statusText = $('#progress-status-text'); @@ -242,6 +243,22 @@ } } + // Redirects user + function redirect(url, use_ajax) { + if (use_ajax) { + resetPolling(); + + var xhReq = createXhrObject(); + xhReq.open('GET', url, true); + xhReq.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + xhReq.send(); + + startPolling(xhReq); + } else { + window.location.href = url; + } + } + /** * Parse messages from the response object * @@ -308,6 +325,10 @@ if (responseObject.hasOwnProperty('refresh')) { refreshRequested = true; } + + if (responseObject.hasOwnProperty('redirect')) { + redirect(responseObject.redirect.url, responseObject.redirect.use_ajax); + } } /** diff --git a/phpBB/composer.json b/phpBB/composer.json index 89bbce4588..88df2bfa3d 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -28,6 +28,7 @@ "php": ">=5.4,<7.1", "bantu/ini-get-wrapper": "1.0.*", "google/recaptcha": "~1.1", + "guzzlehttp/guzzle": "~5.3", "lusitanian/oauth": "^0.8.1", "marc1706/fast-image-size": "1.1.*", "patchwork/utf8": "1.1.*", @@ -48,6 +49,7 @@ }, "require-dev": { "fabpot/goutte": "~2.0", + "facebook/webdriver": "~1.1", "phing/phing": "2.4.*", "phpunit/dbunit": "1.3.*", "phpunit/phpunit": "4.1.*", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 6412029b0b..7cb6c160ce 100644 --- a/phpBB/composer.lock +++ b/phpBB/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "f76b5185058599cad6a87ef7c8c35fbf", - "content-hash": "b89d3c18f8d9b3c4dc476f92030a83a1", + "hash": "2de20b0ffe0ca05fb62a7c685a25ca79", + "content-hash": "6e427257e82c0d33fc94040d9685f516", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -83,6 +83,165 @@ "time": "2015-09-02 17:23:59" }, { + "name": "guzzlehttp/guzzle", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", + "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "shasum": "" + }, + "require": { + "guzzlehttp/ringphp": "^1.1", + "php": ">=5.4.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "^4.0", + "psr/log": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" + ], + "time": "2015-05-20 03:47:55" + }, + { + "name": "guzzlehttp/ringphp", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/RingPHP.git", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", + "shasum": "" + }, + "require": { + "guzzlehttp/streams": "~3.0", + "php": ">=5.4.0", + "react/promise": "~2.0" + }, + "require-dev": { + "ext-curl": "*", + "phpunit/phpunit": "~4.0" + }, + "suggest": { + "ext-curl": "Guzzle will use specific adapters if cURL is present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Ring\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", + "time": "2015-05-20 03:37:09" + }, + { + "name": "guzzlehttp/streams", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/streams.git", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Stream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Provides a simple abstraction over streams of data", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "Guzzle", + "stream" + ], + "time": "2014-10-12 19:18:40" + }, + { "name": "ircmaxell/password-compat", "version": "v1.0.4", "source": { @@ -332,17 +491,61 @@ "time": "2012-12-21 11:40:51" }, { + "name": "react/promise", + "version": "v2.2.1", + "source": { + "type": "git", + "url": "https://github.com/reactphp/promise.git", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", + "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "React\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jan Sorgalla", + "email": "jsorgalla@gmail.com" + } + ], + "description": "A lightweight implementation of CommonJS Promises/A for PHP", + "time": "2015-07-03 13:48:55" + }, + { "name": "s9e/text-formatter", - "version": "0.4.8", + "version": "0.4.10", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "9eeb900157d5934e760a51b4c830643d0275423b" + "reference": "dc6b7b069d17fc18c8a40cce9e1048e25aa11fec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/9eeb900157d5934e760a51b4c830643d0275423b", - "reference": "9eeb900157d5934e760a51b4c830643d0275423b", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/dc6b7b069d17fc18c8a40cce9e1048e25aa11fec", + "reference": "dc6b7b069d17fc18c8a40cce9e1048e25aa11fec", "shasum": "" }, "require": { @@ -389,7 +592,7 @@ "parser", "shortcodes" ], - "time": "2016-01-15 14:07:25" + "time": "2016-02-11 14:03:12" }, { "name": "symfony/config", @@ -1404,258 +1607,47 @@ "time": "2015-05-05 21:14:57" }, { - "name": "guzzle/guzzle", - "version": "v3.9.3", + "name": "facebook/webdriver", + "version": "1.1.1", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle3.git", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9" + "url": "https://github.com/facebook/php-webdriver.git", + "reference": "1c98108ba3eb435b681655764de11502a0653705" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle3/zipball/0645b70d953bc1c067bbc8d5bc53194706b628d9", - "reference": "0645b70d953bc1c067bbc8d5bc53194706b628d9", + "url": "https://api.github.com/repos/facebook/php-webdriver/zipball/1c98108ba3eb435b681655764de11502a0653705", + "reference": "1c98108ba3eb435b681655764de11502a0653705", "shasum": "" }, "require": { - "ext-curl": "*", - "php": ">=5.3.3", - "symfony/event-dispatcher": "~2.1" - }, - "replace": { - "guzzle/batch": "self.version", - "guzzle/cache": "self.version", - "guzzle/common": "self.version", - "guzzle/http": "self.version", - "guzzle/inflection": "self.version", - "guzzle/iterator": "self.version", - "guzzle/log": "self.version", - "guzzle/parser": "self.version", - "guzzle/plugin": "self.version", - "guzzle/plugin-async": "self.version", - "guzzle/plugin-backoff": "self.version", - "guzzle/plugin-cache": "self.version", - "guzzle/plugin-cookie": "self.version", - "guzzle/plugin-curlauth": "self.version", - "guzzle/plugin-error-response": "self.version", - "guzzle/plugin-history": "self.version", - "guzzle/plugin-log": "self.version", - "guzzle/plugin-md5": "self.version", - "guzzle/plugin-mock": "self.version", - "guzzle/plugin-oauth": "self.version", - "guzzle/service": "self.version", - "guzzle/stream": "self.version" + "php": ">=5.3.19" }, "require-dev": { - "doctrine/cache": "~1.3", - "monolog/monolog": "~1.0", - "phpunit/phpunit": "3.7.*", - "psr/log": "~1.0", - "symfony/class-loader": "~2.1", - "zendframework/zend-cache": "2.*,<2.3", - "zendframework/zend-log": "2.*,<2.3" + "phpunit/phpunit": "4.6.*" }, "suggest": { - "guzzlehttp/guzzle": "Guzzle 5 has moved to a new package name. The package you have installed, Guzzle 3, is deprecated." + "phpdocumentor/phpdocumentor": "2.*" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.9-dev" - } - }, - "autoload": { - "psr-0": { - "Guzzle": "src/", - "Guzzle\\Tests": "tests/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - }, - { - "name": "Guzzle Community", - "homepage": "https://github.com/guzzle/guzzle/contributors" - } - ], - "description": "PHP HTTP client. This library is deprecated in favor of https://packagist.org/packages/guzzlehttp/guzzle", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2015-03-18 18:23:50" - }, - { - "name": "guzzlehttp/guzzle", - "version": "5.3.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", - "shasum": "" - }, - "require": { - "guzzlehttp/ringphp": "^1.1", - "php": ">=5.4.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Guzzle is a PHP HTTP client library and framework for building RESTful web service clients", - "homepage": "http://guzzlephp.org/", - "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" - ], - "time": "2015-05-20 03:47:55" - }, - { - "name": "guzzlehttp/ringphp", - "version": "1.1.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/RingPHP.git", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/RingPHP/zipball/dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "reference": "dbbb91d7f6c191e5e405e900e3102ac7f261bc0b", - "shasum": "" - }, - "require": { - "guzzlehttp/streams": "~3.0", - "php": ">=5.4.0", - "react/promise": "~2.0" - }, - "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "~4.0" - }, - "suggest": { - "ext-curl": "Guzzle will use specific adapters if cURL is present" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "GuzzleHttp\\Ring\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } - ], - "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" - }, - { - "name": "guzzlehttp/streams", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/guzzle/streams.git", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/guzzle/streams/zipball/47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "reference": "47aaa48e27dae43d39fc1cea0ccf0d84ac1a2ba5", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "require-dev": { - "phpunit/phpunit": "~4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, "autoload": { "psr-4": { - "GuzzleHttp\\Stream\\": "src/" + "Facebook\\WebDriver\\": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" - ], - "authors": [ - { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" - } + "Apache-2.0" ], - "description": "Provides a simple abstraction over streams of data", - "homepage": "http://guzzlephp.org/", + "description": "A PHP client for WebDriver", + "homepage": "https://github.com/facebook/php-webdriver", "keywords": [ - "Guzzle", - "stream" + "facebook", + "php", + "selenium", + "webdriver" ], - "time": "2014-10-12 19:18:40" + "time": "2015-12-31 15:58:49" }, { "name": "michelf/php-markdown", @@ -2282,50 +2274,6 @@ "time": "2013-03-08 08:21:40" }, { - "name": "react/promise", - "version": "v2.2.1", - "source": { - "type": "git", - "url": "https://github.com/reactphp/promise.git", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/3b6fca09c7d56321057fa8867c8dbe1abf648627", - "reference": "3b6fca09c7d56321057fa8867c8dbe1abf648627", - "shasum": "" - }, - "require": { - "php": ">=5.4.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.0-dev" - } - }, - "autoload": { - "psr-4": { - "React\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jan Sorgalla", - "email": "jsorgalla@gmail.com" - } - ], - "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2015-07-03 13:48:55" - }, - { "name": "sami/sami", "version": "v1.4.1", "source": { diff --git a/phpBB/config/default/container/services_files.yml b/phpBB/config/default/container/services_files.yml index 39277bcd9d..88414d89a9 100644 --- a/phpBB/config/default/container/services_files.yml +++ b/phpBB/config/default/container/services_files.yml @@ -49,6 +49,7 @@ services: class: phpbb\files\types\remote scope: prototype arguments: + - '@config' - '@files.factory' - '@language' - '@php_ini' diff --git a/phpBB/config/installer/container/services_install_controller.yml b/phpBB/config/installer/container/services_install_controller.yml index 5be28c5746..5688c61db9 100644 --- a/phpBB/config/installer/container/services_install_controller.yml +++ b/phpBB/config/installer/container/services_install_controller.yml @@ -49,3 +49,18 @@ services: class: phpbb\install\controller\archive_download arguments: - '@installer.helper.config' + + phpbb.installer.controller.convert: + class: phpbb\convert\controller\convertor + arguments: + - '@installer.helper.container_factory' + - '@installer.helper.database' + - '@phpbb.installer.controller.helper' + - '@installer.helper.install_helper' + - '@installer.helper.iohandler_factory' + - '@language' + - '@installer.navigation.provider' + - '@request' + - '@template' + - '%core.root_path%' + - '%core.php_ext%' diff --git a/phpBB/config/installer/container/services_install_navigation.yml b/phpBB/config/installer/container/services_install_navigation.yml index 301d6f3434..4fc6abb6eb 100644 --- a/phpBB/config/installer/container/services_install_navigation.yml +++ b/phpBB/config/installer/container/services_install_navigation.yml @@ -33,3 +33,10 @@ services: tags: - { name: installer.navigation } + installer.navigation.convertor_navigation: + class: phpbb\install\helper\navigation\convertor_navigation + arguments: + - '@installer.helper.install_helper' + scope: prototype + tags: + - { name: installer.navigation } diff --git a/phpBB/config/installer/container/services_update_requirements.yml b/phpBB/config/installer/container/services_update_requirements.yml index c5272ef549..6b851de78b 100644 --- a/phpBB/config/installer/container/services_update_requirements.yml +++ b/phpBB/config/installer/container/services_update_requirements.yml @@ -15,6 +15,7 @@ services: arguments: - '@installer.helper.container_factory' - '@filesystem' + - '@installer.helper.config' - '@installer.helper.iohandler' - '@installer.helper.update_helper' - '%core.root_path%' diff --git a/phpBB/config/installer/routing/installer.yml b/phpBB/config/installer/routing/installer.yml index 6190799737..1961ba8ed6 100644 --- a/phpBB/config/installer/routing/installer.yml +++ b/phpBB/config/installer/routing/installer.yml @@ -35,3 +35,28 @@ phpbb_installer_update_conflict_download: path: /download/conflict defaults: _controller: phpbb.installer.controller.file_downloader:conflict_archive + +phpbb_convert_intro: + path: /convert/{start_new} + defaults: + _controller: phpbb.installer.controller.convert:intro + start_new: 0 + +phpbb_convert_settings: + path: /convert/settings/{convertor} + defaults: + _controller: phpbb.installer.controller.convert:settings + requirements: + converter: "[a-zA-Z0-9_]+" + +phpbb_convert_convert: + path: /convert/in_progress/{converter} + defaults: + _controller: phpbb.installer.controller.convert:convert + requirements: + converter: "[a-zA-Z0-9_]+" + +phpbb_convert_finish: + path: /convert/finished + defaults: + _controller: phpbb.installer.controller.convert:finish diff --git a/phpBB/docs/CHANGELOG.html b/phpBB/docs/CHANGELOG.html index b77af13d08..f6e63196ee 100644 --- a/phpBB/docs/CHANGELOG.html +++ b/phpBB/docs/CHANGELOG.html @@ -49,8 +49,10 @@ <ol> <li><a href="#changelog">Changelog</a> <ul> + <li><a href="#v320a2">Changes since 3.2.0-a2</a></li> <li><a href="#v320a1">Changes since 3.2.0-a1</a></li> <li><a href="#v31x">Changes since 3.1.x</a></li> + <li><a href="#v317pl1">Changes since 3.1.7-PL1</a></li> <li><a href="#v317">Changes since 3.1.7</a></li> <li><a href="#v316">Changes since 3.1.6</a></li> <li><a href="#v315">Changes since 3.1.5</a></li> @@ -115,9 +117,56 @@ <div class="paragraph"> <div class="inner"> - <div class="content"> +<div class="content"> + + <a name="v320a2"></a><h3>Changes since 3.2.0-a2</h3> + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-10628">PHPBB3-10628</a>] - http:// prepended to "www." urls (but not reflected in preview)</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-11875">PHPBB3-11875</a>] - mediumint(8) too small for post_id</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12221">PHPBB3-12221</a>] - URLs Containing javascript: are Garbled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14129">PHPBB3-14129</a>] - Adding custom extensions autoloaders feature slow downs the board</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14321">PHPBB3-14321</a>] - Fatal error on download the merged conflicts archive during update from 3.1.6 to 3.2-a1</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14323">PHPBB3-14323</a>] - Long urls are no longer shortened</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14368">PHPBB3-14368</a>] - Post Editors Text Should Be Black, Not Blue</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14371">PHPBB3-14371</a>] - Small fix for the aligment quick links</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14373">PHPBB3-14373</a>] - Do not use strpos() on arrays in iohandler_base::add_error_message()</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14378">PHPBB3-14378</a>] - Maintain consistent template var paths in 3.2 installer</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14380">PHPBB3-14380</a>] - Maintain consistent template var paths in 3.2 installer</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14402">PHPBB3-14402</a>] - Tidy plupload cron should not rely on user id/ip being available</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14403">PHPBB3-14403</a>] - phpbb\log should still work even when no user data is given</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14405">PHPBB3-14405</a>] - Text processor parses invalid use of url bbcode</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14419">PHPBB3-14419</a>] - Update composer dependencies and fix outdated composer lock file</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14420">PHPBB3-14420</a>] - Search Results pagination not up to date / broken</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14428">PHPBB3-14428</a>] - Use other links for files remote test</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14431">PHPBB3-14431</a>] - Remote avatar uploading does not support https</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14432">PHPBB3-14432</a>] - The lang() function needs to handle key array</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14434">PHPBB3-14434</a>] - Schema generator fails if extensions have non-migrations in migrations dir</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14436">PHPBB3-14436</a>] - Default data type migration misses oauth_states dependency</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14442">PHPBB3-14442</a>] - Use Goutte ~2.0 after allowing PHP >= 5.4</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14444">PHPBB3-14444</a>] - Fatal error in functions_messenger.php</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14446">PHPBB3-14446</a>] - Add predefined placeholder variables to twig</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14452">PHPBB3-14452</a>] - Undefined $progressFillerText in installer.js</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14453">PHPBB3-14453</a>] - Missing dependency in the text_reparser migration</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13454">PHPBB3-13454</a>] - Remove unused variables, globals, parameters</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13733">PHPBB3-13733</a>] - Allow non-migration files inside migrations folder</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14177">PHPBB3-14177</a>] - Catch exceptions and display a nice error page</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14253">PHPBB3-14253</a>] - Show group requests pending aproval at the ACP groups summary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14377">PHPBB3-14377</a>] - Allow extensions to register custom compiler pass</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14418">PHPBB3-14418</a>] - Add missing language string PM_TOOLS</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14445">PHPBB3-14445</a>] - Force page refresh before the installer generates the schema</li> + </ul> + <h4>Task</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14250">PHPBB3-14250</a>] - Review/bump composer dependencies</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14262">PHPBB3-14262</a>] - Move converter code into a controller</li> + </ul> - <a name="v320a1"></a><h3>Changes since 3.2.0-a1</h3><h4>Bug</h4> + <a name="v320a1"></a><h3>Changes since 3.2.0-a1</h3> + <h4>Bug</h4> <ul> <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-9791">PHPBB3-9791</a>] - invalid [] - chars on search URI</li> <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13451">PHPBB3-13451</a>] - A very long string inside message crashes PHP</li> @@ -389,6 +438,42 @@ <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14265">PHPBB3-14265</a>] - Make all tables available in the container</li> </ul> + <a name="v317pl1"></a><h3>Changes since 3.1.7-PL1</h3> + + <h4>Bug</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12441">PHPBB3-12441</a>] - Database-size in ACP missing after update MariaDB from 5.5 to 10.0</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-12618">PHPBB3-12618</a>] - Extension Version Check does not support https</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13180">PHPBB3-13180</a>] - Increase the field size of date format to allow more syntax for other calendars</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-13908">PHPBB3-13908</a>] - After clause in migration add_column schema tool not honored</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14046">PHPBB3-14046</a>] - Instant message (jabber) dialog says message sent on the creation screen</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14303">PHPBB3-14303</a>] - Some changes for UTF-8 variant on language pack?</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14374">PHPBB3-14374</a>] - Update dynamically generated jquery CDN script tag</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14386">PHPBB3-14386</a>] - open_basedir restriction in effect with remote upload avatar</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14387">PHPBB3-14387</a>] - Extend avatar-driver by extension in ACP not possible</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14394">PHPBB3-14394</a>] - Only purge cache in functional tests if necessary</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14396">PHPBB3-14396</a>] - Use VCHAR_UNI instead of VCHAR for user_dateformat</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14397">PHPBB3-14397</a>] - Fix @since tag in event 'core.ucp_prefs_view_after'</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14403">PHPBB3-14403</a>] - phpbb\log should still work even when no user data is given</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14407">PHPBB3-14407</a>] - Users not being removed from Newly Registered Users group</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14409">PHPBB3-14409</a>] - Update session page info before displaying online list</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14411">PHPBB3-14411</a>] - Delete permanently is not working as it should be</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14423">PHPBB3-14423</a>] - Display database size for Aria storage engine</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14425">PHPBB3-14425</a>] - Database tests do not allow using socket</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14427">PHPBB3-14427</a>] - Memberlist Display Wrong</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14433">PHPBB3-14433</a>] - Functional tests fail for extensions</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14439">PHPBB3-14439</a>] - Error page shown in Manage users -> Anonymous -> Select Form -> Avatar when board wide all avatar settings are disabled</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14467">PHPBB3-14467</a>] - Automatic resize of textarea calculates wrong height</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14475">PHPBB3-14475</a>] - Do not log removal of users from newly registered group</li> + </ul> + <h4>Improvement</h4> + <ul> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14289">PHPBB3-14289</a>] - Add events in navbar header</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14356">PHPBB3-14356</a>] - Add template events to viewtopic around back2top link</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14412">PHPBB3-14412</a>] - Comment fixes for PHPDoc in the events</li> + <li>[<a href="http://tracker.phpbb.com/browse/PHPBB3-14458">PHPBB3-14458</a>] - Explicitly state RewriteBase into .htaccess root file</li> + </ul> + <a name="v317"></a><h3>Changes since 3.1.7</h3> <h4>Security Issue</h4> diff --git a/phpBB/docs/events.md b/phpBB/docs/events.md index bb1289b74f..acc876ea96 100644 --- a/phpBB/docs/events.md +++ b/phpBB/docs/events.md @@ -2251,7 +2251,7 @@ viewtopic_body_postrow_back2top_append * Locations: + styles/prosilver/template/viewtopic_body.html * Since: 3.1.8-RC1 -* Purpose: Add content to the post's bottom directly before the back to top link +* Purpose: Add content to the post's bottom directly after the back to top link viewtopic_body_postrow_back2top_before === diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index 26663d2a62..9d65c48bed 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -415,6 +415,7 @@ class acp_board 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'referer_validation' => array('lang' => 'REFERRER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), + 'remote_upload_verify' => array('lang' => 'UPLOAD_CERT_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), 'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,), diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php index 8056abef00..f2b56cc84b 100644 --- a/phpBB/includes/constants.php +++ b/phpBB/includes/constants.php @@ -28,7 +28,7 @@ if (!defined('IN_PHPBB')) */ // phpBB Version -@define('PHPBB_VERSION', '3.2.0-a3-dev'); +@define('PHPBB_VERSION', '3.2.0-b2-dev'); // QA-related // define('PHPBB_QA', 1); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 422faaa89e..54ff51dda5 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -4146,6 +4146,8 @@ function page_header($page_title = '', $display_online_list = false, $item_id = } } + $user->update_session_infos(); + // Generate logged in/logged out status if ($user->data['user_id'] != ANONYMOUS) { @@ -4577,8 +4579,6 @@ function page_footer($run_cron = true, $display_template = true, $exit_handler = return; } - $user->update_session_infos(); - phpbb_check_and_display_sql_report($request, $auth, $db); $template->assign_vars(array( diff --git a/phpBB/includes/functions_acp.php b/phpBB/includes/functions_acp.php index d710d984b7..dc43957933 100644 --- a/phpBB/includes/functions_acp.php +++ b/phpBB/includes/functions_acp.php @@ -55,6 +55,8 @@ function adm_page_header($page_title) return; } + $user->update_session_infos(); + // gzip_compression if ($config['gzip_compress']) { @@ -166,8 +168,6 @@ function adm_page_footer($copyright_html = true) return; } - $user->update_session_infos(); - phpbb_check_and_display_sql_report($request, $auth, $db); $template->assign_vars(array( diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index e1c687551b..bbf00735af 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -2764,7 +2764,7 @@ function group_user_add($group_id, $user_id_ary = false, $username_ary = false, * * @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER' */ -function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) +function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $log_action = true) { global $db, $auth, $config, $user, $phpbb_dispatcher, $phpbb_container, $phpbb_log; @@ -2899,16 +2899,19 @@ function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $vars = array('group_id', 'group_name', 'user_id_ary', 'username_ary'); extract($phpbb_dispatcher->trigger_event('core.group_delete_user_after', compact($vars))); - if (!$group_name) + if ($log_action) { - $group_name = get_group_name($group_id); - } + if (!$group_name) + { + $group_name = get_group_name($group_id); + } - $log = 'LOG_GROUP_REMOVE'; + $log = 'LOG_GROUP_REMOVE'; - if ($group_name) - { - $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); + if ($group_name) + { + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log, false, array($group_name, implode(', ', $username_ary))); + } } group_update_listings($group_id); @@ -3555,8 +3558,8 @@ function remove_newly_registered($user_id, $user_data = false) } // We need to call group_user_del here, because this function makes sure everything is correctly changed. - // A downside for a call within the session handler is that the language is not set up yet - so no log entry - group_user_del($group_id, $user_id); + // Force function to not log the removal of users from newly registered users group + group_user_del($group_id, $user_id, false, false, false); // Set user_new to 0 to let this not be triggered again $sql = 'UPDATE ' . USERS_TABLE . ' diff --git a/phpBB/install/convert/controller/convertor.php b/phpBB/install/convert/controller/convertor.php new file mode 100644 index 0000000000..a36494c7e6 --- /dev/null +++ b/phpBB/install/convert/controller/convertor.php @@ -0,0 +1,857 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\convert\controller; + +use phpbb\exception\http_exception; +use phpbb\install\controller\helper; +use phpbb\install\helper\container_factory; +use phpbb\install\helper\database; +use phpbb\install\helper\install_helper; +use phpbb\install\helper\iohandler\factory; +use phpbb\install\helper\iohandler\iohandler_interface; +use phpbb\install\helper\navigation\navigation_provider; +use phpbb\language\language; +use phpbb\request\request_interface; +use phpbb\template\template; +use Symfony\Component\HttpFoundation\StreamedResponse; + +/** + * Controller for forum convertors + * + * WARNING: This file did not meant to be present in a production environment, so moving + * this file to a location which is accessible after board installation might + * lead to security issues. + */ +class convertor +{ + /** + * @var \phpbb\cache\driver\driver_interface + */ + protected $cache; + + /** + * @var \phpbb\config\db + */ + protected $config; + + /** + * @var \phpbb\config_php_file + */ + protected $config_php_file; + + /** + * @var string + */ + protected $config_table; + + /** + * @var helper + */ + protected $controller_helper; + + /** + * @var database + */ + protected $db_helper; + + /** + * @var \phpbb\db\driver\driver_interface + */ + protected $db; + + /** + * @var install_helper + */ + protected $install_helper; + + /** + * @var iohandler_interface + */ + protected $iohandler; + + /** + * @var language + */ + protected $language; + + /** + * @var navigation_provider + */ + protected $navigation_provider; + + /** + * @var request_interface + */ + protected $request; + + /** + * @var string + */ + protected $session_keys_table; + + /** + * @var string + */ + protected $session_table; + + /** + * @var template + */ + protected $template; + + /** + * @var string + */ + protected $phpbb_root_path; + + /** + * @var string + */ + protected $php_ext; + + /** + * Constructor + * + * @param container_factory $container + * @param database $db_helper + * @param helper $controller_helper + * @param install_helper $install_helper + * @param factory $iohandler + * @param language $language + * @param navigation_provider $nav + * @param request_interface $request + * @param template $template + * @param string $phpbb_root_path + * @param string $php_ext + */ + public function __construct(container_factory $container, database $db_helper, helper $controller_helper, install_helper $install_helper, factory $iohandler, language $language, navigation_provider $nav, request_interface $request, template $template, $phpbb_root_path, $php_ext) + { + $this->controller_helper = $controller_helper; + $this->db_helper = $db_helper; + $this->install_helper = $install_helper; + $this->language = $language; + $this->navigation_provider = $nav; + $this->request = $request; + $this->template = $template; + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + $iohandler->set_environment('ajax'); + $this->iohandler = $iohandler->get(); + + if (!$this->install_helper->is_phpbb_installed() || !defined('IN_INSTALL')) + { + throw new http_exception(403, 'INSTALL_PHPBB_NOT_INSTALLED'); + } + + $this->controller_helper->handle_language_select(); + + $this->cache = $container->get('cache.driver'); + $this->config = $container->get('config'); + $this->config_php_file = new \phpbb\config_php_file($this->phpbb_root_path, $this->php_ext); + $this->db = $container->get('dbal.conn.driver'); + + $this->config_table = $container->get_parameter('tables.config'); + $this->session_keys_table = $container->get_parameter('tables.sessions_keys'); + $this->session_table = $container->get_parameter('tables.sessions'); + } + + /** + * Render the intro page + * + * @param bool|int $start_new Whether or not to force to start a new convertor + * + * @return \Symfony\Component\HttpFoundation\Response + */ + public function intro($start_new) + { + $this->setup_navigation('intro'); + + if ($start_new) + { + if ($this->request->is_ajax()) + { + $response = new StreamedResponse(); + $iohandler = $this->iohandler; + $url = $this->controller_helper->route('phpbb_convert_intro', array('start_new' => 'new')); + $response->setCallback(function() use ($iohandler, $url) { + $iohandler->redirect($url); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + + $this->config['convert_progress'] = ''; + $this->config['convert_db_server'] = ''; + $this->config['convert_db_user'] = ''; + $this->db->sql_query('DELETE FROM ' . $this->config_table . " + WHERE config_name = 'convert_progress' + OR config_name = 'convert_db_server' + OR config_name = 'convert_db_user'" + ); + } + + // Let's see if there is a conversion in the works... + $options = array(); + if (!empty($this->config['convert_progress']) && + !empty($this->config['convert_db_server']) && + !empty($this->config['convert_db_user']) && + !empty($this->config['convert_options'])) + { + $options = unserialize($this->config['convert_progress']); + $options = array_merge($options, + unserialize($this->config['convert_db_server']), + unserialize($this->config['convert_db_user']), + unserialize($this->config['convert_options']) + ); + } + + // This information should have already been checked once, but do it again for safety + if (!empty($options) && !empty($options['tag']) && + isset($options['dbms']) && + isset($options['dbhost']) && + isset($options['dbport']) && + isset($options['dbuser']) && + isset($options['dbpasswd']) && + isset($options['dbname']) && + isset($options['table_prefix'])) + { + $this->template->assign_vars(array( + 'TITLE' => $this->language->lang('CONTINUE_CONVERT'), + 'BODY' => $this->language->lang('CONTINUE_CONVERT_BODY'), + 'S_CONTINUE' => true, + 'U_NEW_ACTION' => $this->controller_helper->route('phpbb_convert_intro', array('start_new' => 'new')), + 'U_CONTINUE_ACTION' => $this->controller_helper->route('phpbb_convert_convert', array('converter' => $options['tag'])), + )); + + return $this->controller_helper->render('installer_convert.html', 'CONTINUE_CONVERT', true); + } + + return $this->render_convert_list(); + } + + /** + * Obtain convertor settings + * + * @param string $convertor Name of the convertor + * + * @return \Symfony\Component\HttpFoundation\Response|StreamedResponse + */ + public function settings($convertor) + { + $this->setup_navigation('settings'); + + require_once ($this->phpbb_root_path . 'includes/constants.' . $this->php_ext); + require_once ($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext); + + // Include convertor if available + $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $convertor . '.' . $this->php_ext; + if (!file_exists($convertor_file_path)) + { + if ($this->request->is_ajax()) + { + $response = new StreamedResponse(); + $ref = $this; + $response->setCallback(function() use ($ref) { + $ref->render_error('CONVERT_NOT_EXIST'); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + + $this->render_error('CONVERT_NOT_EXIST'); + return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true); + } + + $get_info = true; + $phpbb_root_path = $this->phpbb_root_path; // These globals are required + $phpEx = $this->php_ext; // See above + include_once ($convertor_file_path); + + // The test_file is a file that should be present in the location of the old board. + if (!isset($test_file)) + { + if ($this->request->is_ajax()) + { + $response = new StreamedResponse(); + $ref = $this; + $response->setCallback(function() use ($ref) { + $ref->render_error('DEV_NO_TEST_FILE'); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + + $this->render_error('DEV_NO_TEST_FILE'); + return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true); + } + + if ($this->request->variable('submit', false)) + { + // It must be an AJAX request at this point + $response = new StreamedResponse(); + $ref = $this; + $response->setCallback(function() use ($ref, $convertor) { + $ref->proccess_settings_form($convertor); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + else + { + $this->template->assign_vars(array( + 'U_ACTION' => $this->controller_helper->route('phpbb_convert_settings', array( + 'convertor' => $convertor, + )) + )); + + if ($this->request->is_ajax()) + { + $response = new StreamedResponse(); + $ref = $this; + $response->setCallback(function() use ($ref) { + $ref->render_settings_form(); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + + $this->render_settings_form(); + } + + return $this->controller_helper->render('installer_convert.html', 'STAGE_SETTINGS', true); + } + + /** + * Run conversion + */ + public function convert($converter) + { + $this->setup_navigation('convert'); + + if ($this->request->is_ajax()) + { + $route = $this->controller_helper->route('phpbb_convert_convert', array('converter' => $converter)); + $response = new StreamedResponse(); + $ref = $this; + $response->setCallback(function() use ($ref, $route) { + $ref->redirect_to_html($route); + }); + $response->headers->set('X-Accel-Buffering', 'no'); + + return $response; + } + + $convertor = new \phpbb\convert\convertor($this->template, $this->controller_helper); + $convertor->convert_data($converter); + + return $this->controller_helper->render('installer_convert.html', 'STAGE_IN_PROGRESS'); + } + + /** + * Render the final page of the convertor + */ + public function finish() + { + $this->setup_navigation('finish'); + + $this->template->assign_vars(array( + 'TITLE' => $this->language->lang('CONVERT_COMPLETE'), + 'BODY' => $this->language->lang('CONVERT_COMPLETE_EXPLAIN'), + )); + + // If we reached this step (conversion completed) we want to purge the cache and log the user out. + // This is for making sure the session get not screwed due to the 3.0.x users table being completely new. + $this->cache->purge(); + + require_once($this->phpbb_root_path . 'includes/constants.' . $this->php_ext); + require_once($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext); + + $sql = 'SELECT config_value + FROM ' . $this->config_table . ' + WHERE config_name = \'search_type\''; + $result = $this->db->sql_query($sql); + + if ($this->db->sql_fetchfield('config_value') != 'fulltext_mysql') + { + $this->template->assign_vars(array( + 'S_ERROR_BOX' => true, + 'ERROR_TITLE' => $this->language->lang('SEARCH_INDEX_UNCONVERTED'), + 'ERROR_MSG' => $this->language->lang('SEARCH_INDEX_UNCONVERTED_EXPLAIN'), + )); + } + + $this->db->sql_freeresult($result); + + switch ($this->db->get_sql_layer()) + { + case 'sqlite': + case 'sqlite3': + $this->db->sql_query('DELETE FROM ' . $this->session_keys_table); + $this->db->sql_query('DELETE FROM ' . $this->session_table); + break; + + default: + $this->db->sql_query('TRUNCATE TABLE ' . $this->session_keys_table); + $this->db->sql_query('TRUNCATE TABLE ' . $this->session_table); + break; + } + + return $this->controller_helper->render('installer_convert.html', 'CONVERT_COMPLETE'); + } + + /** + * Validates settings form + * + * @param string $convertor + */ + public function proccess_settings_form($convertor) + { + global $phpbb_root_path, $phpEx, $get_info; + + $phpbb_root_path = $this->phpbb_root_path; + $phpEx = $this->php_ext; + $get_info = true; + + require_once($this->phpbb_root_path . 'includes/constants.' . $this->php_ext); + require_once($this->phpbb_root_path . 'includes/functions_convert.' . $this->php_ext); + + // Include convertor if available + $convertor_file_path = $this->phpbb_root_path . 'install/convertors/convert_' . $convertor . '.' . $this->php_ext; + include ($convertor_file_path); + + // We expect to have an AJAX request here + $src_dbms = $this->request->variable('src_dbms', $convertor_data['dbms']); + $src_dbhost = $this->request->variable('src_dbhost', $convertor_data['dbhost']); + $src_dbport = $this->request->variable('src_dbport', $convertor_data['dbport']); + $src_dbuser = $this->request->variable('src_dbuser', $convertor_data['dbuser']); + $src_dbpasswd = $this->request->variable('src_dbpasswd', $convertor_data['dbpasswd']); + $src_dbname = $this->request->variable('src_dbname', $convertor_data['dbname']); + $src_table_prefix = $this->request->variable('src_table_prefix', $convertor_data['table_prefix']); + $forum_path = $this->request->variable('forum_path', $convertor_data['forum_path']); + $refresh = $this->request->variable('refresh', 1); + + // Default URL of the old board + // @todo Are we going to use this for attempting to convert URL references in posts, or should we remove it? + // -> We should convert old urls to the new relative urls format + // $src_url = $request->variable('src_url', 'Not in use at the moment'); + + // strip trailing slash from old forum path + $forum_path = (strlen($forum_path) && $forum_path[strlen($forum_path) - 1] == '/') ? substr($forum_path, 0, -1) : $forum_path; + + $error = array(); + if (!file_exists($this->phpbb_root_path . $forum_path . '/' . $test_file)) + { + $error[] = $this->language->lang('COULD_NOT_FIND_PATH', $forum_path); + } + + $connect_test = false; + $available_dbms = $this->db_helper->get_available_dbms(false, true, true); + if (!isset($available_dbms[$src_dbms]) || !$available_dbms[$src_dbms]['AVAILABLE']) + { + $error[] = $this->language->lang('INST_ERR_NO_DB'); + } + else + { + $connect_test = $this->db_helper->check_database_connection($src_dbms, $src_dbhost, $src_dbport, $src_dbuser, $src_dbpasswd, $src_dbname, $src_table_prefix); + } + + extract($this->config_php_file->get_all()); + + // The forum prefix of the old and the new forum can only be the same if two different databases are used. + if ($src_table_prefix === $table_prefix && $src_dbms === $dbms && $src_dbhost === $dbhost && $src_dbport === $dbport && $src_dbname === $dbname) + { + $error[] = $this->language->lang('TABLE_PREFIX_SAME', $src_table_prefix); + } + + if (!$connect_test) + { + $error[] = $this->language->lang('INST_ERR_DB_CONNECT'); + } + + $src_dbms = $this->config_php_file->convert_30_dbms_to_31($src_dbms); + + // Check table prefix + if (empty($error)) + { + // initiate database connection to old db if old and new db differ + global $src_db, $same_db; + $src_db = $same_db = false; + + if ($src_dbms != $dbms || $src_dbhost != $dbhost || $src_dbport != $dbport || $src_dbname != $dbname || $src_dbuser != $dbuser) + { + /** @var \phpbb\db\driver\driver_interface $src_db */ + $src_db = new $src_dbms(); + $src_db->sql_connect($src_dbhost, $src_dbuser, htmlspecialchars_decode($src_dbpasswd), $src_dbname, $src_dbport, false, true); + $same_db = false; + } + else + { + $src_db = $this->db; + $same_db = true; + } + + $src_db->sql_return_on_error(true); + $this->db->sql_return_on_error(true); + + // Try to select one row from the first table to see if the prefix is OK + $result = $src_db->sql_query_limit('SELECT * FROM ' . $src_table_prefix . $tables[0], 1); + + if (!$result) + { + $prefixes = array(); + + $db_tools_factory = new \phpbb\db\tools\factory(); + $db_tools = $db_tools_factory->get($src_db); + $tables_existing = $db_tools->sql_list_tables(); + $tables_existing = array_map('strtolower', $tables_existing); + foreach ($tables_existing as $table_name) + { + compare_table($tables, $table_name, $prefixes); + } + unset($tables_existing); + + foreach ($prefixes as $prefix => $count) + { + if ($count >= sizeof($tables)) + { + $possible_prefix = $prefix; + break; + } + } + + $msg = ''; + if (!empty($convertor_data['table_prefix'])) + { + $msg .= $this->language->lang_array('DEFAULT_PREFIX_IS', array($convertor_data['forum_name'], $convertor_data['table_prefix'])); + } + + if (!empty($possible_prefix)) + { + $msg .= '<br />'; + $msg .= ($possible_prefix == '*') ? $this->language->lang('BLANK_PREFIX_FOUND') : $this->language->lang_array('PREFIX_FOUND', array($possible_prefix)); + $src_table_prefix = ($possible_prefix == '*') ? '' : $possible_prefix; + } + + $error[] = $msg; + } + + $src_db->sql_freeresult($result); + $src_db->sql_return_on_error(false); + } + + if (empty($error)) + { + // Save convertor Status + $this->config->set('convert_progress', serialize(array( + 'step' => '', + 'table_prefix' => $src_table_prefix, + 'tag' => $convertor, + )), false); + $this->config->set('convert_db_server', serialize(array( + 'dbms' => $src_dbms, + 'dbhost' => $src_dbhost, + 'dbport' => $src_dbport, + 'dbname' => $src_dbname, + )), false); + $this->config->set('convert_db_user', serialize(array( + 'dbuser' => $src_dbuser, + 'dbpasswd' => $src_dbpasswd, + )), false); + + // Save options + $this->config->set('convert_options', serialize(array( + 'forum_path' => $this->phpbb_root_path . $forum_path, + 'refresh' => $refresh + )), false); + + $url = $this->controller_helper->route('phpbb_convert_convert', array('converter' => $convertor)); + $this->iohandler->redirect($url); + $this->iohandler->send_response(); + } + else + { + $this->render_settings_form($error); + } + } + + /** + * Renders settings form + * + * @param array $error Array of errors + */ + public function render_settings_form($error = array()) + { + foreach ($error as $msg) + { + $this->iohandler->add_error_message($msg); + } + + $dbms_options = array(); + foreach ($this->db_helper->get_available_dbms() as $dbms_key => $dbms_array) + { + $dbms_options[] = array( + 'value' => $dbms_key, + 'label' => 'DB_OPTION_' . strtoupper($dbms_key), + ); + } + + $form_title = 'SPECIFY_OPTIONS'; + $form_data = array( + 'src_dbms' => array( + 'label' => 'DBMS', + 'type' => 'select', + 'options' => $dbms_options, + ), + 'src_dbhost' => array( + 'label' => 'DB_HOST', + 'description' => 'DB_HOST_EXPLAIN', + 'type' => 'text', + ), + 'src_dbport' => array( + 'label' => 'DB_PORT', + 'description' => 'DB_PORT_EXPLAIN', + 'type' => 'text', + ), + 'src_dbname' => array( + 'label' => 'DB_NAME', + 'type' => 'text', + ), + 'src_dbuser' => array( + 'label' => 'DB_USERNAME', + 'type' => 'text', + ), + 'src_dbpasswd' => array( + 'label' => 'DB_PASSWORD', + 'type' => 'password', + ), + 'src_table_prefix' => array( + 'label' => 'TABLE_PREFIX', + 'description' => 'TABLE_PREFIX_EXPLAIN', + 'type' => 'text', + ), + 'forum_path' => array( + 'label' => 'FORUM_PATH', + 'description' => 'FORUM_PATH_EXPLAIN', + 'type' => 'text', + ), + 'refresh' => array( + 'label' => 'REFRESH_PAGE', + 'description' => 'REFRESH_PAGE_EXPLAIN', + 'type' => 'radio', + 'options' => array( + array( + 'value' => 0, + 'label' => 'NO', + 'selected' => true, + ), + array( + 'value' => 1, + 'label' => 'YES', + 'selected' => false, + ), + ), + ), + 'submit' => array( + 'label' => 'SUBMIT', + 'type' => 'submit', + ), + ); + + if ($this->request->is_ajax()) + { + $this->iohandler->add_user_form_group($form_title, $form_data); + $this->iohandler->send_response(); + } + else + { + $rendered_form = $this->iohandler->generate_form_render_data($form_title, $form_data); + + $this->template->assign_vars(array( + 'TITLE' => $this->language->lang('STAGE_SETTINGS'), + 'CONTENT' => $rendered_form, + )); + } + } + + /** + * Render the list of available convertors + * + * @return \Symfony\Component\HttpFoundation\Response + */ + protected function render_convert_list() + { + $this->template->assign_vars(array( + 'TITLE' => $this->language->lang('CONVERT_INTRO'), + 'BODY' => $this->language->lang('CONVERT_INTRO_BODY'), + 'S_LIST' => true, + )); + + $convertors = $sort = array(); + $get_info = true; // Global flag + + $handle = @opendir($this->phpbb_root_path . 'install/convertors/'); + + if (!$handle) + { + die('Unable to access the convertors directory'); + } + + while ($entry = readdir($handle)) + { + if (preg_match('/^convert_([a-z0-9_]+).' . $this->php_ext . '$/i', $entry, $m)) + { + $phpbb_root_path = $this->phpbb_root_path; // These globals are required + $phpEx = $this->php_ext; // See above + include_once($this->phpbb_root_path . 'install/convertors/' . $entry); + if (isset($convertor_data)) + { + $sort[strtolower($convertor_data['forum_name'])] = sizeof($convertors); + + $convertors[] = array( + 'tag' => $m[1], + 'forum_name' => $convertor_data['forum_name'], + 'version' => $convertor_data['version'], + 'dbms' => $convertor_data['dbms'], + 'dbhost' => $convertor_data['dbhost'], + 'dbport' => $convertor_data['dbport'], + 'dbuser' => $convertor_data['dbuser'], + 'dbpasswd' => $convertor_data['dbpasswd'], + 'dbname' => $convertor_data['dbname'], + 'table_prefix' => $convertor_data['table_prefix'], + 'author' => $convertor_data['author'] + ); + } + unset($convertor_data); + } + } + closedir($handle); + + @ksort($sort); + + foreach ($sort as $void => $index) + { + $this->template->assign_block_vars('convertors', array( + 'AUTHOR' => $convertors[$index]['author'], + 'SOFTWARE' => $convertors[$index]['forum_name'], + 'VERSION' => $convertors[$index]['version'], + + 'U_CONVERT' => $this->controller_helper->route('phpbb_convert_settings', array('convertor' => $convertors[$index]['tag'])), + )); + } + + return $this->controller_helper->render('installer_convert.html', 'SUB_INTRO', true); + } + + /** + * Renders an error form + * + * @param string $msg + * @param string|bool $desc + */ + public function render_error($msg, $desc = false) + { + if ($this->request->is_ajax()) + { + $this->iohandler->add_error_message($msg, $desc); + $this->iohandler->send_response(); + } + else + { + $this->template->assign_vars(array( + 'S_ERROR_BOX' => true, + 'ERROR_TITLE' => $this->language->lang($msg), + )); + + if ($desc) + { + $this->template->assign_var('ERROR_MSG', $this->language->lang($desc)); + } + } + } + + /** + * Redirects an AJAX request to a non-JS version + * + * @param string $url URL to redirect to + */ + public function redirect_to_html($url) + { + $this->iohandler->redirect($url); + $this->iohandler->send_response(); + } + + private function setup_navigation($stage) + { + $active = true; + $completed = false; + + switch ($stage) + { + case 'finish': + $this->navigation_provider->set_nav_property( + array('convert', 0, 'finish'), + array( + 'selected' => $active, + 'completed' => $completed, + ) + ); + + $active = false; + $completed = true; + // no break; + + case 'convert': + $this->navigation_provider->set_nav_property( + array('convert', 0, 'convert'), + array( + 'selected' => $active, + 'completed' => $completed, + ) + ); + + $active = false; + $completed = true; + // no break; + + case 'settings': + $this->navigation_provider->set_nav_property( + array('convert', 0, 'settings'), + array( + 'selected' => $active, + 'completed' => $completed, + ) + ); + + $active = false; + $completed = true; + // no break; + + case 'intro': + $this->navigation_provider->set_nav_property( + array('convert', 0, 'intro'), + array( + 'selected' => $active, + 'completed' => $completed, + ) + ); + break; + } + } +} diff --git a/phpBB/install/convert/convert.php b/phpBB/install/convert/convert.php new file mode 100644 index 0000000000..03913d6ae6 --- /dev/null +++ b/phpBB/install/convert/convert.php @@ -0,0 +1,60 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\convert; + +/** + * Class holding all convertor-specific details. + * + * WARNING: This file did not meant to be present in a production environment, so moving this file to a location which + * is accessible after board installation might lead to security issues. + */ +class convert +{ + var $options = array(); + + var $convertor_tag = ''; + var $src_dbms = ''; + var $src_dbhost = ''; + var $src_dbport = ''; + var $src_dbuser = ''; + var $src_dbpasswd = ''; + var $src_dbname = ''; + var $src_table_prefix = ''; + + var $convertor_data = array(); + var $tables = array(); + var $config_schema = array(); + var $convertor = array(); + var $src_truncate_statement = 'DELETE FROM '; + var $truncate_statement = 'DELETE FROM '; + + var $fulltext_search; + + // Batch size, can be adjusted by the conversion file + // For big boards a value of 6000 seems to be optimal + var $batch_size = 2000; + // Number of rows to be inserted at once (extended insert) if supported + // For installations having enough memory a value of 60 may be good. + var $num_wait_rows = 20; + + // Mysqls internal recoding engine messing up with our (better) functions? We at least support more encodings than mysql so should use it in favor. + var $mysql_convert = false; + + var $p_master; + + function convert($p_master) + { + $this->p_master = $p_master; + } +} diff --git a/phpBB/install/convert/convertor.php b/phpBB/install/convert/convertor.php new file mode 100644 index 0000000000..2dae356c26 --- /dev/null +++ b/phpBB/install/convert/convertor.php @@ -0,0 +1,1618 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\convert; + +use phpbb\install\controller\helper; +use phpbb\template\template; + +/** + * Convertor backend class + * + * WARNING: This file did not meant to be present in a production environment, so moving this file to a location which + * is accessible after board installation might lead to security issues. + */ +class convertor +{ + /** + * @var helper + */ + protected $controller_helper; + + /** + * @var \phpbb\filesystem\filesystem + */ + protected $filesystem; + + /** + * @var \phpbb\template\template + */ + protected $template; + + /** + * Constructor + * + * @param template $template + * @param helper $controller_helper + */ + public function __construct(template $template, helper $controller_helper) + { + global $convert, $phpbb_filesystem; + + $this->template = $template; + $this->filesystem = $phpbb_filesystem; + $this->controller_helper = $controller_helper; + + $convert = new convert($this); + } + + /** + * The function which does the actual work (or dispatches it to the relevant places) + */ + function convert_data($converter) + { + global $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache, $auth; + global $convert, $convert_row, $message_parser, $skip_rows, $language; + global $request, $phpbb_dispatcher; + + $phpbb_config_php_file = new \phpbb\config_php_file($phpbb_root_path, $phpEx); + extract($phpbb_config_php_file->get_all()); + + require_once($phpbb_root_path . 'includes/constants.' . $phpEx); + require_once($phpbb_root_path . 'includes/functions_convert.' . $phpEx); + + $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); + + /** @var \phpbb\db\driver\driver_interface $db */ + $db = new $dbms(); + $db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true); + unset($dbpasswd); + + // We need to fill the config to let internal functions correctly work + $config = new \phpbb\config\db($db, new \phpbb\cache\driver\dummy, CONFIG_TABLE); + + // Override a couple of config variables for the duration + $config['max_quote_depth'] = 0; + + // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues + $config['max_post_chars'] = $config['min_post_chars'] = 0; + + // Set up a user as well. We _should_ have enough of a database here at this point to do this + // and it helps for any core code we call + $user->session_begin(); + $user->page = $user->extract_current_page($phpbb_root_path); + + $convert->options = array(); + if (isset($config['convert_progress'])) + { + $convert->options = unserialize($config['convert_progress']); + $convert->options = array_merge($convert->options, unserialize($config['convert_db_server']), unserialize($config['convert_db_user']), unserialize($config['convert_options'])); + } + + // This information should have already been checked once, but do it again for safety + if (empty($convert->options) || empty($convert->options['tag']) || + !isset($convert->options['dbms']) || + !isset($convert->options['dbhost']) || + !isset($convert->options['dbport']) || + !isset($convert->options['dbuser']) || + !isset($convert->options['dbpasswd']) || + !isset($convert->options['dbname']) || + !isset($convert->options['table_prefix'])) + { + $this->error($user->lang['NO_CONVERT_SPECIFIED'], __LINE__, __FILE__); + } + + $this->template->assign_var('S_CONV_IN_PROGRESS', true); + + // Make some short variables accessible, for easier referencing + $convert->convertor_tag = basename($convert->options['tag']); + $convert->src_dbms = $convert->options['dbms']; + $convert->src_dbhost = $convert->options['dbhost']; + $convert->src_dbport = $convert->options['dbport']; + $convert->src_dbuser = $convert->options['dbuser']; + $convert->src_dbpasswd = $convert->options['dbpasswd']; + $convert->src_dbname = $convert->options['dbname']; + $convert->src_table_prefix = $convert->options['table_prefix']; + + // initiate database connection to old db if old and new db differ + global $src_db, $same_db; + $src_db = $same_db = null; + if ($convert->src_dbms != $dbms || $convert->src_dbhost != $dbhost || $convert->src_dbport != $dbport || $convert->src_dbname != $dbname || $convert->src_dbuser != $dbuser) + { + $dbms = $convert->src_dbms; + /** @var \phpbb\db\driver\driver $src_db */ + $src_db = new $dbms(); + $src_db->sql_connect($convert->src_dbhost, $convert->src_dbuser, htmlspecialchars_decode($convert->src_dbpasswd), $convert->src_dbname, $convert->src_dbport, false, true); + $same_db = false; + } + else + { + $src_db = $db; + $same_db = true; + } + + $convert->mysql_convert = false; + switch ($src_db->sql_layer) + { + case 'sqlite': + case 'sqlite3': + $convert->src_truncate_statement = 'DELETE FROM '; + break; + + // Thanks MySQL, for silently converting... + case 'mysql': + case 'mysql4': + if (version_compare($src_db->sql_server_info(true, false), '4.1.3', '>=')) + { + $convert->mysql_convert = true; + } + $convert->src_truncate_statement = 'TRUNCATE TABLE '; + break; + + case 'mysqli': + $convert->mysql_convert = true; + $convert->src_truncate_statement = 'TRUNCATE TABLE '; + break; + + default: + $convert->src_truncate_statement = 'TRUNCATE TABLE '; + break; + } + + if ($convert->mysql_convert && !$same_db) + { + $src_db->sql_query("SET NAMES 'binary'"); + } + + switch ($db->get_sql_layer()) + { + case 'sqlite': + case 'sqlite3': + $convert->truncate_statement = 'DELETE FROM '; + break; + + default: + $convert->truncate_statement = 'TRUNCATE TABLE '; + break; + } + + $get_info = false; + + // check security implications of direct inclusion + if (!file_exists('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx)) + { + $this->error($user->lang['CONVERT_NOT_EXIST'], __LINE__, __FILE__); + } + + if (file_exists('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx)) + { + include_once('./convertors/functions_' . $convert->convertor_tag . '.' . $phpEx); + } + + $get_info = true; + include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx); + + // Map some variables... + $convert->convertor_data = $convertor_data; + $convert->tables = $tables; + $convert->config_schema = $config_schema; + + // Now include the real data + $get_info = false; + include('./convertors/convert_' . $convert->convertor_tag . '.' . $phpEx); + + $convert->convertor_data = $convertor_data; + $convert->tables = $tables; + $convert->config_schema = $config_schema; + $convert->convertor = $convertor; + + // The test_file is a file that should be present in the location of the old board. + if (!file_exists($convert->options['forum_path'] . '/' . $test_file)) + { + $this->error(sprintf($user->lang['COULD_NOT_FIND_PATH'], $convert->options['forum_path']), __LINE__, __FILE__); + } + + $search_type = $config['search_type']; + + // For conversions we are a bit less strict and set to a search backend we know exist... + if (!class_exists($search_type)) + { + $search_type = '\phpbb\search\fulltext_native'; + $config->set('search_type', $search_type); + } + + if (!class_exists($search_type)) + { + trigger_error('NO_SUCH_SEARCH_MODULE'); + } + + $error = false; + $convert->fulltext_search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher); + + if ($error) + { + trigger_error($error); + } + + include_once($phpbb_root_path . 'includes/message_parser.' . $phpEx); + $message_parser = new \parse_message(); + + $jump = $request->variable('jump', 0); + $final_jump = $request->variable('final_jump', 0); + $sync_batch = $request->variable('sync_batch', -1); + $last_statement = $request->variable('last', 0); + + // We are running sync... + if ($sync_batch >= 0) + { + $this->sync_forums($converter, $sync_batch); + return; + } + + if ($jump) + { + $this->jump($converter, $jump, $last_statement); + return; + } + + if ($final_jump) + { + $this->final_jump($final_jump); + return; + } + + $current_table = $request->variable('current_table', 0); + $old_current_table = min(-1, $current_table - 1); + $skip_rows = $request->variable('skip_rows', 0); + + if (!$current_table && !$skip_rows) + { + if (!$request->variable('confirm', false)) + { + // If avatars / ranks / smilies folders are specified make sure they are writable + $bad_folders = array(); + + $local_paths = array( + 'avatar_path' => path($config['avatar_path']), + 'avatar_gallery_path' => path($config['avatar_gallery_path']), + 'icons_path' => path($config['icons_path']), + 'ranks_path' => path($config['ranks_path']), + 'smilies_path' => path($config['smilies_path']) + ); + + foreach ($local_paths as $folder => $local_path) + { + if (isset($convert->convertor[$folder])) + { + if (empty($convert->convertor['test_file'])) + { + // test_file is mandantory at the moment so this should never be reached, but just in case... + $this->error($user->lang['DEV_NO_TEST_FILE'], __LINE__, __FILE__); + } + + if (!$local_path || !$this->filesystem->is_writable($phpbb_root_path . $local_path)) + { + if (!$local_path) + { + $bad_folders[] = sprintf($user->lang['CONFIG_PHPBB_EMPTY'], $folder); + } + else + { + $bad_folders[] = $local_path; + } + } + } + } + + if (sizeof($bad_folders)) + { + $msg = (sizeof($bad_folders) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; + sort($bad_folders); + $this->error(sprintf($msg, implode('<br />', $bad_folders)), __LINE__, __FILE__, true); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['INSTALL_TEST'], + 'U_ACTION' => $this->controller_helper->route('phpbb_convert_convert', array('converter' => $converter)), + )); + return; + } + + // Grab all the tables used in convertor + $missing_tables = $tables_list = $aliases = array(); + + foreach ($convert->convertor['schema'] as $schema) + { + // Skip those not used (because of addons/plugins not detected) + if (!$schema['target']) + { + continue; + } + + foreach ($schema as $key => $val) + { + // we're dealing with an array like: + // array('forum_status', 'forums.forum_status', 'is_item_locked') + if (is_int($key) && !empty($val[1])) + { + $temp_data = $val[1]; + if (!is_array($temp_data)) + { + $temp_data = array($temp_data); + } + + foreach ($temp_data as $value) + { + if (preg_match('/([a-z0-9_]+)\.([a-z0-9_]+)\)* ?A?S? ?([a-z0-9_]*?)\.?([a-z0-9_]*)$/i', $value, $m)) + { + $table = $convert->src_table_prefix . $m[1]; + $tables_list[$table] = $table; + + if (!empty($m[3])) + { + $aliases[] = $convert->src_table_prefix . $m[3]; + } + } + } + } + // 'left_join' => 'topics LEFT JOIN vote_desc ON topics.topic_id = vote_desc.topic_id AND topics.topic_vote = 1' + else if ($key == 'left_join') + { + // Convert the value if it wasn't an array already. + if (!is_array($val)) + { + $val = array($val); + } + + for ($j = 0; $j < sizeof($val); ++$j) + { + if (preg_match('/LEFT JOIN ([a-z0-9_]+) AS ([a-z0-9_]+)/i', $val[$j], $m)) + { + $table = $convert->src_table_prefix . $m[1]; + $tables_list[$table] = $table; + + if (!empty($m[2])) + { + $aliases[] = $convert->src_table_prefix . $m[2]; + } + } + } + } + } + } + + // Remove aliased tables from $tables_list + foreach ($aliases as $alias) + { + unset($tables_list[$alias]); + } + + // Check if the tables that we need exist + $src_db->sql_return_on_error(true); + foreach ($tables_list as $table => $null) + { + $sql = 'SELECT 1 FROM ' . $table; + $_result = $src_db->sql_query_limit($sql, 1); + + if (!$_result) + { + $missing_tables[] = $table; + } + $src_db->sql_freeresult($_result); + } + $src_db->sql_return_on_error(false); + + // Throw an error if some tables are missing + // We used to do some guessing here, but since we have a suggestion of possible values earlier, I don't see it adding anything here to do it again + + if (sizeof($missing_tables) == sizeof($tables_list)) + { + $this->error($user->lang['NO_TABLES_FOUND'] . ' ' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); + } + else if (sizeof($missing_tables)) + { + $this->error(sprintf($user->lang['TABLES_MISSING'], implode($user->lang['COMMA_SEPARATOR'], $missing_tables)) . '<br /><br />' . $user->lang['CHECK_TABLE_PREFIX'], __LINE__, __FILE__); + } + + $url = $this->save_convert_progress($converter, 'confirm=1'); + $msg = $user->lang['PRE_CONVERT_COMPLETE']; + + if ($convert->convertor_data['author_notes']) + { + $msg .= '</p><p>' . sprintf($user->lang['AUTHOR_NOTES'], $convert->convertor_data['author_notes']); + } + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'BODY' => $msg, + 'U_ACTION' => $url, + )); + + return; + } // if (!$request->variable('confirm', false))) + + $this->template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $user->lang['STARTING_CONVERT'], + )); + + // Convert the config table and load the settings of the old board + if (!empty($convert->config_schema)) + { + restore_config($convert->config_schema); + + // Override a couple of config variables for the duration + $config['max_quote_depth'] = 0; + + // @todo Need to confirm that max post length in source is <= max post length in destination or there may be interesting formatting issues + $config['max_post_chars'] = $config['min_post_chars'] = 0; + } + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $user->lang['CONFIG_CONVERT'], + 'RESULT' => $user->lang['DONE'], + )); + + // Now process queries and execute functions that have to be executed prior to the conversion + if (!empty($convert->convertor['execute_first'])) + { + // @codingStandardsIgnoreStart + eval($convert->convertor['execute_first']); + // @codingStandardsIgnoreEnd + } + + if (!empty($convert->convertor['query_first'])) + { + if (!is_array($convert->convertor['query_first'])) + { + $convert->convertor['query_first'] = array('target', array($convert->convertor['query_first'])); + } + else if (!is_array($convert->convertor['query_first'][0])) + { + $convert->convertor['query_first'] = array(array($convert->convertor['query_first'][0], $convert->convertor['query_first'][1])); + } + + foreach ($convert->convertor['query_first'] as $query_first) + { + if ($query_first[0] == 'src') + { + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'binary'"); + } + + $src_db->sql_query($query_first[1]); + + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'utf8'"); + } + } + else + { + $db->sql_query($query_first[1]); + } + } + } + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $user->lang['PREPROCESS_STEP'], + 'RESULT' => $user->lang['DONE'], + )); + } // if (!$current_table && !$skip_rows) + + $this->template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $user->lang['FILLING_TABLES'], + )); + + // This loop takes one target table and processes it + while ($current_table < sizeof($convert->convertor['schema'])) + { + $schema = $convert->convertor['schema'][$current_table]; + + // The target table isn't set, this can be because a module (for example the attachement mod) is taking care of this. + if (empty($schema['target'])) + { + $current_table++; + continue; + } + + $this->template->assign_block_vars('checks', array( + 'TITLE' => sprintf($user->lang['FILLING_TABLE'], $schema['target']), + )); + + // This is only the case when we first start working on the tables. + if (!$skip_rows) + { + // process execute_first and query_first for this table... + if (!empty($schema['execute_first'])) + { + // @codingStandardsIgnoreStart + eval($schema['execute_first']); + // @codingStandardsIgnoreEnd + } + + if (!empty($schema['query_first'])) + { + if (!is_array($schema['query_first'])) + { + $schema['query_first'] = array('target', array($schema['query_first'])); + } + else if (!is_array($schema['query_first'][0])) + { + $schema['query_first'] = array(array($schema['query_first'][0], $schema['query_first'][1])); + } + + foreach ($schema['query_first'] as $query_first) + { + if ($query_first[0] == 'src') + { + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'binary'"); + } + $src_db->sql_query($query_first[1]); + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'utf8'"); + } + } + else + { + $db->sql_query($query_first[1]); + } + } + } + + if (!empty($schema['autoincrement'])) + { + switch ($db->get_sql_layer()) + { + case 'postgres': + $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));'); + break; + + case 'oracle': + $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $largest_id = (int) $row['max_id']; + + if ($largest_id) + { + $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq'); + $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1)); + } + break; + } + } + } + + // Process execute_always for this table + // This is for code which needs to be executed on every pass of this table if + // it gets split because of time restrictions + if (!empty($schema['execute_always'])) + { + // @codingStandardsIgnoreStart + eval($schema['execute_always']); + // @codingStandardsIgnoreEnd + } + + // + // Set up some variables + // + // $waiting_rows holds rows for multirows insertion (MySQL only) + // $src_tables holds unique tables with aliases to select from + // $src_fields will quickly refer source fields (or aliases) corresponding to the current index + // $select_fields holds the names of the fields to retrieve + // + + $sql_data = array( + 'source_fields' => array(), + 'target_fields' => array(), + 'source_tables' => array(), + 'select_fields' => array(), + ); + + // This statement is building the keys for later insertion. + $insert_query = $this->build_insert_query($schema, $sql_data, $current_table); + + // If no source table is affected, we skip the table + if (empty($sql_data['source_tables'])) + { + $skip_rows = 0; + $current_table++; + continue; + } + + $distinct = (!empty($schema['distinct'])) ? 'DISTINCT ' : ''; + + $sql = 'SELECT ' . $distinct . implode(', ', $sql_data['select_fields']) . " \nFROM " . implode(', ', $sql_data['source_tables']); + + // Where + $sql .= (!empty($schema['where'])) ? "\nWHERE (" . $schema['where'] . ')' : ''; + + // Group By + if (!empty($schema['group_by'])) + { + $schema['group_by'] = array($schema['group_by']); + foreach ($sql_data['select_fields'] as $select) + { + $alias = strpos(strtolower($select), ' as '); + $select = ($alias) ? substr($select, 0, $alias) : $select; + if (!in_array($select, $schema['group_by'])) + { + $schema['group_by'][] = $select; + } + } + } + $sql .= (!empty($schema['group_by'])) ? "\nGROUP BY " . implode(', ', $schema['group_by']) : ''; + + // Having + $sql .= (!empty($schema['having'])) ? "\nHAVING " . $schema['having'] : ''; + + // Order By + if (empty($schema['order_by']) && !empty($schema['primary'])) + { + $schema['order_by'] = $schema['primary']; + } + $sql .= (!empty($schema['order_by'])) ? "\nORDER BY " . $schema['order_by'] : ''; + + // Counting basically holds the amount of rows processed. + $counting = -1; + $batch_time = 0; + + while ($counting === -1 || ($counting >= $convert->batch_size && still_on_time())) + { + $old_current_table = $current_table; + + $rows = ''; + $waiting_rows = array(); + + if (!empty($batch_time)) + { + $mtime = explode(' ', microtime()); + $mtime = $mtime[0] + $mtime[1]; + $rows = ceil($counting/($mtime - $batch_time)) . " rows/s ($counting rows) | "; + } + + $this->template->assign_block_vars('checks', array( + 'TITLE' => "skip_rows = $skip_rows", + 'RESULT' => $rows . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] : ''), + )); + + $mtime = explode(' ', microtime()); + $batch_time = $mtime[0] + $mtime[1]; + + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'binary'"); + } + + // Take skip rows into account and only fetch batch_size amount of rows + $___result = $src_db->sql_query_limit($sql, $convert->batch_size, $skip_rows); + + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'utf8'"); + } + + // This loop processes each row + $counting = 0; + + $convert->row = $convert_row = array(); + + if (!empty($schema['autoincrement'])) + { + switch ($db->get_sql_layer()) + { + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' ON'); + break; + } + } + + // Now handle the rows until time is over or no more rows to process... + while ($counting === 0 || still_on_time()) + { + $convert_row = $src_db->sql_fetchrow($___result); + + if (!$convert_row) + { + // move to the next batch or table + break; + } + + // With this we are able to always save the last state + $convert->row = $convert_row; + + // Increment the counting variable, it stores the number of rows we have processed + $counting++; + + $insert_values = array(); + + $sql_flag = $this->process_row($schema, $sql_data, $insert_values); + + if ($sql_flag === true) + { + switch ($db->get_sql_layer()) + { + // If MySQL, we'll wait to have num_wait_rows rows to submit at once + case 'mysql': + case 'mysql4': + case 'mysqli': + $waiting_rows[] = '(' . implode(', ', $insert_values) . ')'; + + if (sizeof($waiting_rows) >= $convert->num_wait_rows) + { + $errored = false; + + $db->sql_return_on_error(true); + + if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) + { + $errored = true; + } + $db->sql_return_on_error(false); + + if ($errored) + { + $db->sql_return_on_error(true); + + // Because it errored out we will try to insert the rows one by one... most of the time this + // is caused by duplicate entries - but we also do not want to miss one... + foreach ($waiting_rows as $waiting_sql) + { + if (!$db->sql_query($insert_query . $waiting_sql)) + { + $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); + } + } + + $db->sql_return_on_error(false); + } + + $waiting_rows = array(); + } + + break; + + default: + $insert_sql = $insert_query . '(' . implode(', ', $insert_values) . ')'; + + $db->sql_return_on_error(true); + + if (!$db->sql_query($insert_sql)) + { + $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); + } + $db->sql_return_on_error(false); + + $waiting_rows = array(); + + break; + } + } + + $skip_rows++; + } + $src_db->sql_freeresult($___result); + + // We might still have some rows waiting + if (sizeof($waiting_rows)) + { + $errored = false; + $db->sql_return_on_error(true); + + if (!$db->sql_query($insert_query . implode(', ', $waiting_rows))) + { + $errored = true; + } + $db->sql_return_on_error(false); + + if ($errored) + { + $db->sql_return_on_error(true); + + // Because it errored out we will try to insert the rows one by one... most of the time this + // is caused by duplicate entries - but we also do not want to miss one... + foreach ($waiting_rows as $waiting_sql) + { + $db->sql_query($insert_query . $waiting_sql); + $this->db_error($user->lang['DB_ERR_INSERT'], htmlspecialchars($insert_query . $waiting_sql) . '<br /><br />' . htmlspecialchars(print_r($db->_sql_error(), true)), __LINE__, __FILE__, true); + } + + $db->sql_return_on_error(false); + } + + $waiting_rows = array(); + } + + if (!empty($schema['autoincrement'])) + { + switch ($db->get_sql_layer()) + { + case 'mssql': + case 'mssql_odbc': + case 'mssqlnative': + $db->sql_query('SET IDENTITY_INSERT ' . $schema['target'] . ' OFF'); + break; + + case 'postgres': + $db->sql_query("SELECT SETVAL('" . $schema['target'] . "_seq',(select case when max(" . $schema['autoincrement'] . ")>0 then max(" . $schema['autoincrement'] . ")+1 else 1 end from " . $schema['target'] . '));'); + break; + + case 'oracle': + $result = $db->sql_query('SELECT MAX(' . $schema['autoincrement'] . ') as max_id FROM ' . $schema['target']); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $largest_id = (int) $row['max_id']; + + if ($largest_id) + { + $db->sql_query('DROP SEQUENCE ' . $schema['target'] . '_seq'); + $db->sql_query('CREATE SEQUENCE ' . $schema['target'] . '_seq START WITH ' . ($largest_id + 1)); + } + break; + } + } + } + + // When we reach this point, either the current table has been processed or we're running out of time. + if (still_on_time() && $counting < $convert->batch_size/* && !defined('DEBUG')*/) + { + $skip_rows = 0; + $current_table++; + } + else + {/* + if (still_on_time() && $counting < $convert->batch_size) + { + $skip_rows = 0; + $current_table++; + }*/ + + // Looks like we ran out of time. + $url = $this->save_convert_progress($converter, 'current_table=' . $current_table . '&skip_rows=' . $skip_rows); + + $current_table++; +// $percentage = ($skip_rows == 0) ? 0 : floor(100 / ($total_rows / $skip_rows)); + + $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $current_table, sizeof($convert->convertor['schema'])); + + $this->template->assign_vars(array( + 'BODY' => $msg, + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + } + + // Process execute_last then we'll be done + $url = $this->save_convert_progress($converter, 'jump=1'); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['FINAL_STEP'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + + /** + * Sync function being executed at the middle, some functions need to be executed after a successful sync. + */ + function sync_forums($converter, $sync_batch) + { + global $user, $db, $phpbb_root_path, $phpEx, $config, $cache; + global $convert; + + include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + + $this->template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $user->lang['SYNC_TOPICS'], + )); + + $batch_size = $convert->batch_size; + + $sql = 'SELECT MIN(topic_id) as min_value, MAX(topic_id) AS max_value + FROM ' . TOPICS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Set values of minimum/maximum primary value for this table. + $primary_min = $row['min_value']; + $primary_max = $row['max_value']; + + if ($sync_batch == 0) + { + $sync_batch = (int) $primary_min; + } + + if ($sync_batch == 0) + { + $sync_batch = 1; + } + + // Fetch a batch of rows, process and insert them. + while ($sync_batch <= $primary_max && still_on_time()) + { + $end = ($sync_batch + $batch_size - 1); + + // Sync all topics in batch mode... + sync('topic', 'range', 'topic_id BETWEEN ' . $sync_batch . ' AND ' . $end, true, true); + + $this->template->assign_block_vars('checks', array( + 'TITLE' => sprintf($user->lang['SYNC_TOPIC_ID'], $sync_batch, ($sync_batch + $batch_size)) . ((defined('DEBUG') && function_exists('memory_get_usage')) ? ' [' . ceil(memory_get_usage()/1024) . ' ' . $user->lang['KIB'] . ']' : ''), + 'RESULT' => $user->lang['DONE'], + )); + + $sync_batch += $batch_size; + } + + if ($sync_batch >= $primary_max) + { + $url = $this->save_convert_progress($converter, 'final_jump=1'); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + else + { + $sync_batch--; + } + + $url = $this->save_convert_progress($converter, 'sync_batch=' . $sync_batch); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + + /** + * Save the convertor status + */ + function save_convert_progress($convertor_tag, $step) + { + global $config, $convert, $language; + + // Save convertor Status + $config->set('convert_progress', serialize(array( + 'step' => $step, + 'table_prefix' => $convert->src_table_prefix, + 'tag' => $convert->convertor_tag, + )), false); + + $config->set('convert_db_server', serialize(array( + 'dbms' => $convert->src_dbms, + 'dbhost' => $convert->src_dbhost, + 'dbport' => $convert->src_dbport, + 'dbname' => $convert->src_dbname, + )), false); + + $config->set('convert_db_user', serialize(array( + 'dbuser' => $convert->src_dbuser, + 'dbpasswd' => $convert->src_dbpasswd, + )), false); + + return $this->controller_helper->route('phpbb_convert_convert', array('converter' => $convertor_tag)) . '?' . $step; + } + + /** + * Finish conversion, the last function to be called. + */ + function finish_conversion() + { + global $db, $phpbb_root_path, $phpEx, $convert, $config, $language, $user; + global $cache, $auth, $phpbb_container, $phpbb_log; + + include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + + $db->sql_query('DELETE FROM ' . CONFIG_TABLE . " + WHERE config_name = 'convert_progress' + OR config_name = 'convert_options' + OR config_name = 'convert_db_server' + OR config_name = 'convert_db_user'"); + $db->sql_query('DELETE FROM ' . SESSIONS_TABLE); + + @unlink($phpbb_root_path . 'cache/data_global.' . $phpEx); + phpbb_cache_moderators($db, $cache, $auth); + + // And finally, add a note to the log + $phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INSTALL_CONVERTED', false, array($convert->convertor_data['forum_name'], $config['version'])); + + $url = $this->controller_helper->route('phpbb_convert_finish'); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['FINAL_STEP'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + + /** + * This function marks the steps after syncing + */ + function final_jump($final_jump) + { + global $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache; + global $convert; + + $this->template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $user->lang['PROCESS_LAST'], + )); + + if ($final_jump == 1) + { + $db->sql_return_on_error(true); + + update_topics_posted(); + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $user->lang['UPDATE_TOPICS_POSTED'], + 'RESULT' => $user->lang['DONE'], + )); + + if ($db->get_sql_error_triggered()) + { + $this->template->assign_vars(array( + 'S_ERROR_BOX' => true, + 'ERROR_TITLE' => $user->lang['UPDATE_TOPICS_POSTED'], + 'ERROR_MSG' => $user->lang['UPDATE_TOPICS_POSTED_ERR'], + )); + } + $db->sql_return_on_error(false); + + $this->finish_conversion(); + return; + } + } + + /** + * This function marks the steps before syncing (jump=1) + */ + function jump($converter, $jump, $last_statement) + { + /** @var \phpbb\db\driver\driver_interface $src_db */ + /** @var \phpbb\cache\driver\driver_interface $cache */ + global $user, $src_db, $same_db, $db, $phpbb_root_path, $phpEx, $config, $cache; + global $convert; + + include_once ($phpbb_root_path . 'includes/functions_admin.' . $phpEx); + + $this->template->assign_block_vars('checks', array( + 'S_LEGEND' => true, + 'LEGEND' => $user->lang['PROCESS_LAST'], + )); + + if ($jump == 1) + { + // Execute 'last' statements/queries + if (!empty($convert->convertor['execute_last'])) + { + if (!is_array($convert->convertor['execute_last'])) + { + // @codingStandardsIgnoreStart + eval($convert->convertor['execute_last']); + // @codingStandardsIgnoreEnd + } + else + { + while ($last_statement < sizeof($convert->convertor['execute_last'])) + { + // @codingStandardsIgnoreStart + eval($convert->convertor['execute_last'][$last_statement]); + // @codingStandardsIgnoreEnd + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $convert->convertor['execute_last'][$last_statement], + 'RESULT' => $user->lang['DONE'], + )); + + $last_statement++; + $url = $this->save_convert_progress($converter, 'jump=1&last=' . $last_statement); + + $percentage = ($last_statement == 0) ? 0 : floor(100 / (sizeof($convert->convertor['execute_last']) / $last_statement)); + $msg = sprintf($user->lang['STEP_PERCENT_COMPLETED'], $last_statement, sizeof($convert->convertor['execute_last']), $percentage); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_LAST'], + 'BODY' => $msg, + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + } + } + + if (!empty($convert->convertor['query_last'])) + { + if (!is_array($convert->convertor['query_last'])) + { + $convert->convertor['query_last'] = array('target', array($convert->convertor['query_last'])); + } + else if (!is_array($convert->convertor['query_last'][0])) + { + $convert->convertor['query_last'] = array(array($convert->convertor['query_last'][0], $convert->convertor['query_last'][1])); + } + + foreach ($convert->convertor['query_last'] as $query_last) + { + if ($query_last[0] == 'src') + { + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'binary'"); + } + + $src_db->sql_query($query_last[1]); + + if ($convert->mysql_convert && $same_db) + { + $src_db->sql_query("SET NAMES 'utf8'"); + } + } + else + { + $db->sql_query($query_last[1]); + } + } + } + + // Sanity check + $db->sql_return_on_error(false); + $src_db->sql_return_on_error(false); + + fix_empty_primary_groups(); + + $sql = 'SELECT MIN(user_regdate) AS board_startdate + FROM ' . USERS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!isset($config['board_startdate']) || ($row['board_startdate'] < $config['board_startdate'] && $row['board_startdate'] > 0)) + { + $config->set('board_startdate', $row['board_startdate']); + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_regdate = ' . $row['board_startdate'] . ' WHERE user_id = ' . ANONYMOUS); + } + + update_dynamic_config(); + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $user->lang['CLEAN_VERIFY'], + 'RESULT' => $user->lang['DONE'], + )); + + $url = $this->save_convert_progress($converter, 'jump=2'); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + + if ($jump == 2) + { + $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_permissions = ''"); + + // TODO: sync() is likely going to bomb out on forums with a considerable amount of topics. + // TODO: the sync function is able to handle FROM-TO values, we should use them here (batch processing) + sync('forum', '', '', false, true); + $cache->destroy('sql', FORUMS_TABLE); + + $this->template->assign_block_vars('checks', array( + 'TITLE' => $user->lang['SYNC_FORUMS'], + 'RESULT' => $user->lang['DONE'], + )); + + // Continue with synchronizing the forums... + $url = $this->save_convert_progress($converter, 'sync_batch=0'); + + $this->template->assign_vars(array( + 'L_SUBMIT' => $user->lang['CONTINUE_CONVERT'], + 'U_ACTION' => $url, + )); + + $this->meta_refresh($url); + return; + } + } + + function build_insert_query(&$schema, &$sql_data, $current_table) + { + global $db, $user; + global $convert; + + // Can we use IGNORE with this DBMS? + $sql_ignore = (strpos($db->get_sql_layer(), 'mysql') === 0 && !defined('DEBUG')) ? 'IGNORE ' : ''; + $insert_query = 'INSERT ' . $sql_ignore . 'INTO ' . $schema['target'] . ' ('; + + $aliases = array(); + + $sql_data = array( + 'source_fields' => array(), + 'target_fields' => array(), + 'source_tables' => array(), + 'select_fields' => array(), + ); + + foreach ($schema as $key => $val) + { + // Example: array('group_name', 'extension_groups.group_name', 'htmlspecialchars'), + if (is_int($key)) + { + if (!empty($val[0])) + { + // Target fields + $sql_data['target_fields'][$val[0]] = $key; + $insert_query .= $val[0] . ', '; + } + + if (!is_array($val[1])) + { + $val[1] = array($val[1]); + } + + foreach ($val[1] as $valkey => $value_1) + { + // This should cover about any case: + // + // table.field => SELECT table.field FROM table + // table.field AS alias => SELECT table.field AS alias FROM table + // table.field AS table2.alias => SELECT table2.field AS alias FROM table table2 + // table.field AS table2.field => SELECT table2.field FROM table table2 + // + if (preg_match('/^([a-z0-9_]+)\.([a-z0-9_]+)( +AS +(([a-z0-9_]+?)\.)?([a-z0-9_]+))?$/i', $value_1, $m)) + { + // There is 'AS ...' in the field names + if (!empty($m[3])) + { + $value_1 = ($m[2] == $m[6]) ? $m[1] . '.' . $m[2] : $m[1] . '.' . $m[2] . ' AS ' . $m[6]; + + // Table alias: store it then replace the source table with it + if (!empty($m[5]) && $m[5] != $m[1]) + { + $aliases[$m[5]] = $m[1]; + $value_1 = str_replace($m[1] . '.' . $m[2], $m[5] . '.' . $m[2], $value_1); + } + } + else + { + // No table alias + $sql_data['source_tables'][$m[1]] = (empty($convert->src_table_prefix)) ? $m[1] : $convert->src_table_prefix . $m[1] . ' ' . $m[1]; + } + + $sql_data['select_fields'][$value_1] = $value_1; + $sql_data['source_fields'][$key][$valkey] = (!empty($m[6])) ? $m[6] : $m[2]; + } + } + } + else if ($key == 'where' || $key == 'group_by' || $key == 'order_by' || $key == 'having') + { + if (@preg_match_all('/([a-z0-9_]+)\.([a-z0-9_]+)/i', $val, $m)) + { + foreach ($m[1] as $value) + { + $sql_data['source_tables'][$value] = (empty($convert->src_table_prefix)) ? $value : $convert->src_table_prefix . $value . ' ' . $value; + } + } + } + } + + // Add the aliases to the list of tables + foreach ($aliases as $alias => $table) + { + $sql_data['source_tables'][$alias] = $convert->src_table_prefix . $table . ' ' . $alias; + } + + // 'left_join' => 'forums LEFT JOIN forum_prune ON forums.forum_id = forum_prune.forum_id', + if (!empty($schema['left_join'])) + { + if (!is_array($schema['left_join'])) + { + $schema['left_join'] = array($schema['left_join']); + } + + foreach ($schema['left_join'] as $left_join) + { + // This won't handle concatened LEFT JOINs + if (!preg_match('/([a-z0-9_]+) LEFT JOIN ([a-z0-9_]+) A?S? ?([a-z0-9_]*?) ?(ON|USING)(.*)/i', $left_join, $m)) + { + $this->error(sprintf($user->lang['NOT_UNDERSTAND'], 'LEFT JOIN', $left_join, $current_table, $schema['target']), __LINE__, __FILE__); + } + + if (!empty($aliases[$m[2]])) + { + if (!empty($m[3])) + { + $this->error(sprintf($user->lang['NAMING_CONFLICT'], $m[2], $m[3], $schema['left_join']), __LINE__, __FILE__); + } + + $m[2] = $aliases[$m[2]]; + $m[3] = $m[2]; + } + + $right_table = $convert->src_table_prefix . $m[2]; + if (!empty($m[3])) + { + unset($sql_data['source_tables'][$m[3]]); + } + else if ($m[2] != $m[1]) + { + unset($sql_data['source_tables'][$m[2]]); + } + + if (strpos($sql_data['source_tables'][$m[1]], "\nLEFT JOIN") !== false) + { + $sql_data['source_tables'][$m[1]] = '(' . $sql_data['source_tables'][$m[1]] . ")\nLEFT JOIN $right_table"; + } + else + { + $sql_data['source_tables'][$m[1]] .= "\nLEFT JOIN $right_table"; + } + + if (!empty($m[3])) + { + unset($sql_data['source_tables'][$m[3]]); + $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[3]; + } + else if (!empty($convert->src_table_prefix)) + { + $sql_data['source_tables'][$m[1]] .= ' AS ' . $m[2]; + } + $sql_data['source_tables'][$m[1]] .= ' ' . $m[4] . $m[5]; + } + } + + // Remove ", " from the end of the insert query + $insert_query = substr($insert_query, 0, -2) . ') VALUES '; + + return $insert_query; + } + + /** + * Function for processing the currently handled row + */ + function process_row(&$schema, &$sql_data, &$insert_values) + { + global $user, $phpbb_root_path, $phpEx, $db, $lang, $config, $cache; + global $convert, $convert_row; + + $sql_flag = false; + + foreach ($schema as $key => $fields) + { + // We are only interested in the lines with: + // array('comment', 'attachments_desc.comment', 'htmlspecialchars'), + if (is_int($key)) + { + if (!is_array($fields[1])) + { + $fields[1] = array($fields[1]); + } + + $firstkey_set = false; + $firstkey = 0; + + foreach ($fields[1] as $inner_key => $inner_value) + { + if (!$firstkey_set) + { + $firstkey = $inner_key; + $firstkey_set = true; + } + + $src_field = isset($sql_data['source_fields'][$key][$inner_key]) ? $sql_data['source_fields'][$key][$inner_key] : ''; + + if (!empty($src_field)) + { + $fields[1][$inner_key] = $convert->row[$src_field]; + } + } + + if (!empty($fields[0])) + { + // We have a target field, if we haven't set $sql_flag yet it will be set to TRUE. + // If a function has already set it to FALSE it won't change it. + if ($sql_flag === false) + { + $sql_flag = true; + } + + // No function assigned? + if (empty($fields[2])) + { + $value = $fields[1][$firstkey]; + } + else if (is_array($fields[2]) && !is_callable($fields[2])) + { + // Execute complex function/eval/typecast + $value = $fields[1]; + + foreach ($fields[2] as $type => $execution) + { + if (strpos($type, 'typecast') === 0) + { + if (!is_array($value)) + { + $value = array($value); + } + $value = $value[0]; + settype($value, $execution); + } + else if (strpos($type, 'function') === 0) + { + if (!is_array($value)) + { + $value = array($value); + } + + $value = call_user_func_array($execution, $value); + } + else if (strpos($type, 'execute') === 0) + { + if (!is_array($value)) + { + $value = array($value); + } + + $execution = str_replace('{RESULT}', '$value', $execution); + $execution = str_replace('{VALUE}', '$value', $execution); + // @codingStandardsIgnoreStart + eval($execution); + // @codingStandardsIgnoreEnd + } + } + } + else + { + $value = call_user_func_array($fields[2], $fields[1]); + } + + if (is_null($value)) + { + $value = ''; + } + + $insert_values[] = $db->_sql_validate_value($value); + } + else if (!empty($fields[2])) + { + if (is_array($fields[2])) + { + // Execute complex function/eval/typecast + $value = ''; + + foreach ($fields[2] as $type => $execution) + { + if (strpos($type, 'typecast') === 0) + { + $value = settype($value, $execution); + } + else if (strpos($type, 'function') === 0) + { + if (!is_array($value)) + { + $value = array($value); + } + + $value = call_user_func_array($execution, $value); + } + else if (strpos($type, 'execute') === 0) + { + if (!is_array($value)) + { + $value = array($value); + } + + $execution = str_replace('{RESULT}', '$value', $execution); + $execution = str_replace('{VALUE}', '$value', $execution); + // @codingStandardsIgnoreStart + eval($execution); + // @codingStandardsIgnoreEnd + } + } + } + else + { + call_user_func_array($fields[2], $fields[1]); + } + } + } + } + + return $sql_flag; + } + + /** + * Own meta refresh function to be able to change the global time used + */ + function meta_refresh($url) + { + global $convert; + + if ($convert->options['refresh']) + { + // Because we should not rely on correct settings, we simply use the relative path here directly. + $this->template->assign_vars(array( + 'S_REFRESH' => true, + 'META' => '<meta http-equiv="refresh" content="5; url=' . $url . '" />') + ); + } + } + + /** + * Error handler function + * + * This function needs to be kept for BC + * + * @param $error + * @param $line + * @param $file + * @param bool|false $skip + */ + public function error($error, $line, $file, $skip = false) + { + $this->template->assign_block_vars('errors', array( + 'TITLE' => $error, + 'DESCRIPTION' => 'In ' . $file . ' on line ' . $line, + )); + } + + /** + * Database error handler function + * + * This function needs to be kept for BC + * + * @param $error + * @param $sql + * @param $line + * @param $file + * @param bool|false $skip + */ + public function db_error($error, $sql, $line, $file, $skip = false) + { + $this->template->assign_block_vars('errors', array( + 'TITLE' => $error, + 'DESCRIPTION' => 'In ' . $file . ' on line ' . $line . '<br /><br /><strong>SQL:</strong> ' . $sql, + )); + } +} diff --git a/phpBB/install/convertors/convert_phpbb20.php b/phpBB/install/convertors/convert_phpbb20.php index 282b3d238a..414d23623a 100644 --- a/phpBB/install/convertors/convert_phpbb20.php +++ b/phpBB/install/convertors/convert_phpbb20.php @@ -38,7 +38,7 @@ $dbms = $phpbb_config_php_file->convert_30_dbms_to_31($dbms); $convertor_data = array( 'forum_name' => 'phpBB 2.0.x', 'version' => '1.0.3', - 'phpbb_version' => '3.2.0-a2', + 'phpbb_version' => '3.2.0-b1', 'author' => '<a href="https://www.phpbb.com/">phpBB Limited</a>', 'dbms' => $dbms, 'dbhost' => $dbhost, diff --git a/phpBB/install/phpbbcli.php b/phpBB/install/phpbbcli.php index 649d0c4283..70a8a9c7ea 100755 --- a/phpBB/install/phpbbcli.php +++ b/phpBB/install/phpbbcli.php @@ -23,7 +23,7 @@ if (php_sapi_name() !== 'cli') define('IN_PHPBB', true); define('IN_INSTALL', true); define('PHPBB_ENVIRONMENT', 'production'); -define('PHPBB_VERSION', '3.2.0-a2-dev'); +define('PHPBB_VERSION', '3.2.0-b2-dev'); $phpbb_root_path = __DIR__ . '/../'; $phpEx = substr(strrchr(__FILE__, '.'), 1); diff --git a/phpBB/install/schemas/schema.json b/phpBB/install/schemas/schema.json new file mode 100644 index 0000000000..ce2263b7d1 --- /dev/null +++ b/phpBB/install/schemas/schema.json @@ -0,0 +1,3389 @@ +{ + "phpbb_acl_groups": { + "COLUMNS": { + "group_id": [ + "UINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "auth_option_id": [ + "UINT", + 0 + ], + "auth_role_id": [ + "UINT", + 0 + ], + "auth_setting": [ + "TINT:2", + 0 + ] + }, + "KEYS": { + "group_id": [ + "INDEX", + "group_id" + ], + "auth_opt_id": [ + "INDEX", + "auth_option_id" + ], + "auth_role_id": [ + "INDEX", + "auth_role_id" + ] + } + }, + "phpbb_acl_options": { + "COLUMNS": { + "auth_option_id": [ + "UINT", + null, + "auto_increment" + ], + "auth_option": [ + "VCHAR:50", + "" + ], + "is_global": [ + "BOOL", + 0 + ], + "is_local": [ + "BOOL", + 0 + ], + "founder_only": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "auth_option_id", + "KEYS": { + "auth_option": [ + "UNIQUE", + [ + "auth_option" + ] + ] + } + }, + "phpbb_acl_roles": { + "COLUMNS": { + "role_id": [ + "UINT", + null, + "auto_increment" + ], + "role_name": [ + "VCHAR_UNI", + "" + ], + "role_description": [ + "TEXT_UNI", + "" + ], + "role_type": [ + "VCHAR:10", + "" + ], + "role_order": [ + "USINT", + 0 + ] + }, + "PRIMARY_KEY": "role_id", + "KEYS": { + "role_type": [ + "INDEX", + "role_type" + ], + "role_order": [ + "INDEX", + "role_order" + ] + } + }, + "phpbb_acl_roles_data": { + "COLUMNS": { + "role_id": [ + "UINT", + 0 + ], + "auth_option_id": [ + "UINT", + 0 + ], + "auth_setting": [ + "TINT:2", + 0 + ] + }, + "PRIMARY_KEY": [ + "role_id", + "auth_option_id" + ], + "KEYS": { + "ath_op_id": [ + "INDEX", + "auth_option_id" + ] + } + }, + "phpbb_acl_users": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "auth_option_id": [ + "UINT", + 0 + ], + "auth_role_id": [ + "UINT", + 0 + ], + "auth_setting": [ + "TINT:2", + 0 + ] + }, + "KEYS": { + "user_id": [ + "INDEX", + "user_id" + ], + "auth_option_id": [ + "INDEX", + "auth_option_id" + ], + "auth_role_id": [ + "INDEX", + "auth_role_id" + ] + } + }, + "phpbb_attachments": { + "COLUMNS": { + "attach_id": [ + "ULINT", + null, + "auto_increment" + ], + "post_msg_id": [ + "ULINT", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "in_message": [ + "BOOL", + 0 + ], + "poster_id": [ + "ULINT", + 0 + ], + "is_orphan": [ + "BOOL", + 1 + ], + "physical_filename": [ + "VCHAR", + "" + ], + "real_filename": [ + "VCHAR", + "" + ], + "download_count": [ + "UINT", + 0 + ], + "attach_comment": [ + "TEXT_UNI", + "" + ], + "extension": [ + "VCHAR:100", + "" + ], + "mimetype": [ + "VCHAR:100", + "" + ], + "filesize": [ + "UINT:20", + 0 + ], + "filetime": [ + "TIMESTAMP", + 0 + ], + "thumbnail": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "attach_id", + "KEYS": { + "filetime": [ + "INDEX", + "filetime" + ], + "post_msg_id": [ + "INDEX", + "post_msg_id" + ], + "topic_id": [ + "INDEX", + "topic_id" + ], + "poster_id": [ + "INDEX", + "poster_id" + ], + "is_orphan": [ + "INDEX", + "is_orphan" + ] + } + }, + "phpbb_banlist": { + "COLUMNS": { + "ban_id": [ + "ULINT", + null, + "auto_increment" + ], + "ban_userid": [ + "ULINT", + 0 + ], + "ban_ip": [ + "VCHAR:40", + "" + ], + "ban_email": [ + "VCHAR_UNI:100", + "" + ], + "ban_start": [ + "TIMESTAMP", + 0 + ], + "ban_end": [ + "TIMESTAMP", + 0 + ], + "ban_exclude": [ + "BOOL", + 0 + ], + "ban_reason": [ + "VCHAR_UNI", + "" + ], + "ban_give_reason": [ + "VCHAR_UNI", + "" + ] + }, + "PRIMARY_KEY": "ban_id", + "KEYS": { + "ban_end": [ + "INDEX", + "ban_end" + ], + "ban_user": [ + "INDEX", + [ + "ban_userid", + "ban_exclude" + ] + ], + "ban_email": [ + "INDEX", + [ + "ban_email", + "ban_exclude" + ] + ], + "ban_ip": [ + "INDEX", + [ + "ban_ip", + "ban_exclude" + ] + ] + } + }, + "phpbb_bbcodes": { + "COLUMNS": { + "bbcode_id": [ + "USINT", + 0 + ], + "bbcode_tag": [ + "VCHAR:16", + "" + ], + "bbcode_helpline": [ + "VCHAR_UNI", + "" + ], + "display_on_posting": [ + "BOOL", + 0 + ], + "bbcode_match": [ + "TEXT_UNI", + "" + ], + "bbcode_tpl": [ + "MTEXT_UNI", + "" + ], + "first_pass_match": [ + "MTEXT_UNI", + "" + ], + "first_pass_replace": [ + "MTEXT_UNI", + "" + ], + "second_pass_match": [ + "MTEXT_UNI", + "" + ], + "second_pass_replace": [ + "MTEXT_UNI", + "" + ] + }, + "PRIMARY_KEY": "bbcode_id", + "KEYS": { + "display_on_post": [ + "INDEX", + "display_on_posting" + ] + } + }, + "phpbb_bookmarks": { + "COLUMNS": { + "topic_id": [ + "ULINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ] + }, + "PRIMARY_KEY": [ + "topic_id", + "user_id" + ] + }, + "phpbb_bots": { + "COLUMNS": { + "bot_id": [ + "ULINT", + null, + "auto_increment" + ], + "bot_active": [ + "BOOL", + 1 + ], + "bot_name": [ + "STEXT_UNI", + "" + ], + "user_id": [ + "ULINT", + 0 + ], + "bot_agent": [ + "VCHAR", + "" + ], + "bot_ip": [ + "VCHAR", + "" + ] + }, + "PRIMARY_KEY": "bot_id", + "KEYS": { + "bot_active": [ + "INDEX", + "bot_active" + ] + } + }, + "phpbb_config": { + "COLUMNS": { + "config_name": [ + "VCHAR", + "" + ], + "config_value": [ + "VCHAR_UNI", + "" + ], + "is_dynamic": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "config_name", + "KEYS": { + "is_dynamic": [ + "INDEX", + "is_dynamic" + ] + } + }, + "phpbb_config_text": { + "COLUMNS": { + "config_name": [ + "VCHAR", + "" + ], + "config_value": [ + "MTEXT", + "" + ] + }, + "PRIMARY_KEY": "config_name" + }, + "phpbb_confirm": { + "COLUMNS": { + "confirm_id": [ + "CHAR:32", + "" + ], + "session_id": [ + "CHAR:32", + "" + ], + "confirm_type": [ + "TINT:3", + 0 + ], + "code": [ + "VCHAR:8", + "" + ], + "seed": [ + "UINT:10", + 0 + ], + "attempts": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": [ + "session_id", + "confirm_id" + ], + "KEYS": { + "confirm_type": [ + "INDEX", + "confirm_type" + ] + } + }, + "phpbb_disallow": { + "COLUMNS": { + "disallow_id": [ + "UINT", + null, + "auto_increment" + ], + "disallow_username": [ + "VCHAR_UNI:255", + "" + ] + }, + "PRIMARY_KEY": "disallow_id" + }, + "phpbb_drafts": { + "COLUMNS": { + "draft_id": [ + "ULINT", + null, + "auto_increment" + ], + "user_id": [ + "ULINT", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "save_time": [ + "TIMESTAMP", + 0 + ], + "draft_subject": [ + "STEXT_UNI", + "" + ], + "draft_message": [ + "MTEXT_UNI", + "" + ] + }, + "PRIMARY_KEY": "draft_id", + "KEYS": { + "save_time": [ + "INDEX", + "save_time" + ] + } + }, + "phpbb_ext": { + "COLUMNS": { + "ext_name": [ + "VCHAR", + "" + ], + "ext_active": [ + "BOOL", + 0 + ], + "ext_state": [ + "TEXT", + "" + ] + }, + "KEYS": { + "ext_name": [ + "UNIQUE", + "ext_name" + ] + } + }, + "phpbb_extension_groups": { + "COLUMNS": { + "group_id": [ + "UINT", + null, + "auto_increment" + ], + "group_name": [ + "VCHAR_UNI", + "" + ], + "cat_id": [ + "TINT:2", + 0 + ], + "allow_group": [ + "BOOL", + 0 + ], + "download_mode": [ + "BOOL", + 1 + ], + "upload_icon": [ + "VCHAR", + "" + ], + "max_filesize": [ + "UINT:20", + 0 + ], + "allowed_forums": [ + "TEXT", + "" + ], + "allow_in_pm": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "group_id" + }, + "phpbb_extensions": { + "COLUMNS": { + "extension_id": [ + "UINT", + null, + "auto_increment" + ], + "group_id": [ + "UINT", + 0 + ], + "extension": [ + "VCHAR:100", + "" + ] + }, + "PRIMARY_KEY": "extension_id" + }, + "phpbb_forums": { + "COLUMNS": { + "forum_id": [ + "UINT", + null, + "auto_increment" + ], + "parent_id": [ + "UINT", + 0 + ], + "left_id": [ + "UINT", + 0 + ], + "right_id": [ + "UINT", + 0 + ], + "forum_parents": [ + "MTEXT", + "" + ], + "forum_name": [ + "STEXT_UNI", + "" + ], + "forum_desc": [ + "TEXT_UNI", + "" + ], + "forum_desc_bitfield": [ + "VCHAR:255", + "" + ], + "forum_desc_options": [ + "UINT:11", + 7 + ], + "forum_desc_uid": [ + "VCHAR:8", + "" + ], + "forum_link": [ + "VCHAR_UNI", + "" + ], + "forum_password": [ + "VCHAR:255", + "" + ], + "forum_style": [ + "UINT", + 0 + ], + "forum_image": [ + "VCHAR", + "" + ], + "forum_rules": [ + "TEXT_UNI", + "" + ], + "forum_rules_link": [ + "VCHAR_UNI", + "" + ], + "forum_rules_bitfield": [ + "VCHAR:255", + "" + ], + "forum_rules_options": [ + "UINT:11", + 7 + ], + "forum_rules_uid": [ + "VCHAR:8", + "" + ], + "forum_topics_per_page": [ + "TINT:4", + 0 + ], + "forum_type": [ + "TINT:4", + 0 + ], + "forum_status": [ + "TINT:4", + 0 + ], + "forum_last_post_id": [ + "ULINT", + 0 + ], + "forum_last_poster_id": [ + "ULINT", + 0 + ], + "forum_last_post_subject": [ + "STEXT_UNI", + "" + ], + "forum_last_post_time": [ + "TIMESTAMP", + 0 + ], + "forum_last_poster_name": [ + "VCHAR_UNI", + "" + ], + "forum_last_poster_colour": [ + "VCHAR:6", + "" + ], + "forum_flags": [ + "TINT:4", + 32 + ], + "display_on_index": [ + "BOOL", + 1 + ], + "enable_indexing": [ + "BOOL", + 1 + ], + "enable_icons": [ + "BOOL", + 1 + ], + "enable_prune": [ + "BOOL", + 0 + ], + "prune_next": [ + "TIMESTAMP", + 0 + ], + "prune_days": [ + "UINT", + 0 + ], + "prune_viewed": [ + "UINT", + 0 + ], + "prune_freq": [ + "UINT", + 0 + ], + "display_subforum_list": [ + "BOOL", + 1 + ], + "forum_options": [ + "UINT:20", + 0 + ], + "forum_posts_approved": [ + "UINT", + 0 + ], + "forum_posts_unapproved": [ + "UINT", + 0 + ], + "forum_posts_softdeleted": [ + "UINT", + 0 + ], + "forum_topics_approved": [ + "UINT", + 0 + ], + "forum_topics_unapproved": [ + "UINT", + 0 + ], + "forum_topics_softdeleted": [ + "UINT", + 0 + ], + "enable_shadow_prune": [ + "BOOL", + 0 + ], + "prune_shadow_days": [ + "UINT", + 7 + ], + "prune_shadow_freq": [ + "UINT", + 1 + ], + "prune_shadow_next": [ + "INT:11", + 0 + ] + }, + "PRIMARY_KEY": "forum_id", + "KEYS": { + "left_right_id": [ + "INDEX", + [ + "left_id", + "right_id" + ] + ], + "forum_lastpost_id": [ + "INDEX", + "forum_last_post_id" + ] + } + }, + "phpbb_forums_access": { + "COLUMNS": { + "forum_id": [ + "UINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "session_id": [ + "CHAR:32", + "" + ] + }, + "PRIMARY_KEY": [ + "forum_id", + "user_id", + "session_id" + ] + }, + "phpbb_forums_track": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "mark_time": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": [ + "user_id", + "forum_id" + ] + }, + "phpbb_forums_watch": { + "COLUMNS": { + "forum_id": [ + "UINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "notify_status": [ + "BOOL", + 0 + ] + }, + "KEYS": { + "forum_id": [ + "INDEX", + "forum_id" + ], + "user_id": [ + "INDEX", + "user_id" + ], + "notify_stat": [ + "INDEX", + "notify_status" + ] + } + }, + "phpbb_groups": { + "COLUMNS": { + "group_id": [ + "UINT", + null, + "auto_increment" + ], + "group_type": [ + "TINT:4", + 1 + ], + "group_founder_manage": [ + "BOOL", + 0 + ], + "group_skip_auth": [ + "BOOL", + 0 + ], + "group_name": [ + "VCHAR_CI", + "" + ], + "group_desc": [ + "TEXT_UNI", + "" + ], + "group_desc_bitfield": [ + "VCHAR:255", + "" + ], + "group_desc_options": [ + "UINT:11", + 7 + ], + "group_desc_uid": [ + "VCHAR:8", + "" + ], + "group_display": [ + "BOOL", + 0 + ], + "group_avatar": [ + "VCHAR", + "" + ], + "group_avatar_type": [ + "VCHAR:255", + "" + ], + "group_avatar_width": [ + "USINT", + 0 + ], + "group_avatar_height": [ + "USINT", + 0 + ], + "group_rank": [ + "UINT", + 0 + ], + "group_colour": [ + "VCHAR:6", + "" + ], + "group_sig_chars": [ + "UINT", + 0 + ], + "group_receive_pm": [ + "BOOL", + 0 + ], + "group_message_limit": [ + "UINT", + 0 + ], + "group_legend": [ + "UINT", + 0 + ], + "group_max_recipients": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "group_id", + "KEYS": { + "group_legend_name": [ + "INDEX", + [ + "group_legend", + "group_name" + ] + ] + } + }, + "phpbb_icons": { + "COLUMNS": { + "icons_id": [ + "UINT", + null, + "auto_increment" + ], + "icons_url": [ + "VCHAR", + "" + ], + "icons_width": [ + "TINT:4", + 0 + ], + "icons_height": [ + "TINT:4", + 0 + ], + "icons_alt": [ + "VCHAR", + "" + ], + "icons_order": [ + "UINT", + 0 + ], + "display_on_posting": [ + "BOOL", + 1 + ] + }, + "PRIMARY_KEY": "icons_id", + "KEYS": { + "display_on_posting": [ + "INDEX", + "display_on_posting" + ] + } + }, + "phpbb_lang": { + "COLUMNS": { + "lang_id": [ + "TINT:4", + null, + "auto_increment" + ], + "lang_iso": [ + "VCHAR:30", + "" + ], + "lang_dir": [ + "VCHAR:30", + "" + ], + "lang_english_name": [ + "VCHAR_UNI:100", + "" + ], + "lang_local_name": [ + "VCHAR_UNI:255", + "" + ], + "lang_author": [ + "VCHAR_UNI:255", + "" + ] + }, + "PRIMARY_KEY": "lang_id", + "KEYS": { + "lang_iso": [ + "INDEX", + "lang_iso" + ] + } + }, + "phpbb_log": { + "COLUMNS": { + "log_id": [ + "ULINT", + null, + "auto_increment" + ], + "log_type": [ + "TINT:4", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "post_id": [ + "ULINT", + 0 + ], + "reportee_id": [ + "ULINT", + 0 + ], + "log_ip": [ + "VCHAR:40", + "" + ], + "log_time": [ + "TIMESTAMP", + 0 + ], + "log_operation": [ + "TEXT_UNI", + "" + ], + "log_data": [ + "MTEXT_UNI", + "" + ] + }, + "PRIMARY_KEY": "log_id", + "KEYS": { + "log_type": [ + "INDEX", + "log_type" + ], + "forum_id": [ + "INDEX", + "forum_id" + ], + "topic_id": [ + "INDEX", + "topic_id" + ], + "reportee_id": [ + "INDEX", + "reportee_id" + ], + "user_id": [ + "INDEX", + "user_id" + ] + } + }, + "phpbb_login_attempts": { + "COLUMNS": { + "attempt_ip": [ + "VCHAR:40", + "" + ], + "attempt_browser": [ + "VCHAR:150", + "" + ], + "attempt_forwarded_for": [ + "VCHAR:255", + "" + ], + "attempt_time": [ + "TIMESTAMP", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "username": [ + "VCHAR_UNI:255", + 0 + ], + "username_clean": [ + "VCHAR_CI", + 0 + ] + }, + "KEYS": { + "att_ip": [ + "INDEX", + [ + "attempt_ip", + "attempt_time" + ] + ], + "att_for": [ + "INDEX", + [ + "attempt_forwarded_for", + "attempt_time" + ] + ], + "att_time": [ + "INDEX", + [ + "attempt_time" + ] + ], + "user_id": [ + "INDEX", + "user_id" + ] + } + }, + "phpbb_migrations": { + "COLUMNS": { + "migration_name": [ + "VCHAR", + "" + ], + "migration_depends_on": [ + "TEXT", + "" + ], + "migration_schema_done": [ + "BOOL", + 0 + ], + "migration_data_done": [ + "BOOL", + 0 + ], + "migration_data_state": [ + "TEXT", + "" + ], + "migration_start_time": [ + "TIMESTAMP", + 0 + ], + "migration_end_time": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": "migration_name" + }, + "phpbb_moderator_cache": { + "COLUMNS": { + "forum_id": [ + "UINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "username": [ + "VCHAR_UNI:255", + "" + ], + "group_id": [ + "UINT", + 0 + ], + "group_name": [ + "VCHAR_UNI", + "" + ], + "display_on_index": [ + "BOOL", + 1 + ] + }, + "KEYS": { + "disp_idx": [ + "INDEX", + "display_on_index" + ], + "forum_id": [ + "INDEX", + "forum_id" + ] + } + }, + "phpbb_modules": { + "COLUMNS": { + "module_id": [ + "UINT", + null, + "auto_increment" + ], + "module_enabled": [ + "BOOL", + 1 + ], + "module_display": [ + "BOOL", + 1 + ], + "module_basename": [ + "VCHAR", + "" + ], + "module_class": [ + "VCHAR:10", + "" + ], + "parent_id": [ + "UINT", + 0 + ], + "left_id": [ + "UINT", + 0 + ], + "right_id": [ + "UINT", + 0 + ], + "module_langname": [ + "VCHAR", + "" + ], + "module_mode": [ + "VCHAR", + "" + ], + "module_auth": [ + "VCHAR", + "" + ] + }, + "PRIMARY_KEY": "module_id", + "KEYS": { + "left_right_id": [ + "INDEX", + [ + "left_id", + "right_id" + ] + ], + "module_enabled": [ + "INDEX", + "module_enabled" + ], + "class_left_id": [ + "INDEX", + [ + "module_class", + "left_id" + ] + ] + } + }, + "phpbb_notification_types": { + "COLUMNS": { + "notification_type_id": [ + "USINT", + null, + "auto_increment" + ], + "notification_type_name": [ + "VCHAR:255", + "" + ], + "notification_type_enabled": [ + "BOOL", + 1 + ] + }, + "PRIMARY_KEY": [ + "notification_type_id" + ], + "KEYS": { + "type": [ + "UNIQUE", + [ + "notification_type_name" + ] + ] + } + }, + "phpbb_notifications": { + "COLUMNS": { + "notification_id": [ + "UINT:10", + null, + "auto_increment" + ], + "notification_type_id": [ + "USINT", + 0 + ], + "item_id": [ + "UINT", + 0 + ], + "item_parent_id": [ + "UINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "notification_read": [ + "BOOL", + 0 + ], + "notification_time": [ + "TIMESTAMP", + 1 + ], + "notification_data": [ + "TEXT_UNI", + "" + ] + }, + "PRIMARY_KEY": "notification_id", + "KEYS": { + "item_ident": [ + "INDEX", + [ + "notification_type_id", + "item_id" + ] + ], + "user": [ + "INDEX", + [ + "user_id", + "notification_read" + ] + ] + } + }, + "phpbb_oauth_accounts": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "provider": [ + "VCHAR", + "" + ], + "oauth_provider_id": [ + "TEXT_UNI", + "" + ] + }, + "PRIMARY_KEY": [ + "user_id", + "provider" + ] + }, + "phpbb_oauth_states": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "session_id": [ + "CHAR:32", + "" + ], + "provider": [ + "VCHAR", + "" + ], + "oauth_state": [ + "VCHAR", + "" + ] + }, + "KEYS": { + "user_id": [ + "INDEX", + "user_id" + ], + "provider": [ + "INDEX", + "provider" + ] + } + }, + "phpbb_oauth_tokens": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "session_id": [ + "CHAR:32", + "" + ], + "provider": [ + "VCHAR", + "" + ], + "oauth_token": [ + "MTEXT", + "" + ] + }, + "KEYS": { + "user_id": [ + "INDEX", + "user_id" + ], + "provider": [ + "INDEX", + "provider" + ] + } + }, + "phpbb_poll_options": { + "COLUMNS": { + "poll_option_id": [ + "TINT:4", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "poll_option_text": [ + "TEXT_UNI", + "" + ], + "poll_option_total": [ + "UINT", + 0 + ] + }, + "KEYS": { + "poll_opt_id": [ + "INDEX", + "poll_option_id" + ], + "topic_id": [ + "INDEX", + "topic_id" + ] + } + }, + "phpbb_poll_votes": { + "COLUMNS": { + "topic_id": [ + "ULINT", + 0 + ], + "poll_option_id": [ + "TINT:4", + 0 + ], + "vote_user_id": [ + "ULINT", + 0 + ], + "vote_user_ip": [ + "VCHAR:40", + "" + ] + }, + "KEYS": { + "topic_id": [ + "INDEX", + "topic_id" + ], + "vote_user_id": [ + "INDEX", + "vote_user_id" + ], + "vote_user_ip": [ + "INDEX", + "vote_user_ip" + ] + } + }, + "phpbb_posts": { + "COLUMNS": { + "post_id": [ + "ULINT", + null, + "auto_increment" + ], + "topic_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "poster_id": [ + "ULINT", + 0 + ], + "icon_id": [ + "UINT", + 0 + ], + "poster_ip": [ + "VCHAR:40", + "" + ], + "post_time": [ + "TIMESTAMP", + 0 + ], + "post_reported": [ + "BOOL", + 0 + ], + "enable_bbcode": [ + "BOOL", + 1 + ], + "enable_smilies": [ + "BOOL", + 1 + ], + "enable_magic_url": [ + "BOOL", + 1 + ], + "enable_sig": [ + "BOOL", + 1 + ], + "post_username": [ + "VCHAR_UNI:255", + "" + ], + "post_subject": [ + "STEXT_UNI", + "", + "true_sort" + ], + "post_text": [ + "MTEXT_UNI", + "" + ], + "post_checksum": [ + "VCHAR:32", + "" + ], + "post_attachment": [ + "BOOL", + 0 + ], + "bbcode_bitfield": [ + "VCHAR:255", + "" + ], + "bbcode_uid": [ + "VCHAR:8", + "" + ], + "post_postcount": [ + "BOOL", + 1 + ], + "post_edit_time": [ + "TIMESTAMP", + 0 + ], + "post_edit_reason": [ + "STEXT_UNI", + "" + ], + "post_edit_user": [ + "ULINT", + 0 + ], + "post_edit_count": [ + "USINT", + 0 + ], + "post_edit_locked": [ + "BOOL", + 0 + ], + "post_visibility": [ + "TINT:3", + 0 + ], + "post_delete_time": [ + "TIMESTAMP", + 0 + ], + "post_delete_reason": [ + "STEXT_UNI", + "" + ], + "post_delete_user": [ + "ULINT", + 0 + ] + }, + "PRIMARY_KEY": "post_id", + "KEYS": { + "forum_id": [ + "INDEX", + "forum_id" + ], + "topic_id": [ + "INDEX", + "topic_id" + ], + "poster_ip": [ + "INDEX", + "poster_ip" + ], + "poster_id": [ + "INDEX", + "poster_id" + ], + "tid_post_time": [ + "INDEX", + [ + "topic_id", + "post_time" + ] + ], + "post_username": [ + "INDEX", + [ + "post_username:255" + ] + ], + "post_visibility": [ + "INDEX", + [ + "post_visibility" + ] + ] + } + }, + "phpbb_privmsgs": { + "COLUMNS": { + "msg_id": [ + "ULINT", + null, + "auto_increment" + ], + "root_level": [ + "UINT", + 0 + ], + "author_id": [ + "ULINT", + 0 + ], + "icon_id": [ + "UINT", + 0 + ], + "author_ip": [ + "VCHAR:40", + "" + ], + "message_time": [ + "TIMESTAMP", + 0 + ], + "enable_bbcode": [ + "BOOL", + 1 + ], + "enable_smilies": [ + "BOOL", + 1 + ], + "enable_magic_url": [ + "BOOL", + 1 + ], + "enable_sig": [ + "BOOL", + 1 + ], + "message_subject": [ + "STEXT_UNI", + "" + ], + "message_text": [ + "MTEXT_UNI", + "" + ], + "message_edit_reason": [ + "STEXT_UNI", + "" + ], + "message_edit_user": [ + "ULINT", + 0 + ], + "message_attachment": [ + "BOOL", + 0 + ], + "bbcode_bitfield": [ + "VCHAR:255", + "" + ], + "bbcode_uid": [ + "VCHAR:8", + "" + ], + "message_edit_time": [ + "TIMESTAMP", + 0 + ], + "message_edit_count": [ + "USINT", + 0 + ], + "to_address": [ + "TEXT_UNI", + "" + ], + "bcc_address": [ + "TEXT_UNI", + "" + ], + "message_reported": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "msg_id", + "KEYS": { + "author_ip": [ + "INDEX", + "author_ip" + ], + "message_time": [ + "INDEX", + "message_time" + ], + "author_id": [ + "INDEX", + "author_id" + ], + "root_level": [ + "INDEX", + "root_level" + ] + } + }, + "phpbb_privmsgs_folder": { + "COLUMNS": { + "folder_id": [ + "UINT", + null, + "auto_increment" + ], + "user_id": [ + "ULINT", + 0 + ], + "folder_name": [ + "VCHAR_UNI", + "" + ], + "pm_count": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "folder_id", + "KEYS": { + "user_id": [ + "INDEX", + "user_id" + ] + } + }, + "phpbb_privmsgs_rules": { + "COLUMNS": { + "rule_id": [ + "UINT", + null, + "auto_increment" + ], + "user_id": [ + "ULINT", + 0 + ], + "rule_check": [ + "UINT", + 0 + ], + "rule_connection": [ + "UINT", + 0 + ], + "rule_string": [ + "VCHAR_UNI", + "" + ], + "rule_user_id": [ + "ULINT", + 0 + ], + "rule_group_id": [ + "UINT", + 0 + ], + "rule_action": [ + "UINT", + 0 + ], + "rule_folder_id": [ + "INT:11", + 0 + ] + }, + "PRIMARY_KEY": "rule_id", + "KEYS": { + "user_id": [ + "INDEX", + "user_id" + ] + } + }, + "phpbb_privmsgs_to": { + "COLUMNS": { + "msg_id": [ + "ULINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "author_id": [ + "ULINT", + 0 + ], + "pm_deleted": [ + "BOOL", + 0 + ], + "pm_new": [ + "BOOL", + 1 + ], + "pm_unread": [ + "BOOL", + 1 + ], + "pm_replied": [ + "BOOL", + 0 + ], + "pm_marked": [ + "BOOL", + 0 + ], + "pm_forwarded": [ + "BOOL", + 0 + ], + "folder_id": [ + "INT:11", + 0 + ] + }, + "KEYS": { + "msg_id": [ + "INDEX", + "msg_id" + ], + "author_id": [ + "INDEX", + "author_id" + ], + "usr_flder_id": [ + "INDEX", + [ + "user_id", + "folder_id" + ] + ] + } + }, + "phpbb_profile_fields": { + "COLUMNS": { + "field_id": [ + "UINT", + null, + "auto_increment" + ], + "field_name": [ + "VCHAR_UNI", + "" + ], + "field_type": [ + "VCHAR:100", + "" + ], + "field_ident": [ + "VCHAR:20", + "" + ], + "field_length": [ + "VCHAR:20", + "" + ], + "field_minlen": [ + "VCHAR", + "" + ], + "field_maxlen": [ + "VCHAR", + "" + ], + "field_novalue": [ + "VCHAR_UNI", + "" + ], + "field_default_value": [ + "VCHAR_UNI", + "" + ], + "field_validation": [ + "VCHAR_UNI:64", + "" + ], + "field_required": [ + "BOOL", + 0 + ], + "field_show_on_reg": [ + "BOOL", + 0 + ], + "field_hide": [ + "BOOL", + 0 + ], + "field_no_view": [ + "BOOL", + 0 + ], + "field_active": [ + "BOOL", + 0 + ], + "field_order": [ + "UINT", + 0 + ], + "field_show_profile": [ + "BOOL", + 0 + ], + "field_show_on_vt": [ + "BOOL", + 0 + ], + "field_show_novalue": [ + "BOOL", + 0 + ], + "field_show_on_pm": [ + "BOOL", + 0 + ], + "field_show_on_ml": [ + "BOOL", + 0 + ], + "field_is_contact": [ + "BOOL", + 0 + ], + "field_contact_desc": [ + "VCHAR", + "" + ], + "field_contact_url": [ + "VCHAR", + "" + ] + }, + "PRIMARY_KEY": "field_id", + "KEYS": { + "fld_type": [ + "INDEX", + "field_type" + ], + "fld_ordr": [ + "INDEX", + "field_order" + ] + } + }, + "phpbb_profile_fields_data": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "pf_phpbb_interests": [ + "MTEXT", + "" + ], + "pf_phpbb_occupation": [ + "MTEXT", + "" + ], + "pf_phpbb_icq": [ + "VCHAR", + "" + ], + "pf_phpbb_twitter": [ + "VCHAR", + "" + ], + "pf_phpbb_facebook": [ + "VCHAR", + "" + ], + "pf_phpbb_skype": [ + "VCHAR", + "" + ], + "pf_phpbb_youtube": [ + "VCHAR", + "" + ], + "pf_phpbb_location": [ + "VCHAR", + "" + ], + "pf_phpbb_googleplus": [ + "VCHAR", + "" + ], + "pf_phpbb_website": [ + "VCHAR", + "" + ], + "pf_phpbb_yahoo": [ + "VCHAR", + "" + ], + "pf_phpbb_aol": [ + "VCHAR", + "" + ] + }, + "PRIMARY_KEY": "user_id" + }, + "phpbb_profile_fields_lang": { + "COLUMNS": { + "field_id": [ + "UINT", + 0 + ], + "lang_id": [ + "UINT", + 0 + ], + "option_id": [ + "UINT", + 0 + ], + "field_type": [ + "VCHAR:100", + "" + ], + "lang_value": [ + "VCHAR_UNI", + "" + ] + }, + "PRIMARY_KEY": [ + "field_id", + "lang_id", + "option_id" + ] + }, + "phpbb_profile_lang": { + "COLUMNS": { + "field_id": [ + "UINT", + 0 + ], + "lang_id": [ + "UINT", + 0 + ], + "lang_name": [ + "VCHAR_UNI", + "" + ], + "lang_explain": [ + "TEXT_UNI", + "" + ], + "lang_default_value": [ + "VCHAR_UNI", + "" + ] + }, + "PRIMARY_KEY": [ + "field_id", + "lang_id" + ] + }, + "phpbb_ranks": { + "COLUMNS": { + "rank_id": [ + "UINT", + null, + "auto_increment" + ], + "rank_title": [ + "VCHAR_UNI", + "" + ], + "rank_min": [ + "UINT", + 0 + ], + "rank_special": [ + "BOOL", + 0 + ], + "rank_image": [ + "VCHAR", + "" + ] + }, + "PRIMARY_KEY": "rank_id" + }, + "phpbb_reports": { + "COLUMNS": { + "report_id": [ + "ULINT", + 0 + ], + "reason_id": [ + "USINT", + 0 + ], + "post_id": [ + "ULINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "user_notify": [ + "BOOL", + 0 + ], + "report_closed": [ + "BOOL", + 0 + ], + "report_time": [ + "TIMESTAMP", + 0 + ], + "report_text": [ + "MTEXT_UNI", + "" + ], + "pm_id": [ + "ULINT", + 0 + ], + "reported_post_enable_bbcode": [ + "BOOL", + 1 + ], + "reported_post_enable_smilies": [ + "BOOL", + 1 + ], + "reported_post_enable_magic_url": [ + "BOOL", + 1 + ], + "reported_post_text": [ + "MTEXT_UNI", + "" + ], + "reported_post_uid": [ + "VCHAR:8", + "" + ], + "reported_post_bitfield": [ + "VCHAR:255", + "" + ] + }, + "PRIMARY_KEY": "report_id", + "KEYS": { + "post_id": [ + "INDEX", + [ + "post_id" + ] + ], + "pm_id": [ + "INDEX", + [ + "pm_id" + ] + ] + } + }, + "phpbb_reports_reasons": { + "COLUMNS": { + "reason_id": [ + "USINT", + null, + "auto_increment" + ], + "reason_title": [ + "VCHAR_UNI", + "" + ], + "reason_description": [ + "MTEXT_UNI", + "" + ], + "reason_order": [ + "USINT", + 0 + ] + }, + "PRIMARY_KEY": "reason_id" + }, + "phpbb_search_results": { + "COLUMNS": { + "search_key": [ + "VCHAR:32", + "" + ], + "search_time": [ + "TIMESTAMP", + 0 + ], + "search_keywords": [ + "MTEXT_UNI", + "" + ], + "search_authors": [ + "MTEXT", + "" + ] + }, + "PRIMARY_KEY": "search_key" + }, + "phpbb_search_wordlist": { + "COLUMNS": { + "word_id": [ + "ULINT", + null, + "auto_increment" + ], + "word_text": [ + "VCHAR_UNI", + "" + ], + "word_common": [ + "BOOL", + 0 + ], + "word_count": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "word_id", + "KEYS": { + "wrd_txt": [ + "UNIQUE", + "word_text" + ], + "wrd_cnt": [ + "INDEX", + "word_count" + ] + } + }, + "phpbb_search_wordmatch": { + "COLUMNS": { + "post_id": [ + "ULINT", + 0 + ], + "word_id": [ + "ULINT", + 0 + ], + "title_match": [ + "BOOL", + 0 + ] + }, + "KEYS": { + "word_id": [ + "INDEX", + "word_id" + ], + "post_id": [ + "INDEX", + "post_id" + ], + "un_mtch": [ + "UNIQUE", + [ + "word_id", + "post_id", + "title_match" + ] + ] + } + }, + "phpbb_sessions": { + "COLUMNS": { + "session_id": [ + "CHAR:32", + "" + ], + "session_user_id": [ + "ULINT", + 0 + ], + "session_last_visit": [ + "TIMESTAMP", + 0 + ], + "session_start": [ + "TIMESTAMP", + 0 + ], + "session_time": [ + "TIMESTAMP", + 0 + ], + "session_ip": [ + "VCHAR:40", + "" + ], + "session_browser": [ + "VCHAR:150", + "" + ], + "session_forwarded_for": [ + "VCHAR:255", + "" + ], + "session_page": [ + "VCHAR_UNI", + "" + ], + "session_viewonline": [ + "BOOL", + 1 + ], + "session_autologin": [ + "BOOL", + 0 + ], + "session_admin": [ + "BOOL", + 0 + ], + "session_forum_id": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "session_id", + "KEYS": { + "session_time": [ + "INDEX", + "session_time" + ], + "session_user_id": [ + "INDEX", + "session_user_id" + ], + "session_fid": [ + "INDEX", + [ + "session_forum_id" + ] + ] + } + }, + "phpbb_sessions_keys": { + "COLUMNS": { + "key_id": [ + "CHAR:32", + "" + ], + "user_id": [ + "ULINT", + 0 + ], + "last_ip": [ + "VCHAR:40", + "" + ], + "last_login": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": [ + "key_id", + "user_id" + ], + "KEYS": { + "last_login": [ + "INDEX", + "last_login" + ] + } + }, + "phpbb_sitelist": { + "COLUMNS": { + "site_id": [ + "UINT", + null, + "auto_increment" + ], + "site_ip": [ + "VCHAR:40", + "" + ], + "site_hostname": [ + "VCHAR", + "" + ], + "ip_exclude": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": "site_id" + }, + "phpbb_smilies": { + "COLUMNS": { + "smiley_id": [ + "UINT", + null, + "auto_increment" + ], + "code": [ + "VCHAR_UNI:50", + "" + ], + "emotion": [ + "VCHAR_UNI:50", + "" + ], + "smiley_url": [ + "VCHAR:50", + "" + ], + "smiley_width": [ + "USINT", + 0 + ], + "smiley_height": [ + "USINT", + 0 + ], + "smiley_order": [ + "UINT", + 0 + ], + "display_on_posting": [ + "BOOL", + 1 + ] + }, + "PRIMARY_KEY": "smiley_id", + "KEYS": { + "display_on_post": [ + "INDEX", + "display_on_posting" + ] + } + }, + "phpbb_styles": { + "COLUMNS": { + "style_id": [ + "UINT", + null, + "auto_increment" + ], + "style_name": [ + "VCHAR_UNI:255", + "" + ], + "style_copyright": [ + "VCHAR_UNI", + "" + ], + "style_active": [ + "BOOL", + 1 + ], + "style_path": [ + "VCHAR:100", + "" + ], + "bbcode_bitfield": [ + "VCHAR:255", + "kNg=" + ], + "style_parent_id": [ + "UINT:4", + 0 + ], + "style_parent_tree": [ + "TEXT", + "" + ] + }, + "PRIMARY_KEY": "style_id", + "KEYS": { + "style_name": [ + "UNIQUE", + "style_name" + ] + } + }, + "phpbb_teampage": { + "COLUMNS": { + "teampage_id": [ + "UINT", + null, + "auto_increment" + ], + "group_id": [ + "UINT", + 0 + ], + "teampage_name": [ + "VCHAR_UNI:255", + "" + ], + "teampage_position": [ + "UINT", + 0 + ], + "teampage_parent": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "teampage_id" + }, + "phpbb_topics": { + "COLUMNS": { + "topic_id": [ + "ULINT", + null, + "auto_increment" + ], + "forum_id": [ + "UINT", + 0 + ], + "icon_id": [ + "UINT", + 0 + ], + "topic_attachment": [ + "BOOL", + 0 + ], + "topic_reported": [ + "BOOL", + 0 + ], + "topic_title": [ + "STEXT_UNI", + "", + "true_sort" + ], + "topic_poster": [ + "ULINT", + 0 + ], + "topic_time": [ + "TIMESTAMP", + 0 + ], + "topic_time_limit": [ + "TIMESTAMP", + 0 + ], + "topic_views": [ + "UINT", + 0 + ], + "topic_status": [ + "TINT:3", + 0 + ], + "topic_type": [ + "TINT:3", + 0 + ], + "topic_first_post_id": [ + "ULINT", + 0 + ], + "topic_first_poster_name": [ + "VCHAR_UNI:255", + "", + "true_sort" + ], + "topic_first_poster_colour": [ + "VCHAR:6", + "" + ], + "topic_last_post_id": [ + "ULINT", + 0 + ], + "topic_last_poster_id": [ + "ULINT", + 0 + ], + "topic_last_poster_name": [ + "VCHAR_UNI", + "" + ], + "topic_last_poster_colour": [ + "VCHAR:6", + "" + ], + "topic_last_post_subject": [ + "STEXT_UNI", + "" + ], + "topic_last_post_time": [ + "TIMESTAMP", + 0 + ], + "topic_last_view_time": [ + "TIMESTAMP", + 0 + ], + "topic_moved_id": [ + "ULINT", + 0 + ], + "topic_bumped": [ + "BOOL", + 0 + ], + "topic_bumper": [ + "UINT", + 0 + ], + "poll_title": [ + "STEXT_UNI", + "" + ], + "poll_start": [ + "TIMESTAMP", + 0 + ], + "poll_length": [ + "TIMESTAMP", + 0 + ], + "poll_max_options": [ + "TINT:4", + 1 + ], + "poll_last_vote": [ + "TIMESTAMP", + 0 + ], + "poll_vote_change": [ + "BOOL", + 0 + ], + "topic_visibility": [ + "TINT:3", + 0 + ], + "topic_delete_time": [ + "TIMESTAMP", + 0 + ], + "topic_delete_reason": [ + "STEXT_UNI", + "" + ], + "topic_delete_user": [ + "ULINT", + 0 + ], + "topic_posts_approved": [ + "UINT", + 0 + ], + "topic_posts_unapproved": [ + "UINT", + 0 + ], + "topic_posts_softdeleted": [ + "UINT", + 0 + ] + }, + "PRIMARY_KEY": "topic_id", + "KEYS": { + "forum_id": [ + "INDEX", + "forum_id" + ], + "forum_id_type": [ + "INDEX", + [ + "forum_id", + "topic_type" + ] + ], + "last_post_time": [ + "INDEX", + "topic_last_post_time" + ], + "fid_time_moved": [ + "INDEX", + [ + "forum_id", + "topic_last_post_time", + "topic_moved_id" + ] + ], + "topic_visibility": [ + "INDEX", + [ + "topic_visibility" + ] + ], + "forum_vis_last": [ + "INDEX", + [ + "forum_id", + "topic_visibility", + "topic_last_post_id" + ] + ] + } + }, + "phpbb_topics_posted": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "topic_posted": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": [ + "user_id", + "topic_id" + ] + }, + "phpbb_topics_track": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "topic_id": [ + "ULINT", + 0 + ], + "forum_id": [ + "UINT", + 0 + ], + "mark_time": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": [ + "user_id", + "topic_id" + ], + "KEYS": { + "forum_id": [ + "INDEX", + "forum_id" + ], + "topic_id": [ + "INDEX", + [ + "topic_id" + ] + ] + } + }, + "phpbb_topics_watch": { + "COLUMNS": { + "topic_id": [ + "ULINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "notify_status": [ + "BOOL", + 0 + ] + }, + "KEYS": { + "topic_id": [ + "INDEX", + "topic_id" + ], + "user_id": [ + "INDEX", + "user_id" + ], + "notify_stat": [ + "INDEX", + "notify_status" + ] + } + }, + "phpbb_user_group": { + "COLUMNS": { + "group_id": [ + "UINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "group_leader": [ + "BOOL", + 0 + ], + "user_pending": [ + "BOOL", + 1 + ] + }, + "KEYS": { + "group_id": [ + "INDEX", + "group_id" + ], + "user_id": [ + "INDEX", + "user_id" + ], + "group_leader": [ + "INDEX", + "group_leader" + ] + } + }, + "phpbb_user_notifications": { + "COLUMNS": { + "item_type": [ + "VCHAR:255", + "" + ], + "item_id": [ + "ULINT", + 0 + ], + "user_id": [ + "ULINT", + 0 + ], + "method": [ + "VCHAR:255", + "" + ], + "notify": [ + "BOOL", + 1 + ] + } + }, + "phpbb_users": { + "COLUMNS": { + "user_id": [ + "ULINT", + null, + "auto_increment" + ], + "user_type": [ + "TINT:2", + 0 + ], + "group_id": [ + "UINT", + 3 + ], + "user_permissions": [ + "MTEXT", + "" + ], + "user_perm_from": [ + "UINT", + 0 + ], + "user_ip": [ + "VCHAR:40", + "" + ], + "user_regdate": [ + "TIMESTAMP", + 0 + ], + "username": [ + "VCHAR_CI", + "" + ], + "username_clean": [ + "VCHAR_CI", + "" + ], + "user_password": [ + "VCHAR:255", + "" + ], + "user_passchg": [ + "TIMESTAMP", + 0 + ], + "user_email": [ + "VCHAR_UNI:100", + "" + ], + "user_email_hash": [ + "BINT", + 0 + ], + "user_birthday": [ + "VCHAR:10", + "" + ], + "user_lastvisit": [ + "TIMESTAMP", + 0 + ], + "user_lastmark": [ + "TIMESTAMP", + 0 + ], + "user_lastpost_time": [ + "TIMESTAMP", + 0 + ], + "user_lastpage": [ + "VCHAR_UNI:200", + "" + ], + "user_last_confirm_key": [ + "VCHAR:10", + "" + ], + "user_last_search": [ + "TIMESTAMP", + 0 + ], + "user_warnings": [ + "TINT:4", + 0 + ], + "user_last_warning": [ + "TIMESTAMP", + 0 + ], + "user_login_attempts": [ + "TINT:4", + 0 + ], + "user_inactive_reason": [ + "TINT:2", + 0 + ], + "user_inactive_time": [ + "TIMESTAMP", + 0 + ], + "user_posts": [ + "UINT", + 0 + ], + "user_lang": [ + "VCHAR:30", + "" + ], + "user_timezone": [ + "VCHAR:100", + "" + ], + "user_dateformat": [ + "VCHAR_UNI:64", + "d M Y H:i" + ], + "user_style": [ + "UINT", + 0 + ], + "user_rank": [ + "UINT", + 0 + ], + "user_colour": [ + "VCHAR:6", + "" + ], + "user_new_privmsg": [ + "INT:4", + 0 + ], + "user_unread_privmsg": [ + "INT:4", + 0 + ], + "user_last_privmsg": [ + "TIMESTAMP", + 0 + ], + "user_message_rules": [ + "BOOL", + 0 + ], + "user_full_folder": [ + "INT:11", + -3 + ], + "user_emailtime": [ + "TIMESTAMP", + 0 + ], + "user_topic_show_days": [ + "USINT", + 0 + ], + "user_topic_sortby_type": [ + "VCHAR:1", + "t" + ], + "user_topic_sortby_dir": [ + "VCHAR:1", + "d" + ], + "user_post_show_days": [ + "USINT", + 0 + ], + "user_post_sortby_type": [ + "VCHAR:1", + "t" + ], + "user_post_sortby_dir": [ + "VCHAR:1", + "a" + ], + "user_notify": [ + "BOOL", + 0 + ], + "user_notify_pm": [ + "BOOL", + 1 + ], + "user_notify_type": [ + "TINT:4", + 0 + ], + "user_allow_pm": [ + "BOOL", + 1 + ], + "user_allow_viewonline": [ + "BOOL", + 1 + ], + "user_allow_viewemail": [ + "BOOL", + 1 + ], + "user_allow_massemail": [ + "BOOL", + 1 + ], + "user_options": [ + "UINT:11", + 230271 + ], + "user_avatar": [ + "VCHAR", + "" + ], + "user_avatar_type": [ + "VCHAR:255", + "" + ], + "user_avatar_width": [ + "USINT", + 0 + ], + "user_avatar_height": [ + "USINT", + 0 + ], + "user_sig": [ + "MTEXT_UNI", + "" + ], + "user_sig_bbcode_uid": [ + "VCHAR:8", + "" + ], + "user_sig_bbcode_bitfield": [ + "VCHAR:255", + "" + ], + "user_jabber": [ + "VCHAR_UNI", + "" + ], + "user_actkey": [ + "VCHAR:32", + "" + ], + "user_newpasswd": [ + "VCHAR:255", + "" + ], + "user_form_salt": [ + "VCHAR_UNI:32", + "" + ], + "user_new": [ + "BOOL", + 1 + ], + "user_reminded": [ + "TINT:4", + 0 + ], + "user_reminded_time": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": "user_id", + "KEYS": { + "user_birthday": [ + "INDEX", + "user_birthday" + ], + "user_email_hash": [ + "INDEX", + "user_email_hash" + ], + "user_type": [ + "INDEX", + "user_type" + ], + "username_clean": [ + "UNIQUE", + "username_clean" + ] + } + }, + "phpbb_warnings": { + "COLUMNS": { + "warning_id": [ + "UINT", + null, + "auto_increment" + ], + "user_id": [ + "ULINT", + 0 + ], + "post_id": [ + "ULINT", + 0 + ], + "log_id": [ + "ULINT", + 0 + ], + "warning_time": [ + "TIMESTAMP", + 0 + ] + }, + "PRIMARY_KEY": "warning_id" + }, + "phpbb_words": { + "COLUMNS": { + "word_id": [ + "ULINT", + null, + "auto_increment" + ], + "word": [ + "VCHAR_UNI", + "" + ], + "replacement": [ + "VCHAR_UNI", + "" + ] + }, + "PRIMARY_KEY": "word_id" + }, + "phpbb_zebra": { + "COLUMNS": { + "user_id": [ + "ULINT", + 0 + ], + "zebra_id": [ + "ULINT", + 0 + ], + "friend": [ + "BOOL", + 0 + ], + "foe": [ + "BOOL", + 0 + ] + }, + "PRIMARY_KEY": [ + "user_id", + "zebra_id" + ] + } +}
\ No newline at end of file diff --git a/phpBB/install/schemas/schema_data.sql b/phpBB/install/schemas/schema_data.sql index 6e5cefc624..ede31e53e6 100644 --- a/phpBB/install/schemas/schema_data.sql +++ b/phpBB/install/schemas/schema_data.sql @@ -239,6 +239,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('queue_interval', ' INSERT INTO phpbb_config (config_name, config_value) VALUES ('ranks_path', 'images/ranks'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_expire_days', '30'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('read_notification_gc', '86400'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('remote_upload_verify', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('require_activation', '0'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('referer_validation', '1'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('script_path', ''); @@ -275,7 +276,7 @@ INSERT INTO phpbb_config (config_name, config_value) VALUES ('tpl_allow_php', '0 INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_icons_path', 'images/upload_icons'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('upload_path', 'files'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('use_system_cron', '0'); -INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-a3-dev'); +INSERT INTO phpbb_config (config_name, config_value) VALUES ('version', '3.2.0-b2-dev'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_expire_days', '90'); INSERT INTO phpbb_config (config_name, config_value) VALUES ('warnings_gc', '14400'); diff --git a/phpBB/install/startup.php b/phpBB/install/startup.php index 927f529b73..711768f9ac 100644 --- a/phpBB/install/startup.php +++ b/phpBB/install/startup.php @@ -101,6 +101,8 @@ $phpbb_class_loader_new = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path} $phpbb_class_loader_new->register(); $phpbb_class_loader = new \phpbb\class_loader('phpbb\\', "{$phpbb_root_path}phpbb/", $phpEx); $phpbb_class_loader->register(); +$phpbb_class_loader = new \phpbb\class_loader('phpbb\\convert\\', "{$phpbb_root_path}install/convert/", $phpEx); +$phpbb_class_loader->register(); $phpbb_class_loader_ext = new \phpbb\class_loader('\\', "{$phpbb_root_path}ext/", $phpEx); $phpbb_class_loader_ext->register(); diff --git a/phpBB/language/en/acp/board.php b/phpBB/language/en/acp/board.php index ba51595dc3..462d66a04a 100644 --- a/phpBB/language/en/acp/board.php +++ b/phpBB/language/en/acp/board.php @@ -535,6 +535,8 @@ $lang = array_merge($lang, array( 'REFERRER_VALID_EXPLAIN' => 'If enabled, the referrer of POST requests will be checked against the host/script path settings. This may cause issues with boards using several domains and or external logins.', 'TPL_ALLOW_PHP' => 'Allow php in templates', 'TPL_ALLOW_PHP_EXPLAIN' => 'If this option is enabled, <code>PHP</code> and <code>INCLUDEPHP</code> statements will be recognised and parsed in templates.', + 'UPLOAD_CERT_VALID' => 'Validate upload certificate', + 'UPLOAD_CERT_VALID_EXPLAIN' => 'If enabled, certificates of remote uploads will be validated. This requires the CA bundle to be defined by the <samp>openssl.cafile</samp> or <samp>curl.cainfo</samp> setting in your php.ini.', )); // Email Settings diff --git a/phpBB/language/en/help/bbcode.php b/phpBB/language/en/help/bbcode.php index e9f3562646..dc39749963 100644 --- a/phpBB/language/en/help/bbcode.php +++ b/phpBB/language/en/help/bbcode.php @@ -44,9 +44,9 @@ $lang = array_merge($lang, array( 'HELP_BBCODE_LINKS_BASIC_ANSWER' => 'phpBB BBCode supports a number of ways of creating URIs (Uniform Resource Indicators) better known as URLs.<ul><li>The first of these uses the <strong>[url=][/url]</strong> tag, whatever you type after the = sign will cause the contents of that tag to act as a URL. For example to link to phpBB.com you could use:<br /><br /><strong>[url=https://www.phpbb.com/]</strong>Visit phpBB!<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">Visit phpBB!</a> Please notice that the link opens in the same window or a new window depending on the users browser preferences.</li><li>If you want the URL itself displayed as the link you can do this by simply using:<br /><br /><strong>[url]</strong>https://www.phpbb.com/<strong>[/url]</strong><br /><br />This would generate the following link, <a href="https://www.phpbb.com/">https://www.phpbb.com/</a></li><li>Additionally, phpBB features something called <i>Magic Links</i>, this will turn any syntactically correct URL into a link without you needing to specify any tags or even the leading http://. For example typing www.phpbb.com into your message will automatically lead to <a href="http://www.phpbb.com/">www.phpbb.com</a> being output when you view the message.</li><li>The same thing applies equally to email addresses, you can either specify an address explicitly for example:<br /><br /><strong>[email]</strong>no.one@domain.adr<strong>[/email]</strong><br /><br />which will output <a href="mailto:no.one@domain.adr">no.one@domain.adr</a> or you can just type no.one@domain.adr into your message and it will be automatically converted when you view.</li></ul>As with all the BBCode tags you can wrap URLs around any of the other tags such as <strong>[img][/img]</strong> (see next entry), <strong>[b][/b]</strong>, etc. As with the formatting tags it is up to you to ensure the correct open and close order is following, for example:<br /><br /><strong>[url=https://www.phpbb.com/][img]</strong>https://www.phpbb.com/theme/images/logos/blue/160x52.png<strong>[/url][/img]</strong><br /><br />is <span style="text-decoration: underline">not</span> correct which may lead to your post being deleted so take care.', 'HELP_BBCODE_LINKS_BASIC_QUESTION' => 'Linking to another site', - 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use <strong>[list=1][/list]</strong> to create a numbered list or alternatively <strong>[list=a][/list]</strong> for an alphabetical list. As with the unordered list, items are specified using <strong>[*]</strong>. For example:<br /><br /><strong>[list=1]</strong><br /><strong>[*]</strong>Go to the shops<br /><strong>[*]</strong>Buy a new computer<br /><strong>[*]</strong>Swear at computer when it crashes<br /><strong>[/list]</strong><br /><br />will generate the following:<ol style="list-style-type: decimal;"><li>Go to the shops</li><li>Buy a new computer</li><li>Swear at computer when it crashes</li></ol>Whereas for an alphabetical list you would use:<br /><br /><strong>[list=a]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol>', + 'HELP_BBCODE_LISTS_ORDERER_ANSWER' => 'The second type of list, an ordered list, gives you control over what is output before each item. To create an ordered list you use <strong>[list=1][/list]</strong> to create a numbered list or alternatively <strong>[list=a][/list]</strong> for an alphabetical list. As with the unordered list, items are specified using <strong>[*]</strong>. For example:<br /><br /><strong>[list=1]</strong><br /><strong>[*]</strong>Go to the shops<br /><strong>[*]</strong>Buy a new computer<br /><strong>[*]</strong>Swear at computer when it crashes<br /><strong>[/list]</strong><br /><br />will generate the following:<ol style="list-style-type: decimal;"><li>Go to the shops</li><li>Buy a new computer</li><li>Swear at computer when it crashes</li></ol>Whereas for an alphabetical list you would use:<br /><br /><strong>[list=a]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=A]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-alpha"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=i]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: lower-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol><br /><strong>[list=I]</strong><br /><strong>[*]</strong>The first possible answer<br /><strong>[*]</strong>The second possible answer<br /><strong>[*]</strong>The third possible answer<br /><strong>[/list]</strong><br /><br />giving<ol style="list-style-type: upper-roman"><li>The first possible answer</li><li>The second possible answer</li><li>The third possible answer</li></ol>', 'HELP_BBCODE_LISTS_ORDERER_QUESTION' => 'Creating an Ordered list', - 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => 'BBCode supports two types of lists, unordered and ordered. They are essentially the same as their HTML equivalents. An unordered list outputs each item in your list sequentially one after the other indenting each with a bullet character. To create an unordered list you use <strong>[list][/list]</strong> and define each item within the list using <strong>[*]</strong>. For example to list your favourite colours you could use:<br /><br /><strong>[list]</strong><br /><strong>[*]</strong>Red<br /><strong>[*]</strong>Blue<br /><strong>[*]</strong>Yellow<br /><strong>[/list]</strong><br /><br />This would generate the following list:<ul><li>Red</li><li>Blue</li><li>Yellow</li></ul>', + 'HELP_BBCODE_LISTS_UNORDERER_ANSWER' => 'BBCode supports two types of lists, unordered and ordered. They are essentially the same as their HTML equivalents. An unordered list outputs each item in your list sequentially one after the other indenting each with a bullet character. To create an unordered list you use <strong>[list][/list]</strong> and define each item within the list using <strong>[*]</strong>. For example to list your favourite colours you could use:<br /><br /><strong>[list]</strong><br /><strong>[*]</strong>Red<br /><strong>[*]</strong>Blue<br /><strong>[*]</strong>Yellow<br /><strong>[/list]</strong><br /><br />This would generate the following list:<ul><li>Red</li><li>Blue</li><li>Yellow</li></ul><br />Alternatively you can specify the list’s bullet style using <strong>[list=disc][/list]</strong>, <strong>[list=circle][/list]</strong>, or <strong>[list=square][/list]</strong>.', 'HELP_BBCODE_LISTS_UNORDERER_QUESTION' => 'Creating an Unordered list', 'HELP_BBCODE_OTHERS_CUSTOM_ANSWER' => 'If you are an administrator on this board and have the proper permissions, you can add further BBCodes through the Custom BBCodes section.', diff --git a/phpBB/language/en/install.php b/phpBB/language/en/install.php index 0c539a7309..e643dd06c1 100644 --- a/phpBB/language/en/install.php +++ b/phpBB/language/en/install.php @@ -91,14 +91,14 @@ $lang = array_merge($lang, array( $lang = array_merge($lang, array( // Filesystem requirements 'FILE_NOT_EXISTS' => 'File not exists', - 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s file need to exist.', + 'FILE_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB the %1$s file needs to exist.', 'FILE_NOT_WRITABLE' => 'File not writable', - 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s file need to be writable.', + 'FILE_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB the %1$s file needs to be writable.', 'DIRECTORY_NOT_EXISTS' => 'Directory not exists', - 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB %1$s directory need to exist.', + 'DIRECTORY_NOT_EXISTS_EXPLAIN' => 'To be able to install phpBB the %1$s directory needs to exist.', 'DIRECTORY_NOT_WRITABLE' => 'Directory not writable', - 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB %1$s directory need to be writable.', + 'DIRECTORY_NOT_WRITABLE_EXPLAIN' => 'To be able to install phpBB the %1$s directory needs to be writable.', // Server requirements 'PHP_VERSION_REQD' => 'PHP version', @@ -439,3 +439,112 @@ $lang = array_merge($lang, array( 'INLINE_UPDATE_SUCCESSFUL' => 'The database update was successful.', )); + +// Converter +$lang = array_merge($lang, array( + // Common converter messages + 'CONVERT_NOT_EXIST' => 'The specified convertor does not exist.', + 'DEV_NO_TEST_FILE' => 'No value has been specified for the test_file variable in the convertor. If you are a user of this convertor, you should not be seeing this error, please report this message to the convertor author. If you are a convertor author, you must specify the name of a file which exists in the source board to allow the path to it to be verified.', + 'COULD_NOT_FIND_PATH' => 'Could not find path to your former board. Please check your settings and try again.<br />» %s was specified as the source path.', + 'CONFIG_PHPBB_EMPTY' => 'The phpBB3 config variable for “%s” is empty.', + + 'MAKE_FOLDER_WRITABLE' => 'Please make sure that this folder exists and is writable by the webserver then try again:<br />»<strong>%s</strong>.', + 'MAKE_FOLDERS_WRITABLE' => 'Please make sure that these folders exist and are writable by the webserver then try again:<br />»<strong>%s</strong>.', + + 'INSTALL_TEST' => 'Test again', + + 'NO_TABLES_FOUND' => 'No tables found.', + 'TABLES_MISSING' => 'Could not find these tables<br />» <strong>%s</strong>.', + 'CHECK_TABLE_PREFIX' => 'Please check your table prefix and try again.', + + // Conversion in progress + 'CONTINUE_CONVERT' => 'Continue conversion', + 'CONTINUE_CONVERT_BODY' => 'A previous conversion attempt has been determined. You are now able to choose between starting a new conversion or continuing the conversion.', + 'CONVERT_NEW_CONVERSION' => 'New conversion', + 'CONTINUE_OLD_CONVERSION' => 'Continue previously started conversion', + + // Start conversion + 'SUB_INTRO' => 'Introduction', + 'CONVERT_INTRO' => 'Welcome to the phpBB Unified Convertor Framework', + 'CONVERT_INTRO_BODY' => 'From here, you are able to import data from other (installed) board systems. The list below shows all the conversion modules currently available. If there is no convertor shown in this list for the board software you wish to convert from, please check our website where further conversion modules may be available for download.', + 'AVAILABLE_CONVERTORS' => 'Available convertors', + 'NO_CONVERTORS' => 'No convertors are available for use.', + 'CONVERT_OPTIONS' => 'Options', + 'SOFTWARE' => 'Board software', + 'VERSION' => 'Version', + 'CONVERT' => 'Convert', + + // Settings + 'STAGE_SETTINGS' => 'Settings', + 'TABLE_PREFIX_SAME' => 'The table prefix needs to be the one used by the software you are converting from.<br />» Specified table prefix was %s.', + 'DEFAULT_PREFIX_IS' => 'The convertor was not able to find tables with the specified prefix. Please make sure you have entered the correct details for the board you are converting from. The default table prefix for %1$s is <strong>%2$s</strong>.', + 'SPECIFY_OPTIONS' => 'Specify conversion options', + 'FORUM_PATH' => 'Board path', + 'FORUM_PATH_EXPLAIN' => 'This is the <strong>relative</strong> path on disk to your former board from the <strong>root of this phpBB3 installation</strong>.', + 'REFRESH_PAGE' => 'Refresh page to continue conversion', + 'REFRESH_PAGE_EXPLAIN' => 'If set to yes, the convertor will refresh the page to continue the conversion after having finished a step. If this is your first conversion for testing purposes and to determine any errors in advance, we suggest to set this to No.', + + // Conversion + 'STAGE_IN_PROGRESS' => 'Conversion in progress', + + 'AUTHOR_NOTES' => 'Author notes<br />» %s', + 'STARTING_CONVERT' => 'Starting conversion process', + 'CONFIG_CONVERT' => 'Converting the configuration', + 'DONE' => 'Done', + 'PREPROCESS_STEP' => 'Executing pre-processing functions/queries', + 'FILLING_TABLE' => 'Filling table <strong>%s</strong>', + 'FILLING_TABLES' => 'Filling tables', + 'DB_ERR_INSERT' => 'Error while processing <code>INSERT</code> query.', + 'DB_ERR_LAST' => 'Error while processing <var>query_last</var>.', + 'DB_ERR_QUERY_FIRST' => 'Error while executing <var>query_first</var>.', + 'DB_ERR_QUERY_FIRST_TABLE' => 'Error while executing <var>query_first</var>, %s (“%s”).', + 'DB_ERR_SELECT' => 'Error while running <code>SELECT</code> query.', + 'STEP_PERCENT_COMPLETED' => 'Step <strong>%d</strong> of <strong>%d</strong>', + 'FINAL_STEP' => 'Process final step', + 'SYNC_FORUMS' => 'Starting to synchronise forums', + 'SYNC_POST_COUNT' => 'Synchronising post_counts', + 'SYNC_POST_COUNT_ID' => 'Synchronising post_counts from <var>entry</var> %1$s to %2$s.', + 'SYNC_TOPICS' => 'Starting to synchronise topics', + 'SYNC_TOPIC_ID' => 'Synchronising topics from <var>topic_id</var> %1$s to %2$s.', + 'PROCESS_LAST' => 'Processing last statements', + 'UPDATE_TOPICS_POSTED' => 'Generating topics posted information', + 'UPDATE_TOPICS_POSTED_ERR' => 'An error occurred while generating topics posted information. You can retry this step in the ACP after the conversion process is completed.', + 'CONTINUE_LAST' => 'Continue last statements', + 'CLEAN_VERIFY' => 'Cleaning up and verifying the final structure', + 'NOT_UNDERSTAND' => 'Could not understand %s #%d, table %s (“%s”)', + 'NAMING_CONFLICT' => 'Naming conflict: %s and %s are both aliases<br /><br />%s', + + // Finish conversion + 'CONVERT_COMPLETE' => 'Conversion completed', + 'CONVERT_COMPLETE_EXPLAIN' => 'You have now successfully converted your board to phpBB 3.2. You can now login and <a href="../">access your board</a>. Please ensure that the settings were transferred correctly before enabling your board by deleting the install directory. Remember that help on using phpBB is available online via the <a href="https://www.phpbb.com/support/docs/en/3.2/ug/">Documentation</a> and the <a href="https://www.phpbb.com/community/viewforum.php?f=466">support forums</a>.', + + 'CONV_ERROR_ATTACH_FTP_DIR' => 'FTP upload for attachments is enabled at the old board. Please disable the FTP upload option and make sure a valid upload directory is specified, then copy all attachment files to this new web accessible directory. Once you have done this, restart the convertor.', + 'CONV_ERROR_CONFIG_EMPTY' => 'There is no configuration information available for the conversion.', + 'CONV_ERROR_FORUM_ACCESS' => 'Unable to get forum access information.', + 'CONV_ERROR_GET_CATEGORIES' => 'Unable to get categories.', + 'CONV_ERROR_GET_CONFIG' => 'Could not retrieve your board configuration.', + 'CONV_ERROR_COULD_NOT_READ' => 'Unable to access/read “%s”.', + 'CONV_ERROR_GROUP_ACCESS' => 'Unable to get group authentication information.', + 'CONV_ERROR_INCONSISTENT_GROUPS' => 'Inconsistency in groups table detected in add_bots() - you need to add all special groups if you do it manually.', + 'CONV_ERROR_INSERT_BOT' => 'Unable to insert bot into users table.', + 'CONV_ERROR_INSERT_BOTGROUP' => 'Unable to insert bot into bots table.', + 'CONV_ERROR_INSERT_USER_GROUP' => 'Unable to insert user into user_group table.', + 'CONV_ERROR_MESSAGE_PARSER' => 'Message parser error', + 'CONV_ERROR_NO_AVATAR_PATH' => 'Note to developer: you must specify $convertor[\'avatar_path\'] to use %s.', + 'CONV_ERROR_NO_FORUM_PATH' => 'The relative path to the source board has not been specified.', + 'CONV_ERROR_NO_GALLERY_PATH' => 'Note to developer: you must specify $convertor[\'avatar_gallery_path\'] to use %s.', + 'CONV_ERROR_NO_GROUP' => 'Group “%1$s” could not be found in %2$s.', + 'CONV_ERROR_NO_RANKS_PATH' => 'Note to developer: you must specify $convertor[\'ranks_path\'] to use %s.', + 'CONV_ERROR_NO_SMILIES_PATH' => 'Note to developer: you must specify $convertor[\'smilies_path\'] to use %s.', + 'CONV_ERROR_NO_UPLOAD_DIR' => 'Note to developer: you must specify $convertor[\'upload_path\'] to use %s.', + 'CONV_ERROR_PERM_SETTING' => 'Unable to insert/update permission setting.', + 'CONV_ERROR_PM_COUNT' => 'Unable to select folder pm count.', + 'CONV_ERROR_REPLACE_CATEGORY' => 'Unable to insert new forum replacing old category.', + 'CONV_ERROR_REPLACE_FORUM' => 'Unable to insert new forum replacing old forum.', + 'CONV_ERROR_USER_ACCESS' => 'Unable to get user authentication information.', + 'CONV_ERROR_WRONG_GROUP' => 'Wrong group “%1$s” defined in %2$s.', + 'CONV_OPTIONS_BODY' => 'This page collects the data required to access the source board. Enter the database details of your former board; the converter will not change anything in the database given below. The source board should be disabled to allow a consistent conversion.', + 'CONV_SAVED_MESSAGES' => 'Saved messages', + + 'PRE_CONVERT_COMPLETE' => 'All pre-conversion steps have successfully been completed. You may now begin the actual conversion process. Please note that you may have to manually do and adjust several things. After conversion, especially check the permissions assigned, rebuild your search index which is not converted and also make sure files got copied correctly, for example avatars and smilies.', +)); diff --git a/phpBB/phpbb/db/migration/data/v31x/v318rc1.php b/phpBB/phpbb/db/migration/data/v31x/v318rc1.php new file mode 100644 index 0000000000..8bae95c7d6 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v318rc1.php @@ -0,0 +1,32 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v31x; + +class v318rc1 extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\increase_size_of_dateformat', + '\phpbb\db\migration\data\v31x\v317pl1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.8-RC1')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php b/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php new file mode 100644 index 0000000000..d61f6b96fd --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/remote_upload_validation.php @@ -0,0 +1,31 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v320; + +class remote_upload_validation extends \phpbb\db\migration\migration +{ + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v320\v320a2', + ); + } + + public function update_data() + { + return array( + array('config.add', array('remote_upload_verify', '0')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v320/text_reparser.php b/phpBB/phpbb/db/migration/data/v320/text_reparser.php index 1d73b74a76..ea614feb40 100644 --- a/phpBB/phpbb/db/migration/data/v320/text_reparser.php +++ b/phpBB/phpbb/db/migration/data/v320/text_reparser.php @@ -17,7 +17,10 @@ class text_reparser extends \phpbb\db\migration\container_aware_migration { static public function depends_on() { - return array('\phpbb\db\migration\data\v310\contact_admin_form'); + return array( + '\phpbb\db\migration\data\v310\contact_admin_form', + '\phpbb\db\migration\data\v320\allowed_schemes_links', + ); } public function effectively_installed() @@ -78,7 +81,7 @@ class text_reparser extends \phpbb\db\migration\container_aware_migration $end = max(1, $resume_data['current']); $reparser->reparse_range($start, $end); - $processed_records = $end - $start + 1; + $processed_records += $end - $start + 1; $resume_data['current'] = $start - 1; if ($start === 1) diff --git a/phpBB/phpbb/db/migration/data/v320/v320b1.php b/phpBB/phpbb/db/migration/data/v320/v320b1.php new file mode 100644 index 0000000000..5c3a3797cd --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/v320b1.php @@ -0,0 +1,39 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +namespace phpbb\db\migration\data\v320; + +class v320b1 extends \phpbb\db\migration\container_aware_migration +{ + public function effectively_installed() + { + return version_compare($this->config['version'], '3.2.0-b1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v317pl1', + '\phpbb\db\migration\data\v320\v320a2', + '\phpbb\db\migration\data\v31x\increase_size_of_dateformat', + '\phpbb\db\migration\data\v320\default_data_type_ids', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.0-b1')), + ); + } +} diff --git a/phpBB/phpbb/files/types/remote.php b/phpBB/phpbb/files/types/remote.php index 33cbfb00ae..1fdba0ca32 100644 --- a/phpBB/phpbb/files/types/remote.php +++ b/phpBB/phpbb/files/types/remote.php @@ -14,6 +14,7 @@ namespace phpbb\files\types; use bantu\IniGetWrapper\IniGetWrapper; +use phpbb\config\config; use phpbb\files\factory; use phpbb\files\filespec; use phpbb\language\language; @@ -21,6 +22,9 @@ use phpbb\request\request_interface; class remote extends base { + /** @var config phpBB config */ + protected $config; + /** @var factory Files factory */ protected $factory; @@ -42,14 +46,16 @@ class remote extends base /** * Construct a form upload type * + * @param config $config phpBB config * @param factory $factory Files factory * @param language $language Language class * @param IniGetWrapper $php_ini ini_get() wrapper * @param request_interface $request Request object * @param string $phpbb_root_path phpBB root path */ - public function __construct(factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path) + public function __construct(config $config, factory $factory, language $language, IniGetWrapper $php_ini, request_interface $request, $phpbb_root_path) { + $this->config = $config; $this->factory = $factory; $this->language = $language; $this->php_ini = $php_ini; @@ -86,10 +92,6 @@ class remote extends base $url = parse_url($upload_url); - $host = $url['host']; - $path = $url['path']; - $port = (!empty($url['port'])) ? (int) $url['port'] : 80; - $upload_ary['type'] = 'application/octet-stream'; $url['path'] = explode('.', $url['path']); @@ -97,108 +99,55 @@ class remote extends base $url['path'] = implode('', $url['path']); $upload_ary['name'] = utf8_basename($url['path']) . (($ext) ? '.' . $ext : ''); - $filesize = 0; $remote_max_filesize = $this->get_max_file_size(); - $errno = 0; - $errstr = ''; + $guzzle_options = [ + 'timeout' => $this->upload->upload_timeout, + 'connect_timeout' => $this->upload->upload_timeout, + 'verify' => !empty($this->config['remote_upload_verify']) ? (bool) $this->config['remote_upload_verify'] : false, + ]; + $client = new \GuzzleHttp\Client($guzzle_options); - if (!($fsock = @fsockopen($host, $port, $errno, $errstr))) + try { - return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); + $response = $client->get($upload_url, $guzzle_options); } - - // Make sure $path not beginning with / - if (strpos($path, '/') === 0) + catch (\GuzzleHttp\Exception\ClientException $clientException) { - $path = substr($path, 1); + return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND'); } - - fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n"); - fputs($fsock, "HOST: " . $host . "\r\n"); - fputs($fsock, "Connection: close\r\n\r\n"); - - // Set a proper timeout for the socket - socket_set_timeout($fsock, $this->upload->upload_timeout); - - $get_info = false; - $data = ''; - $length = false; - $timer_stop = time() + $this->upload->upload_timeout; - - while ((!$length || $filesize < $length) && !@feof($fsock)) + catch (\GuzzleHttp\Exception\RequestException $requestException) { - if ($get_info) + if (strpos($requestException->getMessage(), 'cURL error 28') !== false || preg_match('/408|504/', $requestException->getCode())) { - if ($length) - { - // Don't attempt to read past end of file if server indicated length - $block = @fread($fsock, min($length - $filesize, 1024)); - } - else - { - $block = @fread($fsock, 1024); - } - - $filesize += strlen($block); - - if ($remote_max_filesize && $filesize > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); - } - - $data .= $block; + return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT'); } else { - $line = @fgets($fsock, 1024); - - if ($line == "\r\n") - { - $get_info = true; - } - else - { - if (stripos($line, 'content-type: ') !== false) - { - $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line))); - } - else if ($this->upload->max_filesize && stripos($line, 'content-length: ') !== false) - { - $length = (int) str_replace('content-length: ', '', strtolower($line)); - - if ($remote_max_filesize && $length && $length > $remote_max_filesize) - { - $max_filesize = get_formatted_filesize($remote_max_filesize, false); - - return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); - } - } - else if (stripos($line, '404 not found') !== false) - { - return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'URL_NOT_FOUND'); - } - } + return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); } + } + catch (\Exception $e) + { + return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'NOT_UPLOADED')); + } - $stream_meta_data = stream_get_meta_data($fsock); + $content_length = $response->getBody()->getSize(); + if ($remote_max_filesize && $content_length > $remote_max_filesize) + { + $max_filesize = get_formatted_filesize($remote_max_filesize, false); - // Cancel upload if we exceed timeout - if (!empty($stream_meta_data['timed_out']) || time() >= $timer_stop) - { - return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'REMOTE_UPLOAD_TIMEOUT'); - } + return $this->factory->get('filespec')->set_error($this->language->lang($this->upload->error_prefix . 'WRONG_FILESIZE', $max_filesize['value'], $max_filesize['unit'])); } - @fclose($fsock); - if (empty($data)) + if ($content_length == 0) { return $this->factory->get('filespec')->set_error($this->upload->error_prefix . 'EMPTY_REMOTE_DATA'); } + $data = $response->getBody(); + $filename = tempnam(sys_get_temp_dir(), unique_id() . '-'); if (!($fp = @fopen($filename, 'wb'))) diff --git a/phpBB/phpbb/install/controller/archive_download.php b/phpBB/phpbb/install/controller/archive_download.php index a0f0ba181d..eabc0a9976 100644 --- a/phpBB/phpbb/install/controller/archive_download.php +++ b/phpBB/phpbb/install/controller/archive_download.php @@ -46,9 +46,9 @@ class archive_download */ public function conflict_archive() { - $filename = $this->installer_config->get('update_file_conflict_archive', false); + $filename = $this->installer_config->get('update_file_conflict_archive', ''); - if (!$filename) + if (empty($filename)) { throw new http_exception(404, 'URL_NOT_FOUND'); } @@ -65,7 +65,7 @@ class archive_download { $filename = $this->installer_config->get('update_file_archive', ''); - if (!$filename) + if (empty($filename)) { throw new http_exception(404, 'URL_NOT_FOUND'); } diff --git a/phpBB/phpbb/install/controller/helper.php b/phpBB/phpbb/install/controller/helper.php index 2dad42b4b6..ff7e691224 100644 --- a/phpBB/phpbb/install/controller/helper.php +++ b/phpBB/phpbb/install/controller/helper.php @@ -160,12 +160,13 @@ class helper * Returns path from route name * * @param string $route_name + * @param array $parameters * * @return string */ - public function route($route_name) + public function route($route_name, $parameters = array()) { - $url = $this->router->generate($route_name); + $url = $this->router->generate($route_name, $parameters); return $url; } @@ -182,11 +183,6 @@ class helper if (!empty($submit)) { $lang = $this->phpbb_request->variable('language', ''); - - if (!empty($lang)) - { - $this->language_cookie = $lang; - } } // Retrieve language from cookie @@ -194,10 +190,10 @@ class helper if (empty($lang) && !empty($lang_cookie)) { $lang = $lang_cookie; - $this->language_cookie = $lang; } $lang = (!empty($lang) && strpos($lang, '/') === false) ? $lang : null; + $this->language_cookie = $lang; $this->render_language_select($lang); diff --git a/phpBB/phpbb/install/controller/install.php b/phpBB/phpbb/install/controller/install.php index b987d91c6a..92506872a3 100644 --- a/phpBB/phpbb/install/controller/install.php +++ b/phpBB/phpbb/install/controller/install.php @@ -123,6 +123,7 @@ class install // Set the appropriate input-output handler $this->installer->set_iohandler($this->iohandler_factory->get()); + $this->controller_helper->handle_language_select(); if ($this->request->is_ajax()) { @@ -142,8 +143,6 @@ class install // Determine whether the installation was started or not if (true) { - $this->controller_helper->handle_language_select(); - // Set active stage $this->menu_provider->set_nav_property( array('install', 0, 'introduction'), diff --git a/phpBB/phpbb/install/controller/update.php b/phpBB/phpbb/install/controller/update.php index 9fff11cae8..6b88827940 100644 --- a/phpBB/phpbb/install/controller/update.php +++ b/phpBB/phpbb/install/controller/update.php @@ -122,6 +122,7 @@ class update // Set the appropriate input-output handler $this->installer->set_iohandler($this->iohandler_factory->get()); + $this->controller_helper->handle_language_select(); // Render the intro page if ($this->request->is_ajax()) @@ -140,8 +141,6 @@ class update } else { - $this->controller_helper->handle_language_select(); - // Set active stage $this->menu_provider->set_nav_property( array('update', 0, 'introduction'), diff --git a/phpBB/phpbb/install/helper/config.php b/phpBB/phpbb/install/helper/config.php index 0f0840f470..f58925899b 100644 --- a/phpBB/phpbb/install/helper/config.php +++ b/phpBB/phpbb/install/helper/config.php @@ -157,10 +157,10 @@ class config { if ($this->system_data['max_execution_time'] <= 0) { - return 1; + return PHP_INT_MAX; } - return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - time(); + return ($this->system_data['start_time'] + $this->system_data['max_execution_time']) - microtime(true); } /** @@ -227,18 +227,22 @@ class config $file_content = @file_get_contents($this->install_config_file); $serialized_data = trim(substr($file_content, 8)); - $this->installer_config = array(); - $this->progress_data = array(); - $this->navigation_data = array(); + $installer_config = array(); + $progress_data = array(); + $navigation_data = array(); if (!empty($serialized_data)) { $unserialized_data = json_decode($serialized_data, true); - $this->installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array(); - $this->progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array(); - $this->navigation_data = (is_array($unserialized_data['navigation_data'])) ? $unserialized_data['navigation_data'] : array(); + $installer_config = (is_array($unserialized_data['installer_config'])) ? $unserialized_data['installer_config'] : array(); + $progress_data = (is_array($unserialized_data['progress_data'])) ? $unserialized_data['progress_data'] : array(); + $navigation_data = (is_array($unserialized_data['navigation_data'])) ? $unserialized_data['navigation_data'] : array(); } + + $this->installer_config = array_merge($this->installer_config, $installer_config); + $this->progress_data = array_merge($this->progress_data, $progress_data); + $this->navigation_data = array_merge($this->navigation_data, $navigation_data); } /** @@ -430,7 +434,7 @@ class config $this->system_data['max_execution_time'] = $execution_time; // Set start time - $this->system_data['start_time'] = time(); + $this->system_data['start_time'] = microtime(true); // Get memory limit $this->system_data['memory_limit'] = $this->php_ini->getBytes('memory_limit'); diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index 1342ffa30f..31474ae4e9 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -72,6 +72,11 @@ class ajax_iohandler extends iohandler_base protected $download; /** + * @var array + */ + protected $redirect_url; + + /** * Constructor * * @param path_helper $path_helper @@ -89,6 +94,7 @@ class ajax_iohandler extends iohandler_base $this->nav_data = array(); $this->cookies = array(); $this->download = array(); + $this->redirect_url = array(); $this->file_status = ''; parent::__construct(); @@ -131,6 +137,14 @@ class ajax_iohandler extends iohandler_base */ public function add_user_form_group($title, $form) { + $this->form = $this->generate_form_render_data($title, $form); + } + + /** + * {@inheritdoc} + */ + public function generate_form_render_data($title, $form) + { $this->template->assign_block_vars('options', array( 'LEGEND' => $this->language->lang($title), 'S_LEGEND' => true, @@ -189,7 +203,7 @@ class ajax_iohandler extends iohandler_base 'form_install' => 'installer_form.html', )); - $this->form = $this->template->assign_display('form_install'); + return $this->template->assign_display('form_install'); } /** @@ -273,6 +287,12 @@ class ajax_iohandler extends iohandler_base $this->cookies = array(); } + if (!empty($this->redirect_url)) + { + $json_array['redirect'] = $this->redirect_url; + $this->redirect_url = array(); + } + return $json_array; } @@ -373,6 +393,15 @@ class ajax_iohandler extends iohandler_base } /** + * {@inheritdoc} + */ + public function redirect($url, $use_ajax = false) + { + $this->redirect_url = array('url' => $url, 'use_ajax' => $use_ajax); + $this->send_response(); + } + + /** * Callback function for language replacing * * @param array $matches diff --git a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php index 89f3594378..7945904524 100644 --- a/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/cli_iohandler.php @@ -289,4 +289,11 @@ class cli_iohandler extends iohandler_base public function render_update_file_status($status_array) { } + + /** + * {@inheritdoc} + */ + public function redirect($url, $use_ajax = false) + { + } } diff --git a/phpBB/phpbb/install/helper/iohandler/factory.php b/phpBB/phpbb/install/helper/iohandler/factory.php index 52d24e49b2..1e8395760a 100644 --- a/phpBB/phpbb/install/helper/iohandler/factory.php +++ b/phpBB/phpbb/install/helper/iohandler/factory.php @@ -75,7 +75,5 @@ class factory throw new iohandler_not_implemented_exception(); break; } - - throw new iohandler_not_implemented_exception(); } } diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php index 7271fe9bc0..fed4bc101f 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_base.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_base.php @@ -170,6 +170,14 @@ abstract class iohandler_base implements iohandler_interface } /** + * {@inheritdoc} + */ + public function generate_form_render_data($title, $form) + { + return ''; + } + + /** * Localize message. * * Note: When an array is passed into the parameters below, it will be diff --git a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php index 00aab3283e..6b3839506f 100644 --- a/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php +++ b/phpBB/phpbb/install/helper/iohandler/iohandler_interface.php @@ -124,6 +124,16 @@ interface iohandler_interface public function add_user_form_group($title, $form); /** + * Returns the rendering information for the form + * + * @param string $title Language variable with the title of the form + * @param array $form An array describing the required data (options etc) + * + * @return string Information to render the form + */ + public function generate_form_render_data($title, $form); + + /** * Sets the number of tasks belonging to the installer in the current mode. * * @param int $task_count Number of tasks @@ -175,6 +185,14 @@ interface iohandler_interface public function add_download_link($route, $title, $msg = null); /** + * Redirects the user to a new page + * + * @param string $url URL to redirect to + * @param bool $use_ajax Whether or not to use AJAX redirect + */ + public function redirect($url, $use_ajax = false); + + /** * Renders the status of update files * * @param array $status_array Array containing files in groups to render diff --git a/phpBB/phpbb/install/helper/navigation/convertor_navigation.php b/phpBB/phpbb/install/helper/navigation/convertor_navigation.php new file mode 100644 index 0000000000..54cab83b1d --- /dev/null +++ b/phpBB/phpbb/install/helper/navigation/convertor_navigation.php @@ -0,0 +1,78 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\install\helper\navigation; + +use phpbb\install\helper\install_helper; + +class convertor_navigation implements navigation_interface +{ + /** + * @var install_helper + */ + private $install_helper; + + /** + * Constructor + * + * @param install_helper $install_helper + */ + public function __construct(install_helper $install_helper) + { + $this->install_helper = $install_helper; + } + + /** + * {@inheritdoc} + */ + public function get() + { + if (!$this->install_helper->is_phpbb_installed()) + { + return array(); + } + + return array( + 'convert' => array( + 'label' => 'CONVERT', + 'route' => 'phpbb_convert_intro', + 'order' => 3, + array( + 'intro' => array( + 'label' => 'SUB_INTRO', + 'stage' => true, + 'order' => 0, + ), + 'settings' => array( + 'label' => 'STAGE_SETTINGS', + 'stage' => true, + 'route' => 'phpbb_convert_settings', + 'order' => 1, + ), + 'convert' => array( + 'label' => 'STAGE_IN_PROGRESS', + 'stage' => true, + 'route' => 'phpbb_convert_convert', + 'order' => 2, + ), + 'finish' => array( + 'label' => 'CONVERT_COMPLETE', + 'stage' => true, + 'route' => 'phpbb_convert_finish', + 'order' => 3, + ), + ), + ), + ); + } +} diff --git a/phpBB/phpbb/install/module/install_database/task/create_schema.php b/phpBB/phpbb/install/module/install_database/task/create_schema.php index cabb78787f..a5635d5dbe 100644 --- a/phpBB/phpbb/install/module/install_database/task/create_schema.php +++ b/phpBB/phpbb/install/module/install_database/task/create_schema.php @@ -13,6 +13,8 @@ namespace phpbb\install\module\install_database\task; +use phpbb\install\exception\resource_limit_reached_exception; + /** * Create database schema */ @@ -106,6 +108,17 @@ class create_schema extends \phpbb\install\task_base */ public function run() { + // As this task may take a large amount of time to complete refreshing the page might be necessary for some + // server configurations with limited resources + if (!$this->config->get('pre_schema_forced_refresh')) + { + if ($this->config->get_time_remaining() < 5) + { + $this->config->set('pre_schema_forced_refresh', true); + throw new resource_limit_reached_exception(); + } + } + $this->db->sql_return_on_error(true); $dbms = $this->config->get('dbms'); diff --git a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php index 6a98721e77..be6404dcd8 100644 --- a/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php +++ b/phpBB/phpbb/install/module/obtain_data/task/obtain_update_settings.php @@ -57,22 +57,35 @@ class obtain_update_settings extends task_base } else { + if ($this->installer_config->get('disable_filesystem_update', false)) + { + $options[] = array( + 'value' => 'db_only', + 'label' => 'UPDATE_TYPE_DB_ONLY', + 'selected' => true, + ); + } + else + { + $options = array( + array( + 'value' => 'all', + 'label' => 'UPDATE_TYPE_ALL', + 'selected' => true, + ), + array( + 'value' => 'db_only', + 'label' => 'UPDATE_TYPE_DB_ONLY', + 'selected' => false, + ), + ); + } + $this->iohandler->add_user_form_group('UPDATE_TYPE', array( 'update_type' => array( 'label' => 'UPDATE_TYPE', 'type' => 'radio', - 'options' => array( - array( - 'value' => 'all', - 'label' => 'UPDATE_TYPE_ALL', - 'selected' => true, - ), - array( - 'value' => 'db_only', - 'label' => 'UPDATE_TYPE_DB_ONLY', - 'selected' => false, - ), - ), + 'options' => $options, ), 'submit_update' => array( 'label' => 'SUBMIT', diff --git a/phpBB/phpbb/install/module/requirements/task/check_update.php b/phpBB/phpbb/install/module/requirements/task/check_update.php index c986c76810..4e9124ff47 100644 --- a/phpBB/phpbb/install/module/requirements/task/check_update.php +++ b/phpBB/phpbb/install/module/requirements/task/check_update.php @@ -14,6 +14,7 @@ namespace phpbb\install\module\requirements\task; use phpbb\filesystem\filesystem; +use phpbb\install\helper\config; use phpbb\install\helper\container_factory; use phpbb\install\helper\iohandler\iohandler_interface; use phpbb\install\helper\update_helper; @@ -35,6 +36,11 @@ class check_update extends task_base protected $filesystem; /** + * @var config + */ + protected $installer_config; + + /** * @var iohandler_interface */ protected $iohandler; @@ -69,14 +75,16 @@ class check_update extends task_base * * @param container_factory $container * @param filesystem $filesystem + * @param config $config * @param iohandler_interface $iohandler * @param update_helper $update_helper * @param string $phpbb_root_path * @param string $php_ext */ - public function __construct(container_factory $container, filesystem $filesystem, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext) + public function __construct(container_factory $container, filesystem $filesystem, config $config, iohandler_interface $iohandler, update_helper $update_helper, $phpbb_root_path, $php_ext) { $this->filesystem = $filesystem; + $this->installer_config = $config; $this->iohandler = $iohandler; $this->update_helper = $update_helper; $this->phpbb_root_path = $phpbb_root_path; @@ -117,8 +125,10 @@ class check_update extends task_base $this->iohandler->add_error_message('UPDATE_FILES_NOT_FOUND'); $this->set_test_passed(false); - // If there are no update files, we can't check the version - return false; + // If there are no update files, we can't check the version etc + // However, we can let the users run migrations if they really want to... + $this->installer_config->set('disable_filesystem_update', true); + return true; } // Recover version numbers diff --git a/phpBB/phpbb/install/module/update_database/task/update.php b/phpBB/phpbb/install/module/update_database/task/update.php index 4b2baf2c23..aa44d403dd 100644 --- a/phpBB/phpbb/install/module/update_database/task/update.php +++ b/phpBB/phpbb/install/module/update_database/task/update.php @@ -158,6 +158,7 @@ class update extends task_base array_unshift($msg, $e->getMessage()); $this->iohandler->add_error_message($msg); + $this->iohandler->send_response(); throw new user_interaction_required_exception(); } diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index 7b0d6f0fba..154361ef64 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -100,11 +100,18 @@ class path_helper */ public function update_web_root_path($path) { + $web_root_path = $this->get_web_root_path(); + + // Removes the web root path if it is already present + if (strpos($path, $web_root_path) === 0) + { + $path = $this->phpbb_root_path . substr($path, strlen($web_root_path)); + } + if (strpos($path, $this->phpbb_root_path) === 0) { $path = substr($path, strlen($this->phpbb_root_path)); - $web_root_path = $this->get_web_root_path(); if (substr($web_root_path, -8) === 'app.php/' && substr($path, 0, 7) === 'app.php') { $path = substr($path, 8); diff --git a/phpBB/phpbb/session.php b/phpBB/phpbb/session.php index 3f7146c59b..12031bda03 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -1600,6 +1600,8 @@ class session $db->sql_return_on_error(false); + $this->data = array_merge($this->data, $sql_ary); + if ($this->data['user_id'] != ANONYMOUS && !empty($config['new_member_post_limit']) && $this->data['user_new'] && $config['new_member_post_limit'] <= $this->data['user_posts']) { $this->leave_newly_registered(); diff --git a/phpBB/phpbb/template/twig/definition.php b/phpBB/phpbb/template/twig/definition.php index cb3c953692..205f0e68ee 100644 --- a/phpBB/phpbb/template/twig/definition.php +++ b/phpBB/phpbb/template/twig/definition.php @@ -19,7 +19,10 @@ namespace phpbb\template\twig; class definition { /** @var array **/ - protected $definitions = array(); + protected $definitions = array( + 'SCRIPTS' => '__SCRIPTS_PLACEHOLDER__', + 'STYLESHEETS' => '__STYLESHEETS_PLACEHOLDER__' + ); /** * Get a DEFINE'd variable diff --git a/phpBB/phpbb/template/twig/node/includeasset.php b/phpBB/phpbb/template/twig/node/includeasset.php index 3d3c6e4df8..6d50eafc9d 100644 --- a/phpBB/phpbb/template/twig/node/includeasset.php +++ b/phpBB/phpbb/template/twig/node/includeasset.php @@ -53,8 +53,6 @@ abstract class includeasset extends \Twig_Node ->write("\$asset->add_assets_version('{$config['assets_version']}');\n") ->outdent() ->write("}\n") - ->write("\$context['definition']->set('STYLESHEETS', '__STYLESHEETS_PLACEHOLDER__');\n") - ->write("\$context['definition']->set('SCRIPTS', '__SCRIPTS_PLACEHOLDER__');\n") ->write("\$this->getEnvironment()->get_assets_bag()->add_{$this->get_setters_name()}(\$asset);") ; } diff --git a/phpBB/styles/prosilver/style.cfg b/phpBB/styles/prosilver/style.cfg index 21951b7b0d..ec7d8d2e27 100644 --- a/phpBB/styles/prosilver/style.cfg +++ b/phpBB/styles/prosilver/style.cfg @@ -21,8 +21,8 @@ # General Information about this style name = prosilver copyright = © phpBB Limited, 2007 -style_version = 3.2.0-a2 -phpbb_version = 3.2.0-a2 +style_version = 3.2.0-b1 +phpbb_version = 3.2.0-b1 # Defining a different template bitfield # template_bitfield = lNg= diff --git a/phpBB/viewonline.php b/phpBB/viewonline.php index 765599f165..e8698d9916 100644 --- a/phpBB/viewonline.php +++ b/phpBB/viewonline.php @@ -88,6 +88,8 @@ if ($mode == 'whois' && $auth->acl_get('a_') && $session_id) page_footer(); } +$user->update_session_infos(); + // Forum info $sql_ary = array( 'SELECT' => 'f.forum_id, f.forum_name, f.parent_id, f.forum_type, f.left_id, f.right_id', |