From 66055927c85826e1ada1bacc37997da2d061da14 Mon Sep 17 00:00:00 2001
From: Manuel Selbach <manuel_selbach@yahoo.de>
Date: Mon, 27 Jan 2020 22:56:33 +0100
Subject: [PATCH] [TASK] Check valid database name specific for DBMS

With this change the check for a valid database name will be done
specific for each DBMS.

Resolves: #85739
Releases: master
Change-Id: Ia006a31fb4686fc45ac2ab3862f3a530ed5eef58
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/63053
Tested-by: TYPO3com <noreply@typo3.com>
Tested-by: Susanne Moog <look@susi.dev>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Susanne Moog <look@susi.dev>
Reviewed-by: Benni Mack <benni@typo3.org>
---
 .../Platform/AbstractPlatform.php             |  9 +++-
 .../DatabaseCheck/Platform/PostgreSql.php     | 28 +++++++++++
 .../DatabaseCheck/Platform/SqlSrv.php         | 49 +++++++++++++++++++
 .../DatabaseCheck/Platform/Sqlite.php         | 30 ++++++++++++
 4 files changed, 114 insertions(+), 2 deletions(-)

diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/AbstractPlatform.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/AbstractPlatform.php
index 466fd32aaf10..f95a1d831151 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/AbstractPlatform.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/AbstractPlatform.php
@@ -30,6 +30,11 @@ abstract class AbstractPlatform implements PlatformCheckInterface
      */
     protected $messageQueue;
 
+    /**
+     * @var int The maximum length of the schema name
+     */
+    protected const SCHEMA_NAME_MAX_LENGTH = 64;
+
     public function __construct()
     {
         $this->messageQueue = new FlashMessageQueue('install-database-check-platform');
@@ -58,7 +63,7 @@ abstract class AbstractPlatform implements PlatformCheckInterface
      */
     public static function isValidDatabaseName(string $databaseName): bool
     {
-        return strlen($databaseName) <= 50 && preg_match('/^[a-zA-Z0-9\$_]*$/', $databaseName);
+        return strlen($databaseName) <= static::SCHEMA_NAME_MAX_LENGTH && preg_match('/^[a-zA-Z0-9\$_]*$/', $databaseName);
     }
 
     protected function checkDatabaseName(Connection $connection): void
@@ -69,7 +74,7 @@ abstract class AbstractPlatform implements PlatformCheckInterface
 
         $this->messageQueue->enqueue(
             new FlashMessage(
-                'Given database name must be shorter than fifty characters'
+                'The given database name must not be longer than ' . static::SCHEMA_NAME_MAX_LENGTH . ' characters'
                 . ' and consist solely of basic latin letters (a-z), digits (0-9), dollar signs ($)'
                 . ' and underscores (_).',
                 'Database name not valid',
diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/PostgreSql.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/PostgreSql.php
index 9475ec550216..111414afb9af 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/PostgreSql.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/PostgreSql.php
@@ -205,4 +205,32 @@ class PostgreSql extends AbstractPlatform
             ));
         }
     }
+
+    /**
+     * Validate the database name
+     *
+     * @param string $databaseName
+     * @return bool
+     */
+    public static function isValidDatabaseName(string $databaseName): bool
+    {
+        return strlen($databaseName) <= static::SCHEMA_NAME_MAX_LENGTH && preg_match('/^(?!pg_)[a-zA-Z0-9\$_]*$/', $databaseName);
+    }
+
+    protected function checkDatabaseName(Connection $connection): void
+    {
+        if (static::isValidDatabaseName($connection->getDatabase())) {
+            return;
+        }
+
+        $this->messageQueue->enqueue(
+            new FlashMessage(
+                'The given database name must not be longer than ' . static::SCHEMA_NAME_MAX_LENGTH . ' characters'
+                . ' and consist solely of basic latin letters (a-z), digits (0-9), dollar signs ($)'
+                . ' and underscores (_) and does not start with "pg_".',
+                'Database name not valid',
+                FlashMessage::ERROR
+            )
+        );
+    }
 }
diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/SqlSrv.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/SqlSrv.php
index 8b3869e5ba51..ed2728654f8f 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/SqlSrv.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/SqlSrv.php
@@ -27,6 +27,13 @@ use TYPO3\CMS\Core\Utility\GeneralUtility;
  */
 class SqlSrv extends AbstractPlatform
 {
+    /**
+     * https://docs.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers
+     *
+     * @var int The maximum length of the schema name
+     */
+    protected const SCHEMA_NAME_MAX_LENGTH = 128;
+
     /**
      * SQL Server has a more complex naming schema for the collation.
      * For more information visit:
@@ -139,4 +146,46 @@ class SqlSrv extends AbstractPlatform
             }
         }
     }
+
+    /**
+     * Validate the database name
+     * https://docs.microsoft.com/en-us/sql/relational-databases/databases/database-identifiers
+     *
+     * Examples:
+     *
+     * valid:
+     *      _foo
+     *      @foo
+     *      #foo
+     *      _floo1äea
+     *      @foo111111111kemcie_l#@
+     *
+     * not valid:
+     *      @@thisShouldNotBeValid
+     *
+     *
+     * @param string $databaseName
+     * @return bool
+     */
+    public static function isValidDatabaseName(string $databaseName): bool
+    {
+        return strlen($databaseName) <= static::SCHEMA_NAME_MAX_LENGTH && preg_match('/^(?!@@)[a-zA-Z0-9\$_@#\p{L}]*$/u', $databaseName);
+    }
+
+    protected function checkDatabaseName(Connection $connection): void
+    {
+        if (static::isValidDatabaseName($connection->getDatabase())) {
+            return;
+        }
+
+        $this->messageQueue->enqueue(
+            new FlashMessage(
+                'The given database name must not be longer than ' . static::SCHEMA_NAME_MAX_LENGTH . ' characters'
+                . ' and consist solely of basic latin letters (a-z), unicode characters, digits (0-9), dollar signs ($),'
+                . ' symbol @, underscores (_) and does not start with "@@".',
+                'Database name not valid',
+                FlashMessage::ERROR
+            )
+        );
+    }
 }
diff --git a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/Sqlite.php b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/Sqlite.php
index 1e0d159b04d8..23c8c95f4367 100644
--- a/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/Sqlite.php
+++ b/typo3/sysext/install/Classes/SystemEnvironment/DatabaseCheck/Platform/Sqlite.php
@@ -18,6 +18,7 @@ namespace TYPO3\CMS\Install\SystemEnvironment\DatabaseCheck\Platform;
 
 use TYPO3\CMS\Core\Database\Connection;
 use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Messaging\FlashMessage;
 use TYPO3\CMS\Core\Messaging\FlashMessageQueue;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 
@@ -67,4 +68,33 @@ class Sqlite extends AbstractPlatform
     {
         // TODO: Implement getDefaultDatabaseServerCharset() method.
     }
+
+    /**
+     * Validate the database name
+     * SQLite does not have any limitation for the length of the database name,
+     * but must start with a letter or _
+     *
+     * @param string $databaseName
+     * @return bool
+     */
+    public static function isValidDatabaseName(string $databaseName): bool
+    {
+        return (bool)preg_match('/^[A-Za-z_\/][a-zA-Z0-9\$\/_.-]*$/', $databaseName);
+    }
+
+    protected function checkDatabaseName(Connection $connection): void
+    {
+        if (static::isValidDatabaseName($connection->getDatabase())) {
+            return;
+        }
+
+        $this->messageQueue->enqueue(
+            new FlashMessage(
+                'The given database name must consist solely of basic latin letters (a-z), digits (0-9)'
+                . ' and underscores (_).',
+                'Database name not valid',
+                FlashMessage::ERROR
+            )
+        );
+    }
 }
-- 
GitLab