diff options
Diffstat (limited to 'phpBB/phpbb')
36 files changed, 654 insertions, 65 deletions
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/cache/driver/apcu.php b/phpBB/phpbb/cache/driver/apcu.php new file mode 100644 index 0000000000..40192e4026 --- /dev/null +++ b/phpBB/phpbb/cache/driver/apcu.php @@ -0,0 +1,70 @@ +<?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\cache\driver; + +/** +* ACM for APCU +*/ +class apcu extends \phpbb\cache\driver\memory +{ + var $extension = 'apcu'; + + /** + * {@inheritDoc} + */ + function purge() + { + apcu_clear_cache(); + + parent::purge(); + } + + /** + * Fetch an item from the cache + * + * @access protected + * @param string $var Cache key + * @return mixed Cached data + */ + function _read($var) + { + return apcu_fetch($this->key_prefix . $var); + } + + /** + * Store data in the cache + * + * @access protected + * @param string $var Cache key + * @param mixed $data Data to store + * @param int $ttl Time-to-live of cached data + * @return bool True if the operation succeeded + */ + function _write($var, $data, $ttl = 2592000) + { + return apcu_store($this->key_prefix . $var, $data, $ttl); + } + + /** + * Remove an item from the cache + * + * @access protected + * @param string $var Cache key + * @return bool True if the operation succeeded + */ + function _delete($var) + { + return apcu_delete($this->key_prefix . $var); + } +} diff --git a/phpBB/phpbb/cache/driver/memcached.php b/phpBB/phpbb/cache/driver/memcached.php index a7da22d7e8..808e15afe8 100644 --- a/phpBB/phpbb/cache/driver/memcached.php +++ b/phpBB/phpbb/cache/driver/memcached.php @@ -68,7 +68,7 @@ class memcached extends \phpbb\cache\driver\memory foreach (explode(',', PHPBB_ACM_MEMCACHE) as $u) { preg_match('#(.*)/(\d+)#', $u, $parts); - $this->memcache->addServer(trim($parts[1]), (int) trim($parts[2])); + $this->memcached->addServer(trim($parts[1]), (int) trim($parts[2])); } } diff --git a/phpBB/phpbb/cache/driver/redis.php b/phpBB/phpbb/cache/driver/redis.php index eda774491c..eaeb529918 100644 --- a/phpBB/phpbb/cache/driver/redis.php +++ b/phpBB/phpbb/cache/driver/redis.php @@ -137,6 +137,10 @@ class redis extends \phpbb\cache\driver\memory */ function _write($var, $data, $ttl = 2592000) { + if ($ttl == 0) + { + return $this->redis->set($var, $data); + } return $this->redis->setex($var, $ttl, $data); } diff --git a/phpBB/phpbb/console/command/extension/enable.php b/phpBB/phpbb/console/command/extension/enable.php index a8312d5c15..f92de0069c 100644 --- a/phpBB/phpbb/console/command/extension/enable.php +++ b/phpBB/phpbb/console/command/extension/enable.php @@ -37,11 +37,18 @@ class enable extends command $io = new SymfonyStyle($input, $output); $name = $input->getArgument('extension-name'); + $extension = $this->manager->get_extension($name); + + if (!$extension->is_enableable()) + { + $io->error($this->user->lang('CLI_EXTENSION_NOT_ENABLEABLE', $name)); + return 1; + } if ($this->manager->is_enabled($name)) { $io->error($this->user->lang('CLI_EXTENSION_ENABLED', $name)); - return 2; + return 1; } $this->manager->enable($name); diff --git a/phpBB/phpbb/console/command/fixup/update_hashes.php b/phpBB/phpbb/console/command/fixup/update_hashes.php index 4bcc3b5d19..9a0e9bc798 100644 --- a/phpBB/phpbb/console/command/fixup/update_hashes.php +++ b/phpBB/phpbb/console/command/fixup/update_hashes.php @@ -101,9 +101,9 @@ class update_hashes extends \phpbb\console\command\command { $new_hash = $this->passwords_manager->hash($row['user_password'], array($this->default_type)); - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_password = "' . $this->db->sql_escape($new_hash) . '" - WHERE user_id = ' . (int) $row['user_id']; + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_password = '" . $this->db->sql_escape($new_hash) . "' + WHERE user_id = " . (int) $row['user_id']; $this->db->sql_query($sql); $progress_bar->advance(); } diff --git a/phpBB/phpbb/cron/task/core/update_hashes.php b/phpBB/phpbb/cron/task/core/update_hashes.php index a4fe477d99..ba095abc8b 100644 --- a/phpBB/phpbb/cron/task/core/update_hashes.php +++ b/phpBB/phpbb/cron/task/core/update_hashes.php @@ -111,9 +111,9 @@ class update_hashes extends \phpbb\cron\task\base // Increase number so we know that users were selected from the database $affected_rows++; - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_password = "' . $this->db->sql_escape($new_hash) . '" - WHERE user_id = ' . (int) $row['user_id']; + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_password = '" . $this->db->sql_escape($new_hash) . "' + WHERE user_id = " . (int) $row['user_id']; $this->db->sql_query($sql); } diff --git a/phpBB/phpbb/db/extractor/postgres_extractor.php b/phpBB/phpbb/db/extractor/postgres_extractor.php index a98e39621c..0219d2ac8d 100644 --- a/phpBB/phpbb/db/extractor/postgres_extractor.php +++ b/phpBB/phpbb/db/extractor/postgres_extractor.php @@ -85,7 +85,7 @@ class postgres_extractor extends base_extractor // We don't even care about storing the results. We already know the answer if we get rows back. if ($this->db->sql_fetchrow($result)) { - $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; + $sql_data .= "DROP SEQUENCE IF EXISTS {$table_name}_seq;\n"; $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; } $this->db->sql_freeresult($result); 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. +<IfModule mod_version.c> + <IfVersion < 2.4> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfVersion> + <IfVersion >= 2.4> + <Files "*"> + Require all denied + </Files> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + <IfModule !mod_authz_core.c> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfModule> + <IfModule mod_authz_core.c> + <Files "*"> + Require all denied + </Files> + </IfModule> +</IfModule> 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. +<IfModule mod_version.c> + <IfVersion < 2.4> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfVersion> + <IfVersion >= 2.4> + <Files "*"> + Require all denied + </Files> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + <IfModule !mod_authz_core.c> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfModule> + <IfModule mod_authz_core.c> + <Files "*"> + Require all denied + </Files> + </IfModule> +</IfModule> 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. +<IfModule mod_version.c> + <IfVersion < 2.4> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfVersion> + <IfVersion >= 2.4> + <Files "*"> + Require all denied + </Files> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + <IfModule !mod_authz_core.c> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfModule> + <IfModule mod_authz_core.c> + <Files "*"> + Require all denied + </Files> + </IfModule> +</IfModule> 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 @@ +<?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 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. +<IfModule mod_version.c> + <IfVersion < 2.4> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfVersion> + <IfVersion >= 2.4> + <Files "*"> + Require all denied + </Files> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + <IfModule !mod_authz_core.c> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfModule> + <IfModule mod_authz_core.c> + <Files "*"> + Require all denied + </Files> + </IfModule> +</IfModule> 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. +<IfModule mod_version.c> + <IfVersion < 2.4> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfVersion> + <IfVersion >= 2.4> + <Files "*"> + Require all denied + </Files> + </IfVersion> +</IfModule> +<IfModule !mod_version.c> + <IfModule !mod_authz_core.c> + <Files "*"> + Order Allow,Deny + Deny from All + </Files> + </IfModule> + <IfModule mod_authz_core.c> + <Files "*"> + Require all denied + </Files> + </IfModule> +</IfModule> 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 @@ +<?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\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/postgres.php b/phpBB/phpbb/db/tools/postgres.php index e2a4e668a6..077d6e06f9 100644 --- a/phpBB/phpbb/db/tools/postgres.php +++ b/phpBB/phpbb/db/tools/postgres.php @@ -448,7 +448,7 @@ class postgres extends tools // We don't even care about storing the results. We already know the answer if we get rows back. if ($this->db->sql_fetchrow($result)) { - $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; + $statements[] = "DROP SEQUENCE IF EXISTS {$table_name}_seq;\n"; } $this->db->sql_freeresult($result); 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/event/kernel_exception_subscriber.php b/phpBB/phpbb/event/kernel_exception_subscriber.php index b7a54f2608..373e59b0c8 100644 --- a/phpBB/phpbb/event/kernel_exception_subscriber.php +++ b/phpBB/phpbb/event/kernel_exception_subscriber.php @@ -16,6 +16,7 @@ namespace phpbb\event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Response; @@ -23,6 +24,13 @@ use Symfony\Component\HttpFoundation\Response; class kernel_exception_subscriber implements EventSubscriberInterface { /** + * Set to true to show full exception messages + * + * @var bool + */ + protected $debug; + + /** * Template object * * @var \phpbb\template\template @@ -44,9 +52,11 @@ class kernel_exception_subscriber implements EventSubscriberInterface * * @param \phpbb\template\template $template Template object * @param \phpbb\language\language $language Language object + * @param bool $debug Set to true to show full exception messages */ - public function __construct(\phpbb\template\template $template, \phpbb\language\language $language) + public function __construct(\phpbb\template\template $template, \phpbb\language\language $language, $debug = false) { + $this->debug = $debug || defined('DEBUG'); $this->template = $template; $this->language = $language; $this->type_caster = new \phpbb\request\type_cast_helper(); @@ -69,6 +79,10 @@ class kernel_exception_subscriber implements EventSubscriberInterface { $message = $this->language->lang_array($message, $exception->get_parameters()); } + else if (!$this->debug && $exception instanceof NotFoundHttpException) + { + $message = $this->language->lang('PAGE_NOT_FOUND'); + } // Show <strong> text in bold $message = preg_replace('#<(/?strong)>#i', '<$1>', $message); @@ -99,7 +113,7 @@ class kernel_exception_subscriber implements EventSubscriberInterface $data['message'] = $message; } - if (defined('DEBUG')) + if ($this->debug) { $data['trace'] = $exception->getTrace(); } diff --git a/phpBB/phpbb/event/php_exporter.php b/phpBB/phpbb/event/php_exporter.php index ae3553c558..26d7e2b426 100644 --- a/phpBB/phpbb/event/php_exporter.php +++ b/phpBB/phpbb/event/php_exporter.php @@ -392,7 +392,7 @@ class php_exporter public function get_vars_from_single_line_array($line, $throw_multiline = true) { $match = array(); - preg_match('#^\$vars = array\(\'([a-zA-Z0-9_\' ,]+)\'\);$#', $line, $match); + preg_match('#^\$vars = (?:\[|array\()\'([a-zA-Z0-9_\' ,]+)\'[\)\]];$#', $line, $match); if (isset($match[1])) { diff --git a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php index a40d457466..bce0149890 100644 --- a/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php +++ b/phpBB/phpbb/install/helper/iohandler/ajax_iohandler.php @@ -186,6 +186,7 @@ class ajax_iohandler extends iohandler_base $tpl_ary['TITLE'] = $this->language->lang($input_options['label']); $tpl_ary['KEY'] = $input_name; $tpl_ary['S_EXPLAIN'] = false; + $tpl_ary['DISABLED'] = isset($input_options['disabled']) ? $input_options['disabled'] : false; if (isset($input_options['default'])) { @@ -219,6 +220,11 @@ class ajax_iohandler extends iohandler_base $this->template->assign_var('S_NOT_ONLY_BUTTON_FORM', $not_button_form); + if (!$not_button_form) + { + $this->template->destroy_block_vars('options'); + } + $this->template->set_filenames(array( 'form_install' => 'installer_form.html', )); diff --git a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php index 553a30ea28..eee13a6581 100644 --- a/phpBB/phpbb/install/module/install_finish/task/install_extensions.php +++ b/phpBB/phpbb/install/module/install_finish/task/install_extensions.php @@ -118,6 +118,14 @@ class install_extensions extends \phpbb\install\task_base try { + $extension = $this->extension_manager->get_extension($ext_name); + + if (!$extension->is_enableable()) + { + $this->iohandler->add_log_message(array('CLI_EXTENSION_NOT_ENABLEABLE', $ext_name)); + continue; + } + $this->extension_manager->enable($ext_name); $extensions = $this->get_extensions(); diff --git a/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php index f911b7ac62..21aa93b7ea 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/download_updated_files.php @@ -78,16 +78,23 @@ class download_updated_files extends task_base } else if ($this->iohandler->get_input('update_recheck_files_submit', false)) { + $this->installer_config->set('file_updater_elem_progress', ''); + $this->installer_config->set('update_files', array()); throw new jump_to_restart_point_exception('check_update_files'); } else { - // Render download box - $this->iohandler->add_download_link( - 'phpbb_installer_update_file_download', - 'DOWNLOAD_UPDATE_METHOD', - 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' - ); + $file_update_info = $this->installer_config->get('update_files', array()); + + if (count($file_update_info) > 0) + { + // Render download box + $this->iohandler->add_download_link( + 'phpbb_installer_update_file_download', + 'DOWNLOAD_UPDATE_METHOD', + 'DOWNLOAD_UPDATE_METHOD_EXPLAIN' + ); + } // Add form to continue update $this->iohandler->add_user_form_group('UPDATE_CONTINUE_UPDATE_PROCESS', array( @@ -96,8 +103,9 @@ class download_updated_files extends task_base 'type' => 'submit', ), 'database_update_submit' => array( - 'label' => 'UPDATE_CONTINUE_UPDATE_PROCESS', - 'type' => 'submit', + 'label' => 'UPDATE_CONTINUE_UPDATE_PROCESS', + 'type' => 'submit', + 'disabled' => count($file_update_info) > 0, ), )); diff --git a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php index 47a71eb844..9daa8530c6 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/file_check.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/file_check.php @@ -103,6 +103,29 @@ class file_check extends task_base $file_update_info = array(); $file_update_info['update_without_diff'] = array_diff($update_info['binary'], $update_info['deleted']); + foreach ($file_update_info['update_without_diff'] as $key => $binary_file) + { + $new_file = $new_path . $binary_file; + $file = $this->phpbb_root_path . $binary_file; + + if (!$this->filesystem->exists($file)) + { + continue; + } + + if (md5_file($file) === md5_file($new_file)) + { + // File already up to date + unset($file_update_info['update_without_diff'][$key]); + } + } + + // Remove update without diff info if empty + if (count($file_update_info['update_without_diff']) < 1) + { + unset($file_update_info['update_without_diff']); + } + // Filter out files that are already deleted $file_update_info['delete'] = array_filter( $update_info['deleted'], @@ -111,6 +134,12 @@ class file_check extends task_base return file_exists($root_path . $filename); } ); + + // Remove files to delete list if empty + if (count($file_update_info['delete']) < 1) + { + unset($file_update_info['delete']); + } } $progress_count = $this->installer_config->get('file_check_progress_count', 0); diff --git a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php index cf1e4cf4ac..0e82f91553 100644 --- a/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php +++ b/phpBB/phpbb/install/module/update_filesystem/task/show_file_status.php @@ -129,9 +129,9 @@ class show_file_status extends task_base // Add form to continue update $this->iohandler->add_user_form_group('UPDATE_CONTINUE_FILE_UPDATE', array( - 'submit_continue_file_update' => array( - 'label' => 'UPDATE_CONTINUE_FILE_UPDATE', - 'type' => 'submit', + 'submit_continue_file_update' => array( + 'label' => 'UPDATE_CONTINUE_FILE_UPDATE', + 'type' => 'submit', ), )); diff --git a/phpBB/phpbb/log/log.php b/phpBB/phpbb/log/log.php index cf3db365a4..5aad7ee326 100644 --- a/phpBB/phpbb/log/log.php +++ b/phpBB/phpbb/log/log.php @@ -747,7 +747,7 @@ class log implements \phpbb\log\log_interface foreach ($log as $key => $row) { $log[$key]['viewtopic'] = (isset($topic_auth['f_read'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id']) : false; - $log[$key]['viewpost'] = (isset($topic_auth['f_read'][$row['topic_id']]) && $row['post_id']) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id'] . '&p=' . $row['post_id']) : false; + $log[$key]['viewpost'] = (isset($topic_auth['f_read'][$row['topic_id']]) && $row['post_id']) ? append_sid("{$this->phpbb_root_path}viewtopic.{$this->php_ext}", 'f=' . $topic_auth['f_read'][$row['topic_id']] . '&t=' . $row['topic_id'] . '&p=' . $row['post_id'] . '#p' . $row['post_id']) : false; $log[$key]['viewlogs'] = (isset($topic_auth['m_'][$row['topic_id']])) ? append_sid("{$this->phpbb_root_path}mcp.{$this->php_ext}", 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, $this->user->session_id) : false; } } diff --git a/phpBB/phpbb/notification/manager.php b/phpBB/phpbb/notification/manager.php index 6923d96392..1cd7e5bc9a 100644 --- a/phpBB/phpbb/notification/manager.php +++ b/phpBB/phpbb/notification/manager.php @@ -475,9 +475,10 @@ class manager if ($type instanceof \phpbb\notification\type\type_interface && $type->is_available()) { $options = array_merge(array( - 'id' => $type->get_type(), - 'lang' => 'NOTIFICATION_TYPE_' . strtoupper($type->get_type()), - 'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS', + 'type' => $type, + 'id' => $type->get_type(), + 'lang' => 'NOTIFICATION_TYPE_' . strtoupper($type->get_type()), + 'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS', ), (($type::$notification_option !== false) ? $type::$notification_option : array())); $this->subscription_types[$options['group']][$options['id']] = $options; @@ -509,6 +510,7 @@ class manager foreach ($this->get_available_subscription_methods() as $method_name => $method) { $subscription_methods[$method_name] = array( + 'method' => $method, 'id' => $method->get_type(), 'lang' => str_replace('.', '_', strtoupper($method->get_type())), ); diff --git a/phpBB/phpbb/notification/method/email.php b/phpBB/phpbb/notification/method/email.php index 21a6559012..56dd1e9367 100644 --- a/phpBB/phpbb/notification/method/email.php +++ b/phpBB/phpbb/notification/method/email.php @@ -13,6 +13,8 @@ namespace phpbb\notification\method; +use phpbb\notification\type\type_interface; + /** * Email notification method class * This class handles sending emails for notifications @@ -56,10 +58,14 @@ class email extends \phpbb\notification\method\messenger_base /** * Is this method available for the user? * This is checked on the notifications options + * + * @param type_interface $notification_type An optional instance of a notification type. If provided, this + * method additionally checks if the type provides an email template. + * @return bool */ - public function is_available() + public function is_available(type_interface $notification_type = null) { - return $this->config['email_enable'] && $this->user->data['user_email']; + return parent::is_available($notification_type) && $this->config['email_enable'] && $this->user->data['user_email']; } /** diff --git a/phpBB/phpbb/notification/method/jabber.php b/phpBB/phpbb/notification/method/jabber.php index 509c6b432c..81fdb378e2 100644 --- a/phpBB/phpbb/notification/method/jabber.php +++ b/phpBB/phpbb/notification/method/jabber.php @@ -13,6 +13,8 @@ namespace phpbb\notification\method; +use phpbb\notification\type\type_interface; + /** * Jabber notification method class * This class handles sending Jabber messages for notifications @@ -56,10 +58,14 @@ class jabber extends \phpbb\notification\method\messenger_base /** * Is this method available for the user? * This is checked on the notifications options + * + * @param type_interface $notification_type An optional instance of a notification type. If provided, this + * method additionally checks if the type provides an email template. + * @return bool */ - public function is_available() + public function is_available(type_interface $notification_type = null) { - return ($this->global_available() && $this->user->data['user_jabber']); + return parent::is_available($notification_type) && $this->global_available() && $this->user->data['user_jabber']; } /** diff --git a/phpBB/phpbb/notification/method/messenger_base.php b/phpBB/phpbb/notification/method/messenger_base.php index 1f5525accc..32e79aa936 100644 --- a/phpBB/phpbb/notification/method/messenger_base.php +++ b/phpBB/phpbb/notification/method/messenger_base.php @@ -13,6 +13,8 @@ namespace phpbb\notification\method; +use phpbb\notification\type\type_interface; + /** * Abstract notification method handling email and jabber notifications * using the phpBB messenger. @@ -43,6 +45,19 @@ abstract class messenger_base extends \phpbb\notification\method\base } /** + * Is this method available for the user? + * This is checked on the notifications options + * + * @param type_interface $notification_type An optional instance of a notification type. This method returns false + * only if the type is provided and if it doesn't provide an email template. + * @return bool + */ + public function is_available(type_interface $notification_type = null) + { + return $notification_type === null || $notification_type->get_email_template() !== false; + } + + /** * Notify using phpBB messenger * * @param int $notify_method Notify method for messenger (e.g. NOTIFY_IM) diff --git a/phpBB/phpbb/path_helper.php b/phpBB/phpbb/path_helper.php index 154361ef64..5b6db35f23 100644 --- a/phpBB/phpbb/path_helper.php +++ b/phpBB/phpbb/path_helper.php @@ -496,4 +496,17 @@ class path_helper return $page; } + + /** + * Tells if the router is currently in use (if the current page is a route or not) + * + * @return bool + */ + public function is_router_used() + { + // Script name URI (e.g. phpBB/app.php) + $script_name = $this->symfony_request->getScriptName(); + + return basename($script_name) === 'app.' . $this->php_ext; + } } 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/session.php b/phpBB/phpbb/session.php index c5b50c2b07..6b5b8f2625 100644 --- a/phpBB/phpbb/session.php +++ b/phpBB/phpbb/session.php @@ -91,9 +91,18 @@ class session $page_name .= str_replace('%2F', '/', urlencode($symfony_request_path)); } - // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath($root_path))); - $page_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath('./'))); + if (substr($root_path, 0, 2) === './' && strpos($root_path, '..') === false) + { + $root_dirs = explode('/', str_replace('\\', '/', rtrim($root_path, '/'))); + $page_dirs = explode('/', str_replace('\\', '/', '.')); + } + else + { + // current directory within the phpBB root (for example: adm) + $root_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath($root_path))); + $page_dirs = explode('/', str_replace('\\', '/', $phpbb_filesystem->realpath('./'))); + } + $intersection = array_intersect_assoc($root_dirs, $page_dirs); $root_dirs = array_diff_assoc($root_dirs, $intersection); diff --git a/phpBB/phpbb/textformatter/s9e/factory.php b/phpBB/phpbb/textformatter/s9e/factory.php index 7719ce5afa..d5ad8283d9 100644 --- a/phpBB/phpbb/textformatter/s9e/factory.php +++ b/phpBB/phpbb/textformatter/s9e/factory.php @@ -273,6 +273,11 @@ class factory implements \phpbb\textformatter\cache_interface { $configurator->BBCodes->addCustom($bbcode['usage'], $bbcode['template']); } + if (isset($configurator->tags['QUOTE'])) + { + // Remove the nesting limit and let other services remove quotes at parsing time + $configurator->tags['QUOTE']->nestingLimit = PHP_INT_MAX; + } // Modify the template to disable images/flash depending on user's settings foreach (array('FLASH', 'IMG') as $name) @@ -323,6 +328,9 @@ class factory implements \phpbb\textformatter\cache_interface // Only parse emoticons at the beginning of the text or if they're preceded by any // one of: a new line, a space, a dot, or a right square bracket $configurator->Emoticons->notAfter = '[^\\n .\\]]'; + + // Ignore emoticons that are immediately followed by a "word" character + $configurator->Emoticons->notBefore = '\\w'; } // Load the censored words @@ -382,7 +390,18 @@ class factory implements \phpbb\textformatter\cache_interface unset($configurator->tags['censor:tag']); } - $objects = $configurator->finalize(); + $objects = $configurator->finalize(); + + /** + * Access the objects returned by finalize() before they are saved to cache + * + * @event core.text_formatter_s9e_configure_finalize + * @var array objects Array containing a "parser" object, a "renderer" object and optionally a "js" string + * @since 3.2.2-RC1 + */ + $vars = array('objects'); + extract($this->dispatcher->trigger_event('core.text_formatter_s9e_configure_finalize', compact($vars))); + $parser = $objects['parser']; $renderer = $objects['renderer']; @@ -518,7 +537,9 @@ class factory implements \phpbb\textformatter\cache_interface protected function extract_templates($template) { // Capture the template fragments - preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END .*? -->#s', $template, $matches, PREG_SET_ORDER); + // Allow either phpBB template or the Twig syntax + preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END .*? -->#s', $template, $matches, PREG_SET_ORDER) ?: + preg_match_all('#{% for (.*?) in .*? %}(.*?){% endfor %}#s', $template, $matches, PREG_SET_ORDER); $fragments = array(); foreach ($matches as $match) 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; + } } |