diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index 6541350..36b3d55 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -188,6 +188,11 @@ const DRUPAL_KILOBYTE = 1024; /** + * The maximum number of characters in a module or theme name. + */ +const DRUPAL_EXTENSION_NAME_MAX_LENGTH = 50; + +/** * Time of the current request in seconds elapsed since the Unix Epoch. * * This differs from $_SERVER['REQUEST_TIME'], which is stored as a float diff --git a/core/includes/module.inc b/core/includes/module.inc index bc91311..bef3a2a 100644 --- a/core/includes/module.inc +++ b/core/includes/module.inc @@ -8,6 +8,7 @@ use Drupal\Component\Utility\NestedArray; use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\DependencyInjection\ContainerBuilder; +use Drupal\Core\Extension\ExtensionNameLengthException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Yaml\Parser; @@ -260,6 +261,13 @@ function module_enable($module_list, $enable_dependencies = TRUE) { unset($module_list[$module]); continue; } + // Throw an exception if the module name is too long. + if (strlen($module) > DRUPAL_EXTENSION_NAME_MAX_LENGTH) { + throw new ExtensionNameLengthException(format_string('Module name %name is over the maximum allowed length of @max characters.', array( + '%name' => $module, + '@max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, + ))); + } $module_list[$module] = $module_data[$module]->sort; // Add dependencies to the list, with a placeholder weight. diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 3683d37..87eaed6 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -11,6 +11,7 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Config\Config; use Drupal\Core\Language\Language; +use Drupal\Core\Extension\ExtensionNameLengthException; use Drupal\Core\Template\Attribute; use Drupal\Core\Utility\ThemeRegistry; use Drupal\Core\Theme\ThemeSettings; @@ -1563,6 +1564,14 @@ function theme_enable($theme_list) { $theme_config = config('system.theme'); $disabled_themes = config('system.theme.disabled'); foreach ($theme_list as $key) { + // Throw an exception if the theme name is too long. + if (strlen($key) > DRUPAL_EXTENSION_NAME_MAX_LENGTH) { + throw new ExtensionNameLengthException(format_string('Theme name %name is over the maximum allowed length of @max characters.', array( + '%name' => $key, + '@max' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, + ))); + } + // The value is not used; the weight is ignored for themes currently. $theme_config->set("enabled.$key", 0); $disabled_themes->clear($key); diff --git a/core/includes/update.inc b/core/includes/update.inc index a5feb50..7bd9783 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -360,6 +360,16 @@ function update_prepare_d8_bootstrap() { // Migrate each extension into configuration, varying by the extension's // status, and record its schema version. foreach ($result as $record) { + if (drupal_strlen($record->name) > 50) { + $requirements['module name too long ' . $record->name] = array( + 'title' => 'Module name too long', + 'value' => format_string('@name is @count characters long.', array('@name' => $record->name, '@count' => drupal_strlen($record->name))), + 'description' => 'Module names longer than 50 characters are no longer supported.', + 'severity' => REQUIREMENT_ERROR, + ); + update_extra_requirements($requirements); + } + if ($record->type == 'module') { if ($record->status && isset($module_data[$record->name])) { $module_config->set('enabled.' . $record->name, $record->weight); diff --git a/core/lib/Drupal/Core/Extension/ExtensionNameLengthException.php b/core/lib/Drupal/Core/Extension/ExtensionNameLengthException.php new file mode 100644 index 0000000..8930d1e --- /dev/null +++ b/core/lib/Drupal/Core/Extension/ExtensionNameLengthException.php @@ -0,0 +1,13 @@ + array( 'description' => 'The name of the module that is using the file.', 'type' => 'varchar', - 'length' => 255, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => '', ), @@ -288,3 +288,19 @@ function file_update_8002() { } } } + +/** + * Convert the 'module' column in {file_usage} to the maximum shortname length. + */ +function file_update_8003() { + if (db_field_exists('file_usage', 'module')) { + $spec = array( + 'description' => 'The name of the module that is using the file.', + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => '', + ); + db_change_field('file_usage', 'module', 'module', $spec); + } +} diff --git a/core/modules/menu_link/menu_link.install b/core/modules/menu_link/menu_link.install index 1d80679..a09be43 100644 --- a/core/modules/menu_link/menu_link.install +++ b/core/modules/menu_link/menu_link.install @@ -75,7 +75,7 @@ function menu_link_schema() { 'module' => array( 'description' => 'The name of the module that generated this link.', 'type' => 'varchar', - 'length' => 255, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => 'system', ), diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 67cd0c3..8a427fc 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -322,7 +322,7 @@ function node_schema() { 'module' => array( 'description' => 'The module defining this node type.', 'type' => 'varchar', - 'length' => 255, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, ), 'description' => array( @@ -754,6 +754,21 @@ function node_update_8015() { } /** + * Convert the 'module' column in {node_type} to the maximum shortname length. + */ +function node_update_8016() { + if (db_field_exists('node_type', 'module')) { + $spec = array( + 'description' => 'The module defining this node type.', + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + ); + db_change_field('node_type', 'module', 'module', $spec); + } +} + +/** * @} End of "addtogroup updates-7.x-to-8.x" * The next series of updates should start at 9000. */ diff --git a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnable.php b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnable.php index b2d08fc..427f86f 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnable.php +++ b/core/modules/system/lib/Drupal/system/Tests/Module/ModuleEnable.php @@ -7,6 +7,7 @@ namespace Drupal\system\Tests\Module; +use Drupal\Core\Extension\ExtensionNameLengthException; use Drupal\simpletest\WebTestBase; /** @@ -44,4 +45,19 @@ function testRequiredModuleSchemaVersions() { $this->assertTrue($version > 0, 'User module version is > 0.'); } + /** + * Tests that an exception is thrown when a module name is too long. + */ + function testModuleNameLength() { + $module_name = 'invalid_module_name_over_the_maximum_allowed_character_length'; + $message = format_string('Exception thrown when enabling module %name with a name length over the allowed maximum', array('%name' => $module_name)); + try { + module_enable(array($module_name)); + $this->fail($message); + } + catch (ExtensionNameLengthException $e) { + $this->pass($message); + } + } + } diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ExistingModuleNameLengthUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ExistingModuleNameLengthUpgradePathTest.php new file mode 100644 index 0000000..d1004cc --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ExistingModuleNameLengthUpgradePathTest.php @@ -0,0 +1,48 @@ + 'Module name length upgrade test (existing module)', + 'description' => 'Upgrade path test when there is an installed module with a too long name.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + // Path to the database dump files. + $this->databaseDumpFiles = array( + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.minimal.database.php.gz', + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.module_name_length.database.php', + ); + parent::setUp(); + } + + /** + * Checks that upgrading is not possible when there is a too long module name. + */ + public function testUpgradeAborts() { + // Load the first update screen. + $this->getUpdatePhp(); + if (!$this->assertResponse(200)) { + throw new \Exception('Initial GET to update.php did not return HTTP 200 status.'); + } + + $this->assertText('Module name too long'); + $this->assertNoFieldByXPath('//input[@type="submit"]', 'Allowed to continue with the update process.'); + } + +} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModuleNameLengthUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModuleNameLengthUpgradePathTest.php new file mode 100644 index 0000000..9525d6f --- /dev/null +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/ModuleNameLengthUpgradePathTest.php @@ -0,0 +1,57 @@ + 'Module name length upgrade test', + 'description' => 'Upgrade path tests for module name length related changes.', + 'group' => 'Upgrade path', + ); + } + + public function setUp() { + // Path to the database dump files. + $this->databaseDumpFiles = array( + drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.minimal.database.php.gz', + ); + parent::setUp(); + } + + /** + * Performs upgrade path tests for module name length related changes. + */ + public function testModuleNameLengths() { + $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); + + // Make sure that the module colums where shortened. + try { + db_insert('file_usage') + ->fields(array( + 'fid' => 2, + 'module' => str_repeat('b', 51), + 'type' => $this->randomName(), + 'id' => $this->randomName(), + 'count' => 1, + )) + ->execute(); + $this->fail('Length of {file_usage}.module successfully updated.'); + } + catch (DatabaseExceptionWrapper $e) { + $this->pass('Length of {file_usage}.module successfully updated.'); + } + } + +} diff --git a/core/modules/system/system.install b/core/modules/system/system.install index 3824136..9368b58 100644 --- a/core/modules/system/system.install +++ b/core/modules/system/system.install @@ -2194,6 +2194,25 @@ function system_update_8056() { } /** + * Change the length of the 'module' column to the maximum length. + * + * @see system_update_8048() + */ +function system_update_8057() { + if (db_field_exists('menu_links', 'module')) { + $spec = array( + 'description' => 'The name of the module that generated this link.', + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => 'system', + ); + db_change_field('menu_links', 'module', 'module', $spec); + } + +} + +/** * @} End of "defgroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.info.yml b/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.info.yml new file mode 100644 index 0000000..16d9c78 --- /dev/null +++ b/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.info.yml @@ -0,0 +1,7 @@ +name: 'Module name length test' +type: module +description: 'Test module with a name over the maximum allowed characters.' +package: Testing +version: VERSION +core: 8.x +hidden: TRUE diff --git a/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.module b/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.module new file mode 100644 index 0000000..d0dc049 --- /dev/null +++ b/core/modules/system/tests/modules/invalid_module_name_over_the_maximum_allowed_character_length/invalid_module_name_over_the_maximum_allowed_character_length.module @@ -0,0 +1,8 @@ +fields(array( + 'filename' => 'modules/invalid_module_name_over_the_maximum_allowed_character_length.module', + 'name' => 'invalid_module_name_over_the_maximum_allowed_character_length', + 'type' => 'module', + 'status' => 1, + 'schema_version' => 0, + )) + ->execute(); diff --git a/core/modules/user/user.install b/core/modules/user/user.install index 9819cde..df9112c 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -60,7 +60,7 @@ function user_schema() { ), 'theme' => array( 'type' => 'varchar', - 'length' => 255, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => '', 'description' => "User's default theme.", @@ -167,7 +167,7 @@ function user_schema() { ), 'module' => array( 'type' => 'varchar', - 'length' => 255, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => '', 'description' => "The module declaring the permission.", @@ -198,7 +198,7 @@ function user_schema() { 'module' => array( 'description' => 'The name of the module declaring the variable.', 'type' => 'varchar', - 'length' => 204, + 'length' => DRUPAL_EXTENSION_NAME_MAX_LENGTH, 'not null' => TRUE, 'default' => '', ), @@ -1058,5 +1058,43 @@ function user_update_8017() { } /** + * Use the maximum allowed module name length in module name database fields. + */ +function user_update_8018() { + if (db_field_exists('role_permission', 'module')) { + $spec = array( + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The module declaring the permission.', + ); + db_change_field('role_permission', 'module', 'module', $spec); + } + + if (db_field_exists('users_data', 'module')) { + $spec = array( + 'description' => 'The name of the module declaring the variable.', + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => '', + ); + db_change_field('users_data', 'module', 'module', $spec); + } + + if (db_field_exists('users', 'theme')) { + $spec = array( + 'type' => 'varchar', + 'length' => 50, + 'not null' => TRUE, + 'default' => '', + 'description' => "User's default theme.", + ); + db_change_field('users', 'theme', 'theme', $spec); + } +} + +/** * @} End of "addtogroup updates-7.x-to-8.x". */