diff --git a/build/build.xml b/build/build.xml index 995d5128d0..42f242b59d 100644 --- a/build/build.xml +++ b/build/build.xml @@ -3,8 +3,8 @@ - - + + diff --git a/phpBB/composer.json b/phpBB/composer.json index 52217a7540..1b8de72710 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -33,7 +33,7 @@ "marc1706/fast-image-size": "^1.1", "paragonie/random_compat": "^1.4", "patchwork/utf8": "^1.1", - "s9e/text-formatter": "~0.9.0", + "s9e/text-formatter": "~0.10.0", "symfony/config": "^2.8", "symfony/console": "^2.8", "symfony/debug": "^2.8", diff --git a/phpBB/composer.lock b/phpBB/composer.lock index 2cce1156f0..d460c6db58 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": "a66e58446c273c4b92f8e5f227180be8", - "content-hash": "d3646acce6058e89ebcf76debb7f72ea", + "hash": "3b947e5d38012be6ef86609c709c7b4b", + "content-hash": "447fa8ed870502dc3089b0a0ffa08ef0", "packages": [ { "name": "bantu/ini-get-wrapper", @@ -660,16 +660,16 @@ }, { "name": "s9e/text-formatter", - "version": "0.9.6", + "version": "0.10.1", "source": { "type": "git", "url": "https://github.com/s9e/TextFormatter.git", - "reference": "077c510109f3011dec68a5bcbaeb93a1f9138128" + "reference": "9380fd3d3e3289d7e966bab7769ca2aae5d23f67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/077c510109f3011dec68a5bcbaeb93a1f9138128", - "reference": "077c510109f3011dec68a5bcbaeb93a1f9138128", + "url": "https://api.github.com/repos/s9e/TextFormatter/zipball/9380fd3d3e3289d7e966bab7769ca2aae5d23f67", + "reference": "9380fd3d3e3289d7e966bab7769ca2aae5d23f67", "shasum": "" }, "require": { @@ -721,7 +721,7 @@ "parser", "shortcodes" ], - "time": "2017-05-10 19:37:30" + "time": "2017-07-03 13:55:54" }, { "name": "symfony/config", @@ -2825,9 +2825,7 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "email": "fabien@symfony.com" } ], "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", diff --git a/phpBB/docs/INSTALL.html b/phpBB/docs/INSTALL.html index 704a9f13a7..956a384263 100644 --- a/phpBB/docs/INSTALL.html +++ b/phpBB/docs/INSTALL.html @@ -456,9 +456,21 @@

6.ii. Webserver configuration

-

Depending on your web server, you may have to configure your server to deny web access to the cache/, files/, store/ and other directories. This is to prevent users from accessing sensitive files.

+

Depending on your web server, you may have to configure your server to deny web access to the cache/, files/, includes, phpbb, store/, and vendor directories. This is to prevent users from accessing sensitive files.

-

For Apache there are .htaccess files already in place to do this for you. Similarly, for Windows based servers using IIS there are web.config files already in place to do this for you. For other webservers, you will have to adjust the configuration yourself. Sample files for nginx and lighttpd to help you get started may be found in docs/ directory.

+

+ For Apache there are .htaccess files already in place to do this for the most sensitive files and folders. We do however recommend to completely deny all access to the aforementioned folders and their respective subfolders in your Apache configuration.
+ On Apache 2.4, denying access to the phpbb folder in a phpBB instance located at /var/www/html/ would be accomplished by adding the following access rules to the Apache configuration file (typically apache.conf): +

+<Directory /var/www/html/phpbb/*>
+	Require all denied
+</Directory>
+<Directory /var/www/html/phpbb>
+	Require all denied
+</Directory>
+
+

The same settings can be applied to the other mentioned directories by replacing phpbb by the respective directory name. Please note that there are differences in syntax between Apache version 2.2 and 2.4.

+

For Windows based servers using IIS there are web.config files already in place to do this for you. For other webservers, you will have to adjust the configuration yourself. Sample files for nginx and lighttpd to help you get started may be found in the docs/ directory.

diff --git a/phpBB/docs/assets/css/stylesheet.css b/phpBB/docs/assets/css/stylesheet.css index 192a6f9f79..c090ab7e07 100644 --- a/phpBB/docs/assets/css/stylesheet.css +++ b/phpBB/docs/assets/css/stylesheet.css @@ -115,6 +115,17 @@ code { padding: 0 4px; } +pre { + color: #006600; + font-weight: normal; + font-family: 'Courier New', monospace; + border-color: #D1D7DC; + border-width: 1px; + border-style: solid; + background-color: #FAFAFA; + padding: 0 4px +} + #wrap { padding: 0 20px; min-width: 650px; diff --git a/phpBB/docs/lighttpd.sample.conf b/phpBB/docs/lighttpd.sample.conf index 5b04122267..f5b509e002 100644 --- a/phpBB/docs/lighttpd.sample.conf +++ b/phpBB/docs/lighttpd.sample.conf @@ -37,7 +37,7 @@ $HTTP["host"] == "www.myforums.com" { accesslog.filename = "/var/log/lighttpd/access-www.myforums.com.log" # Deny access to internal phpbb files. - $HTTP["url"] =~ "^/(config\.php|common\.php|includes|cache|files|store|images/avatars/upload)" { + $HTTP["url"] =~ "^/(config\.php|common\.php|cache|files|images/avatars/upload|includes|phpbb|store|vendor)" { url.access-deny = ( "" ) } diff --git a/phpBB/docs/nginx.sample.conf b/phpBB/docs/nginx.sample.conf index c415720e9c..ce929b6e54 100644 --- a/phpBB/docs/nginx.sample.conf +++ b/phpBB/docs/nginx.sample.conf @@ -72,7 +72,7 @@ http { } # Deny access to internal phpbb files. - location ~ /(config\.php|common\.php|includes|cache|files|store|images/avatars/upload) { + location ~ /(config\.php|common\.php|cache|files|images/avatars/upload|includes|phpbb|store|vendor) { deny all; # deny was ignored before 0.8.40 for connections over IPv6. # Use internal directive to prohibit access on older versions. diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 3dabd1b46e..6c15c14300 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -2815,6 +2815,11 @@ function get_preg_expression($mode) case 'path_remove_dot_trailing_slash': return '#^(?:(\.)?)+(?:(.+)?)+(?:([\\/\\\])$)#'; break; + + case 'semantic_version': + // Regular expression to match semantic versions by http://rgxdb.com/ + return '/(?<=^[Vv]|^)(?:(?(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?(?:0|[1-9](?:(?:0|[1-9])+)*))[.](?(?:0|[1-9](?:(?:0|[1-9])+)*))(?:-(?(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:0|[1-9](?:(?:0|[1-9])+)*)))*))?(?:[+](?(?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+))(?:[.](?:(?:(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?|(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)(?:[A-Za-z]|-)(?:(?:(?:0|[1-9])|(?:[A-Za-z]|-))+)?)|(?:(?:0|[1-9])+)))*))?)$/'; + break; } return ''; diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php index 7040370627..f46df99edb 100644 --- a/phpBB/includes/ucp/ucp_remind.php +++ b/phpBB/includes/ucp/ucp_remind.php @@ -41,8 +41,15 @@ class ucp_remind $email = strtolower($request->variable('email', '')); $submit = (isset($_POST['submit'])) ? true : false; + add_form_key('ucp_remind'); + if ($submit) { + if (!check_form_key('ucp_remind')) + { + trigger_error('FORM_INVALID'); + } + $sql_array = array( 'SELECT' => 'user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason', 'FROM' => array(USERS_TABLE => 'u'), diff --git a/phpBB/language/en/acp/common.php b/phpBB/language/en/acp/common.php index 63235c01d8..de5039f047 100644 --- a/phpBB/language/en/acp/common.php +++ b/phpBB/language/en/acp/common.php @@ -440,16 +440,19 @@ $lang = array_merge($lang, array( 'UPLOAD_DIR_SIZE' => 'Size of posted attachments', 'USERS_PER_DAY' => 'Users per day', - 'VALUE' => 'Value', - 'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.', - 'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version', - 'VERSION_CHECK' => 'Version check', - 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', + 'VALUE' => 'Value', + 'VERSIONCHECK_FAIL' => 'Failed to obtain latest version information.', + 'VERSIONCHECK_FORCE_UPDATE' => 'Re-Check version', + 'VERSION_CHECK' => 'Version check', + 'VERSION_CHECK_EXPLAIN' => 'Checks to see if your phpBB installation is up to date.', + 'VERSIONCHECK_INVALID_ENTRY' => 'Latest version information contains an unsupported entry.', + 'VERSIONCHECK_INVALID_URL' => 'Latest version information contains invalid URL.', + 'VERSIONCHECK_INVALID_VERSION' => 'Latest version information contains an invalid version.', 'VERSION_NOT_UP_TO_DATE_ACP' => 'Your phpBB installation is not up to date.
Below is a link to the release announcement, which contains more information as well as instructions on updating.', 'VERSION_NOT_UP_TO_DATE_TITLE' => 'Your phpBB installation is not up to date.', - 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', - 'VIEW_ADMIN_LOG' => 'View administrator log', - 'VIEW_INACTIVE_USERS' => 'View inactive users', + 'VERSION_UP_TO_DATE_ACP' => 'Your phpBB installation is up to date. There are no updates available at this time.', + 'VIEW_ADMIN_LOG' => 'View administrator log', + 'VIEW_INACTIVE_USERS' => 'View inactive users', 'WELCOME_PHPBB' => 'Welcome to phpBB', 'WRITABLE_CONFIG' => 'Your config file (config.php) is currently world-writable. We strongly encourage you to change the permissions to 640 or at least to 644 (for example: chmod 640 config.php).', diff --git a/phpBB/phpbb/avatar/driver/remote.php b/phpBB/phpbb/avatar/driver/remote.php index 3a88a432d1..efc4f5ec0f 100644 --- a/phpBB/phpbb/avatar/driver/remote.php +++ b/phpBB/phpbb/avatar/driver/remote.php @@ -85,8 +85,11 @@ class remote extends \phpbb\avatar\driver\driver } // Check if this url looks alright - // This isn't perfect, but it's what phpBB 3.0 did, and might as well make sure everything is compatible - if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.('. implode('|', $this->allowed_extensions) . ')$#i', $url)) + // Do not allow specifying the port (see RFC 3986) or IP addresses + if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.('. implode('|', $this->allowed_extensions) . ')$#i', $url) || + preg_match('@^(http|https|ftp)://[^/:?#]+:[0-9]+[/:?#]@i', $url) || + preg_match('#^(http|https|ftp)://(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])#i', $url) || + preg_match('#^(http|https|ftp)://(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){0,5}(?:[\dA-F]{1,4}(?::[\dA-F]{1,4})?|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:)|(?:::))#i', $url)) { $error[] = 'AVATAR_URL_INVALID'; return false; diff --git a/phpBB/phpbb/avatar/driver/upload.php b/phpBB/phpbb/avatar/driver/upload.php index 4effa4c410..887a0ff258 100644 --- a/phpBB/phpbb/avatar/driver/upload.php +++ b/phpBB/phpbb/avatar/driver/upload.php @@ -146,6 +146,16 @@ class upload extends \phpbb\avatar\driver\driver return false; } + // Do not allow specifying the port (see RFC 3986) or IP addresses + // remote_upload() will do its own check for allowed filetypes + if (preg_match('@^(http|https|ftp)://[^/:?#]+:[0-9]+[/:?#]@i', $url) || + preg_match('#^(http|https|ftp)://(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])#i', $url) || + preg_match('#^(http|https|ftp)://(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){0,5}(?:[\dA-F]{1,4}(?::[\dA-F]{1,4})?|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:)|(?:::))#i', $url)) + { + $error[] = 'AVATAR_URL_INVALID'; + return false; + } + $file = $upload->handle_upload('files.types.remote', $url); } else diff --git a/phpBB/phpbb/db/migration/data/v30x/.htaccess b/phpBB/phpbb/db/migration/data/v30x/.htaccess new file mode 100644 index 0000000000..44242b5418 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v30x/.htaccess @@ -0,0 +1,33 @@ +# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from +# module mod_authz_host to a new module called mod_access_compat (which may be +# disabled) and a new "Require" syntax has been introduced to mod_authz_host. +# We could just conditionally provide both versions, but unfortunately Apache +# does not explicitly tell us its version if the module mod_version is not +# available. In this case, we check for the availability of module +# mod_authz_core (which should be on 2.4 or higher only) as a best guess. + + + + Order Allow,Deny + Deny from All + + + = 2.4> + + Require all denied + + + + + + + Order Allow,Deny + Deny from All + + + + + Require all denied + + + diff --git a/phpBB/phpbb/db/migration/data/v310/.htaccess b/phpBB/phpbb/db/migration/data/v310/.htaccess new file mode 100644 index 0000000000..44242b5418 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v310/.htaccess @@ -0,0 +1,33 @@ +# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from +# module mod_authz_host to a new module called mod_access_compat (which may be +# disabled) and a new "Require" syntax has been introduced to mod_authz_host. +# We could just conditionally provide both versions, but unfortunately Apache +# does not explicitly tell us its version if the module mod_version is not +# available. In this case, we check for the availability of module +# mod_authz_core (which should be on 2.4 or higher only) as a best guess. + + + + Order Allow,Deny + Deny from All + + + = 2.4> + + Require all denied + + + + + + + Order Allow,Deny + Deny from All + + + + + Require all denied + + + diff --git a/phpBB/phpbb/db/migration/data/v31x/.htaccess b/phpBB/phpbb/db/migration/data/v31x/.htaccess new file mode 100644 index 0000000000..44242b5418 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/.htaccess @@ -0,0 +1,33 @@ +# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from +# module mod_authz_host to a new module called mod_access_compat (which may be +# disabled) and a new "Require" syntax has been introduced to mod_authz_host. +# We could just conditionally provide both versions, but unfortunately Apache +# does not explicitly tell us its version if the module mod_version is not +# available. In this case, we check for the availability of module +# mod_authz_core (which should be on 2.4 or higher only) as a best guess. + + + + Order Allow,Deny + Deny from All + + + = 2.4> + + Require all denied + + + + + + + Order Allow,Deny + Deny from All + + + + + Require all denied + + + diff --git a/phpBB/phpbb/db/migration/data/v31x/v3111.php b/phpBB/phpbb/db/migration/data/v31x/v3111.php new file mode 100644 index 0000000000..f01bbc2bff --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v31x/v3111.php @@ -0,0 +1,36 @@ + +* @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 v3111 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.1.11', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v31x\v3111rc1', + ); + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.1.11')), + ); + } +} diff --git a/phpBB/phpbb/db/migration/data/v320/.htaccess b/phpBB/phpbb/db/migration/data/v320/.htaccess new file mode 100644 index 0000000000..44242b5418 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v320/.htaccess @@ -0,0 +1,33 @@ +# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from +# module mod_authz_host to a new module called mod_access_compat (which may be +# disabled) and a new "Require" syntax has been introduced to mod_authz_host. +# We could just conditionally provide both versions, but unfortunately Apache +# does not explicitly tell us its version if the module mod_version is not +# available. In this case, we check for the availability of module +# mod_authz_core (which should be on 2.4 or higher only) as a best guess. + + + + Order Allow,Deny + Deny from All + + + = 2.4> + + Require all denied + + + + + + + Order Allow,Deny + Deny from All + + + + + Require all denied + + + diff --git a/phpBB/phpbb/db/migration/data/v32x/.htaccess b/phpBB/phpbb/db/migration/data/v32x/.htaccess new file mode 100644 index 0000000000..44242b5418 --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/.htaccess @@ -0,0 +1,33 @@ +# With Apache 2.4 the "Order, Deny" syntax has been deprecated and moved from +# module mod_authz_host to a new module called mod_access_compat (which may be +# disabled) and a new "Require" syntax has been introduced to mod_authz_host. +# We could just conditionally provide both versions, but unfortunately Apache +# does not explicitly tell us its version if the module mod_version is not +# available. In this case, we check for the availability of module +# mod_authz_core (which should be on 2.4 or higher only) as a best guess. + + + + Order Allow,Deny + Deny from All + + + = 2.4> + + Require all denied + + + + + + + Order Allow,Deny + Deny from All + + + + + Require all denied + + + diff --git a/phpBB/phpbb/db/migration/data/v32x/v321.php b/phpBB/phpbb/db/migration/data/v32x/v321.php new file mode 100644 index 0000000000..268f978b4b --- /dev/null +++ b/phpBB/phpbb/db/migration/data/v32x/v321.php @@ -0,0 +1,37 @@ + +* @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\v32x; + +class v321 extends \phpbb\db\migration\migration +{ + public function effectively_installed() + { + return phpbb_version_compare($this->config['version'], '3.2.1', '>='); + } + + static public function depends_on() + { + return array( + '\phpbb\db\migration\data\v32x\v321rc1', + ); + + } + + public function update_data() + { + return array( + array('config.update', array('version', '3.2.1')), + ); + } +} diff --git a/phpBB/phpbb/db/tools/tools.php b/phpBB/phpbb/db/tools/tools.php index 76036554d2..2f891e43d5 100644 --- a/phpBB/phpbb/db/tools/tools.php +++ b/phpBB/phpbb/db/tools/tools.php @@ -941,29 +941,19 @@ class tools implements tools_interface continue; } - // These DBMS prefix index name with the table name switch ($this->sql_layer) { + // These DBMS prefix index name with the table name case 'oracle': case 'sqlite3': - $index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); - $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) - - if (strpos($index_name , $table_name) === false) - { - if (strpos($index_name, $table_prefix) !== false) - { - $row[$col] = substr($row[$col], strlen($table_prefix) + 1); - } - else - { - $row[$col] = substr($row[$col], strlen($table_name) + 1); - } - } + $new_index_name = $this->check_index_name_length($table_name, $table_name . '_' . $index_name, false); + break; + default: + $new_index_name = $this->check_index_name_length($table_name, $index_name, false); break; } - if (strtolower($row[$col]) == strtolower($index_name)) + if (strtolower($row[$col]) == strtolower($new_index_name)) { $this->db->sql_freeresult($result); return true; @@ -1577,15 +1567,17 @@ class tools implements tools_interface $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) if (strpos($index_name, $table_prefix) === 0) { - $index_name = substr($index_name, strlen($table_prefix) + 1); - return $this->check_index_name_length($table_name, $index_name); + $index_name = substr($index_name, strlen($table_prefix)); + return $this->check_index_name_length($table_name, $index_name, $throw_error); } - // Try removing the table name then - if (strpos($index_name, $table_name) === 0) + // Try removing the remaining suffix part of table name then + $table_suffix = substr($table_name, strlen($table_prefix)); + if (strpos($index_name, $table_suffix) === 0) { - $index_name = substr($index_name, strlen($table_name) + 1); - return $this->check_index_name_length($table_name, $index_name); + // Remove the suffix and underscore separator between table_name and index_name + $index_name = substr($index_name, strlen($table_suffix) + 1); + return $this->check_index_name_length($table_name, $index_name, $throw_error); } if ($throw_error) diff --git a/phpBB/phpbb/search/fulltext_mysql.php b/phpBB/phpbb/search/fulltext_mysql.php index d5165df016..da1aad1c3a 100644 --- a/phpBB/phpbb/search/fulltext_mysql.php +++ b/phpBB/phpbb/search/fulltext_mysql.php @@ -272,6 +272,27 @@ class fulltext_mysql extends \phpbb\search\base foreach ($this->split_words as $i => $word) { + // Check for not allowed search queries for InnoDB. + // We assume similar restrictions for MyISAM, which is usually even + // slower but not as restrictive as InnoDB. + // InnoDB full-text search does not support the use of a leading + // plus sign with wildcard ('+*'), a plus and minus sign + // combination ('+-'), or leading a plus and minus sign combination. + // InnoDB full-text search only supports leading plus or minus signs. + // For example, InnoDB supports '+apple' but does not support 'apple+'. + // Specifying a trailing plus or minus sign causes InnoDB to report + // a syntax error. InnoDB full-text search does not support the use + // of multiple operators on a single search word, as in this example: + // '++apple'. Use of multiple operators on a single search word + // returns a syntax error to standard out. + // Also, ensure that the wildcard character is only used at the + // end of the line as it's intended by MySQL. + if (preg_match('#^(\+[+-]|\+\*|.+[+-]$|.+\*(?!$))#', $word)) + { + unset($this->split_words[$i]); + continue; + } + $clean_word = preg_replace('#^[+\-|"]#', '', $word); // check word length diff --git a/phpBB/phpbb/textformatter/s9e/renderer.php b/phpBB/phpbb/textformatter/s9e/renderer.php index 9be20b7f53..6fcd2b0a98 100644 --- a/phpBB/phpbb/textformatter/s9e/renderer.php +++ b/phpBB/phpbb/textformatter/s9e/renderer.php @@ -247,14 +247,12 @@ class renderer implements \phpbb\textformatter\renderer_interface $vars = array('renderer', 'xml'); extract($this->dispatcher->trigger_event('core.text_formatter_s9e_render_before', compact($vars))); + $html = $this->renderer->render($xml); if (isset($this->censor) && $this->viewcensors) { - // NOTE: censorHtml() is XML-safe - $xml = $this->censor->censorHtml($xml, true); + $html = $this->censor->censorHtml($html, true); } - $html = $this->renderer->render($xml); - /** * Modify a rendered text * diff --git a/phpBB/phpbb/version_helper.php b/phpBB/phpbb/version_helper.php index bb15dd1a74..a73fbfbfbe 100644 --- a/phpBB/phpbb/version_helper.php +++ b/phpBB/phpbb/version_helper.php @@ -60,6 +60,23 @@ class version_helper /** @var \phpbb\file_downloader */ protected $file_downloader; + protected $version_schema = array( + 'stable' => array( + 'current' => 'version', + 'download' => 'url', + 'announcement' => 'url', + 'eol' => 'url', + 'security' => 'bool', + ), + 'unstable' => array( + 'current' => 'version', + 'download' => 'url', + 'announcement' => 'url', + 'eol' => 'url', + 'security' => 'bool', + ), + ); + /** * Constructor * @@ -392,9 +409,101 @@ class version_helper $info['stable'] = (empty($info['stable'])) ? array() : $info['stable']; $info['unstable'] = (empty($info['unstable'])) ? $info['stable'] : $info['unstable']; + $info = $this->validate_versions($info); + $this->cache->put($cache_file, $info, 86400); // 24 hours } return $info; } + + /** + * Validate versions info input + * + * @param array $versions_info Decoded json data array. Will be modified + * and cleaned by this method + * + * @return array Versions info array + * @throws version_check_exception + */ + public function validate_versions($versions_info) + { + $array_diff = array_diff_key($versions_info, array($this->version_schema)); + + // Remove excessive data + if (count($array_diff) > 0) + { + $old_versions_info = $versions_info; + $versions_info = array( + 'stable' => !empty($old_versions_info['stable']) ? $old_versions_info['stable'] : array(), + 'unstable' => !empty($old_versions_info['unstable']) ? $old_versions_info['unstable'] : array(), + ); + unset($old_versions_info); + } + + foreach ($versions_info as $stability_type => &$versions_data) + { + foreach ($versions_data as $branch => &$version_data) + { + if (!preg_match('/^[0-9a-z\-\.]+$/i', $branch)) + { + unset($versions_data[$branch]); + continue; + } + + $stability_diff = array_diff_key($version_data, $this->version_schema[$stability_type]); + + if (count($stability_diff) > 0) + { + $old_version_data = $version_data; + $version_data = array(); + foreach ($this->version_schema[$stability_type] as $key => $value) + { + if (isset($old_version_data[$key])) + { + $version_data[$key] = $old_version_data[$key]; + } + } + unset($old_version_data); + } + + foreach ($version_data as $key => &$value) + { + if (!isset($this->version_schema[$stability_type][$key])) + { + unset($version_data[$key]); + throw new version_check_exception('VERSIONCHECK_INVALID_ENTRY'); + } + + switch ($this->version_schema[$stability_type][$key]) + { + case 'bool': + $value = (bool) $value; + break; + + case 'url': + if (!empty($value) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $value) && + !preg_match('#^' . get_preg_expression('www_url') . '$#iu', $value)) + { + throw new version_check_exception('VERSIONCHECK_INVALID_URL'); + } + break; + + case 'version': + if (!empty($value) && !preg_match(get_preg_expression('semantic_version'), $value)) + { + throw new version_check_exception('VERSIONCHECK_INVALID_VERSION'); + } + break; + + default: + // Shouldn't be possible to trigger this + throw new version_check_exception('VERSIONCHECK_INVALID_ENTRY'); + } + } + } + } + + return $versions_info; + } } diff --git a/phpBB/web.config b/phpBB/web.config index 99a1fe6023..d0a3cb33fe 100644 --- a/phpBB/web.config +++ b/phpBB/web.config @@ -18,7 +18,10 @@ + + + diff --git a/tests/avatar/manager_test.php b/tests/avatar/manager_test.php index 924f1319a2..9e826a3a59 100644 --- a/tests/avatar/manager_test.php +++ b/tests/avatar/manager_test.php @@ -384,4 +384,58 @@ class phpbb_avatar_manager_test extends \phpbb_database_test_case 'avatar_height' => 0, ), $row); } + + public function data_remote_avatar_url() + { + return array( + array('127.0.0.1:91?foo.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array(gethostbyname('secure.gravatar.com') . '/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80), + array(gethostbyname('secure.gravatar.com') . ':120/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com:80/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com:80?55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com?55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), // should be a 404 + array('2001:db8:0:0:0:0:2:1/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com/2001:db8:0:0:0:0:2:1/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + array('secure.gravatar.com/127.0.0.1:80/avatar/55502f40dc8b7c769880b10874abc9d0.jpg', 80, 80, array('AVATAR_URL_INVALID')), + ); + } + + /** + * @dataProvider data_remote_avatar_url + */ + public function test_remote_avatar_url($url, $width, $height, $expected_error = array()) + { + global $phpbb_root_path, $phpEx; + + if (!function_exists('get_preg_expression')) + { + require($phpbb_root_path . 'includes/functions.' . $phpEx); + } + + $this->config['server_name'] = 'foobar.com'; + + /** @var \phpbb\avatar\driver\remote $remote_avatar */ + $remote_avatar = $this->manager->get_driver('avatar.driver.remote', false); + + $request = new phpbb_mock_request(array(), array( + 'avatar_remote_url' => $url, + 'avatar_remote_width' => $width, + 'avatar_remote_height' => $height, + )); + + $row = array(); + $error = array(); + + $return = $remote_avatar->process_form($request, null, $this->user, $row, $error); + if (count($expected_error) > 0) + { + $this->assertFalse($return); + } + else + { + $this->assertNotEquals(false, $return); + } + $this->assertSame($expected_error, $error); + } } diff --git a/tests/dbal/db_tools_test.php b/tests/dbal/db_tools_test.php index b884b4ab95..f9243e7266 100644 --- a/tests/dbal/db_tools_test.php +++ b/tests/dbal/db_tools_test.php @@ -421,4 +421,41 @@ class phpbb_dbal_db_tools_test extends phpbb_database_test_case $this->assertTrue($this->tools->sql_column_add('prefix_table_name', 'c_bug_13282', array('TINT:2'))); $this->assertTrue($this->tools->sql_column_exists('prefix_table_name', 'c_bug_13282')); } + + public function test_create_index_with_long_name() + { + // This constant is being used for checking table prefix. + $table_prefix = substr(CONFIG_TABLE, 0, -6); // strlen(config) + + if (strlen($table_prefix) > 20) + { + $this->markTestIncomplete('The table prefix length is too long for proper testing of index shortening function.'); + } + + $table_suffix = str_repeat('a', 25 - strlen($table_prefix)); + $table_name = $table_prefix . $table_suffix; + + $this->tools->sql_create_table($table_name, $this->table_data); + + // Index name and table suffix and table prefix have > 30 chars in total. + // Index name and table suffix have <= 30 chars in total. + $long_index_name = str_repeat('i', 30 - strlen($table_suffix)); + $this->assertFalse($this->tools->sql_index_exists($table_name, $long_index_name)); + $this->assertTrue($this->tools->sql_create_index($table_name, $long_index_name, array('c_timestamp'))); + $this->assertTrue($this->tools->sql_index_exists($table_name, $long_index_name)); + + // Index name and table suffix have > 30 chars in total. + $very_long_index_name = str_repeat('i', 30); + $this->assertFalse($this->tools->sql_index_exists($table_name, $very_long_index_name)); + $this->assertTrue($this->tools->sql_create_index($table_name, $very_long_index_name, array('c_timestamp'))); + $this->assertTrue($this->tools->sql_index_exists($table_name, $very_long_index_name)); + + $this->tools->sql_table_drop($table_name); + + // Index name has > 30 chars - that should not be possible. + $too_long_index_name = str_repeat('i', 31); + $this->assertFalse($this->tools->sql_index_exists('prefix_table_name', $too_long_index_name)); + $this->setExpectedTriggerError(E_USER_ERROR); + $this->tools->sql_create_index('prefix_table_name', $too_long_index_name, array('c_timestamp')); + } } diff --git a/tests/text_processing/tickets_data/PHPBB3-15261.html b/tests/text_processing/tickets_data/PHPBB3-15261.html new file mode 100644 index 0000000000..b563052b47 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15261.html @@ -0,0 +1 @@ +foo **** baz \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-15261.txt b/tests/text_processing/tickets_data/PHPBB3-15261.txt new file mode 100644 index 0000000000..a8c4a05c10 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15261.txt @@ -0,0 +1 @@ +foo baz \ No newline at end of file diff --git a/tests/text_processing/tickets_data/PHPBB3-15261.xml b/tests/text_processing/tickets_data/PHPBB3-15261.xml new file mode 100644 index 0000000000..c0d0f395a1 --- /dev/null +++ b/tests/text_processing/tickets_data/PHPBB3-15261.xml @@ -0,0 +1,14 @@ + + + + word_id + word + replacement + + + 1 + <*> + **** + +
+
diff --git a/tests/version/version_helper_remote_test.php b/tests/version/version_helper_remote_test.php index fa383d487f..35c3d92a3a 100644 --- a/tests/version/version_helper_remote_test.php +++ b/tests/version/version_helper_remote_test.php @@ -51,8 +51,8 @@ class version_helper_remote_test extends \phpbb_test_case public function provider_get_versions() { return array( - array('', false), - array('foobar', false), + array('', false, '', 'VERSIONCHECK_FAIL'), + array('foobar', false, '', 'VERSIONCHECK_FAIL'), array('{ "stable": { "1.0": { @@ -93,7 +93,7 @@ class version_helper_remote_test extends \phpbb_test_case "security": false } } -}', false), +}', false, '', 'VERSIONCHECK_FAIL'), array('{ "stable": { "1.0": { @@ -104,26 +104,7 @@ class version_helper_remote_test extends \phpbb_test_case "security": "" } } -}', true, array ( - 'stable' => array ( - '1.0' => array ( - 'current' => '1.0.1<script>alert(\'foo\');</script>', - 'download' => 'https://www.phpbb.com/customise/db/download/104136<script>alert(\'foo\');</script>', - 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/<script>alert(\'foo\');</script>', - 'eol' => '<script>alert(\'foo\');</script>', - 'security' => '<script>alert(\'foo\');</script>', - ), - ), - 'unstable' => array ( - '1.0' => array ( - 'current' => '1.0.1<script>alert(\'foo\');</script>', - 'download' => 'https://www.phpbb.com/customise/db/download/104136<script>alert(\'foo\');</script>', - 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/<script>alert(\'foo\');</script>', - 'eol' => '<script>alert(\'foo\');</script>', - 'security' => '<script>alert(\'foo\');</script>', - ), - ), - )), +}', false, null, 'VERSIONCHECK_INVALID_VERSION'), array('{ "unstable": { "1.0": { @@ -134,25 +115,87 @@ class version_helper_remote_test extends \phpbb_test_case "security": "" } } +}', false, null, 'VERSIONCHECK_INVALID_VERSION'), + array('{ + "unstable": { + "1.0": { + "current": "1.0.1", + "download": "https://www.phpbb.com/customise/db/download/104136", + "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/", + "eol": "", + "security": "" + } + } +}', false, array('stable' => array(), 'unstable' => array()), 'VERSIONCHECK_INVALID_VERSION'), + array('{ + "\"\n\n": "test", + "stable": { + "1.0": { + "current": "1.0.1", + "download": "https://www.phpbb.com/customise/db/download/104136", + "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/", + "eol": null, + "security": false + } + } }', true, array ( - 'unstable' => array ( + 'stable' => array ( '1.0' => array ( - 'current' => '1.0.1<script>alert(\'foo\');</script>', - 'download' => 'https://www.phpbb.com/customise/db/download/104136<script>alert(\'foo\');</script>', - 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/<script>alert(\'foo\');</script>', - 'eol' => '<script>alert(\'foo\');</script>', - 'security' => '<script>alert(\'foo\');</script>', + 'current' => '1.0.1', + 'download' => 'https://www.phpbb.com/customise/db/download/104136', + 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/', + 'eol' => NULL, + 'security' => false, + ), + ), + 'unstable' => array ( + '1.0' => array ( + 'current' => '1.0.1', + 'download' => 'https://www.phpbb.com/customise/db/download/104136', + 'announcement' => 'https://www.phpbb.com/customise/db/extension/boardrules/', + 'eol' => NULL, + 'security' => false, ), ), - 'stable' => array(), )), + array('{ + "unstable": { + "1.0": { + "current": "1.0.1", + "download": "https://www.phpbb.com/customise/db/download/104136", + "announcement": "https://www.phpbb.com/customise/db/extension/boardrules/", + "eol": null, + "security": false, + "foobar": "": "1.0.1", + "download2": "https://www.phpbb.com/customise/db/download/104136", + "bannouncement": "https://www.phpbb.com/customise/db/extension/boardrules/", + "eol": null, + "security": false, + "foobar": "