Loading colorbox.install +34 −2 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ * Install, update and uninstall functions for the colorbox module. */ use Drupal\Core\Url; /** * Implements hook_install(). */ Loading @@ -21,9 +23,14 @@ function colorbox_requirements($phase) { } $library = \Drupal::service('library.discovery')->getLibraryByName('colorbox', 'colorbox'); $library_exists = file_exists(DRUPAL_ROOT . '/' . $library['js'][0]['data']); $library_exists = !empty($library['js'][0]['data']) && file_exists(DRUPAL_ROOT . '/' . $library['js'][0]['data']); $dompurify = \Drupal::service('library.discovery')->getLibraryByName('colorbox', 'dompurify'); $dompurify_exists = !empty($dompurify['js'][0]['data']) && file_exists(DRUPAL_ROOT . '/' . $dompurify['js'][0]['data']); return [ $library_requirements = [ 'colorbox_library_downloaded' => [ 'title' => t('Colorbox library'), 'value' => $library_exists ? t('Installed') : t('Not installed'), Loading @@ -31,4 +38,29 @@ function colorbox_requirements($phase) { 'severity' => $library_exists ? REQUIREMENT_OK : REQUIREMENT_ERROR, ], ]; $suppress_warning = \Drupal::config('colorbox.settings')->get('dompurify_hide_warning'); if (!$suppress_warning) { $library_requirements['colorbox_dompurify_downloaded'] = [ 'title' => t('DOMPurify library'), 'value' => $dompurify_exists ? t('Installed') : t('Not installed'), 'description' => $dompurify_exists ? '' : t('The DOMPurify library is not installed. ' . 'The Colorbox module uses this library to sanitize HTML captions. ' . 'Without this library, all captions will be treated as plain text. ' . 'If you intend to have HTML captions in Colorbox content, ' . 'the DOMPurify library needs to be <a href="@url">downloaded</a> ' . 'and extracted into the /libraries/DOMPurify folder in your Drupal ' . 'installation directory. <br /><br />' . 'If you do not intend to use HTML captions, you can suppress this warning on the ' . '<a href="@config">Colorbox configuration page.</a>', [ '@url' => 'https://github.com/cure53/DOMPurify/archive/main.zip', '@config' => Url::fromRoute('colorbox.admin_settings')->toString(), ]), 'severity' => $dompurify_exists ? REQUIREMENT_OK : REQUIREMENT_WARNING, ]; } return $library_requirements; } colorbox.libraries.yml +11 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ colorbox: js: /libraries/colorbox/jquery.colorbox-min.js: { minified: true } dependencies: - core/drupal - core/drupalSettings - core/jquery - core/jquery.once Loading @@ -22,6 +24,15 @@ colorbox-dev: - core/jquery - core/jquery.once dompurify: remote: https://github.com/cure53/DOMPurify version: VERSION license: name: MPL gpl-compatible: false js: /libraries/DOMPurify/dist/purify.min.js: { } init: version: VERSION js: Loading js/colorbox.js +48 −3 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * Colorbox JS. */ (function ($, Drupal) { (function ($, Drupal, drupalSettings) { 'use strict'; Loading Loading @@ -36,7 +36,7 @@ // If a title attribute is supplied, sanitize it. var title = $(this).attr('title'); if (title) { extendParams.title = Drupal.checkPlain(title); extendParams.title = Drupal.colorbox.sanitizeMarkup(title); } $(this).colorbox($.extend({}, settings.colorbox, extendParams)); }); Loading Loading @@ -64,4 +64,49 @@ } }; })(jQuery, Drupal); // Create colorbox namespace if it doesn't exist. if (!Drupal.hasOwnProperty('colorbox')) { Drupal.colorbox = {}; } /** * Global function to allow sanitizing captions and control strings. * * @param markup * String containing potential markup. * @return @string * Sanitized string with potentially dangerous markup removed. */ Drupal.colorbox.sanitizeMarkup = function(markup) { // If DOMPurify installed, allow some HTML. Otherwise, treat as plain text. if (typeof DOMPurify !== 'undefined') { var purifyConfig = { ALLOWED_TAGS: [ 'a', 'b', 'strong', 'i', 'em', 'u', 'cite', 'code', 'br' ], ALLOWED_ATTR: [ 'href', 'hreflang', 'title', 'target' ] } if (drupalSettings.hasOwnProperty('dompurify_custom_config')) { purifyConfig = drupalSettings.dompurify_custom_config; } return DOMPurify.sanitize(markup, purifyConfig); } else { return Drupal.checkPlain(markup); } } })(jQuery, Drupal, drupalSettings); src/Commands/ColorboxCommands.php +81 −0 Original line number Diff line number Diff line Loading @@ -115,4 +115,85 @@ class ColorboxCommands extends DrushCommands { } } /** * Download and install the DOMPurify plugin. * * @param mixed $path * Optional. A path where to install the DOMPurify plugin. * If omitted Drush will use the default location. * * @command colorbox:dompurify * @aliases colorboxdompurify,colorbox-dompurify */ public function domPurify($path = '') { $fs = new Filesystem(); if (empty($path)) { $path = DRUPAL_ROOT . '/libraries/DOMPurify'; } // Create path if it doesn't exist // Exit with a message otherwise. if (!$fs->exists($path)) { $fs->mkdir($path); } else { $this->logger()->notice(dt('DOMPurify is already present at @path. No download required.', ['@path' => $path])); return; } // Load the DOMPurify defined library. if ($dompurify_library = $this->libraryDiscovery->getLibraryByName('colorbox', 'dompurify')) { // Download the file. $client = new Client(); $destination = tempnam(sys_get_temp_dir(), 'DOMPurify-tmp'); try { $client->get($dompurify_library['remote'] . '/archive/main.zip', ['save_to' => $destination]); } catch (RequestException $e) { // Remove the directory. $fs->remove($path); $this->logger()->error(dt('Drush was unable to download the DOMPurify library from @remote. @exception', [ '@remote' => $dompurify_library['remote'] . '/archive/main.zip', '@exception' => $e->getMessage(), ], 'error')); return; } // Move downloaded file. $fs->rename($destination, $path . '/DOMPurify.zip'); // Unzip the file. $zip = new \ZipArchive(); $res = $zip->open($path . '/DOMPurify.zip'); if ($res === TRUE) { $zip->extractTo($path); $zip->close(); } else { // Remove the directory if unzip fails and exit. $fs->remove($path); $this->logger()->error(dt('Error: unable to unzip DOMPurify file.', [], 'error')); return; } // Remove the downloaded zip file. $fs->remove($path . '/DOMPurify.zip'); // Move the dist directory. $fs->mirror($path . '/DOMPurify-main/dist', $path . '/dist', NULL, ['override' => TRUE]); $fs->remove($path . '/DOMPurify-main'); // Success. $this->logger()->notice(dt('The DOMPurify library has been successfully downloaded to @path.', [ '@path' => $path, ], 'success')); } else { $this->logger()->error(dt('Drush was unable to load the DOMPurify library')); } } } src/Form/ColorboxSettingsForm.php +56 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\colorbox\Form; use Drupal\Core\Asset\LibraryDiscoveryInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; Loading @@ -21,6 +22,13 @@ class ColorboxSettingsForm extends ConfigFormBase { */ protected $extensionListModule; /** * Library discovery service. * * @var LibraryDiscoveryInterface */ protected $libraryDiscovery; /** * A state that represents the custom settings being enabled. */ Loading @@ -47,11 +55,17 @@ class ColorboxSettingsForm extends ConfigFormBase { * The module handler service. * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module * The list of available modules. * @param \Drupal\Core\Asset\LibraryDiscoveryInterface $libraryDiscovery * The library discovery service. */ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $moduleHandler, ModuleExtensionList $extension_list_module) { public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $moduleHandler, ModuleExtensionList $extension_list_module, LibraryDiscoveryInterface $libraryDiscovery) { parent::__construct($config_factory); $this->moduleHandler = $moduleHandler; $this->extensionListModule = $extension_list_module; $this->libraryDiscovery = $libraryDiscovery; } /** Loading @@ -61,7 +75,8 @@ class ColorboxSettingsForm extends ConfigFormBase { return new static( $container->get('config.factory'), $container->get('module_handler'), $container->get('extension.list.module') $container->get('extension.list.module'), $container->get('library.discovery') ); } Loading Loading @@ -89,6 +104,44 @@ class ColorboxSettingsForm extends ConfigFormBase { $config = $this->configFactory->get('colorbox.settings'); $dompurify = $this->libraryDiscovery->getLibraryByName('colorbox', 'dompurify'); $dompurify_file = !empty($dompurify['js'][0]['data']) ? DRUPAL_ROOT . '/' . $dompurify['js'][0]['data'] : NULL; $dompurify_exists = !empty($dompurify) && !empty($dompurify_file) && file_exists($dompurify_file); $form['colorbox_dompurify'] = [ '#type' => 'details', '#title' => $this->t('DOMPurify Library'), '#open' => TRUE, ]; $dompurify_message = $dompurify_exists ? $this->t('The DOMPurify library is installed. ' . 'This library will sanitize HTML in Colorbox captions.') : $this->t('The <a href="@dompurify_link">DOMPurify</a> ' . 'library is not installed. ' . 'This library is necessary if you want to use HTML in Colorbox captions. ' . 'Without it, all captions will be treated as plain text.', [ '@dompurify_link' => 'https://github.com/cure53/DOMPurify/archive/main.zip' ]); $form['colorbox_dompurify']['dompurify_message'] = array( '#type' => 'markup', '#prefix' => '<p>', '#suffix' => '</p>', '#markup' => $dompurify_message, ); if (!$dompurify_exists) { $form['colorbox_dompurify']['dompurify_hide_warning'] = array( '#type' => 'checkbox', '#title' => t('Don\'t show warning on status report'), '#default_value' => $config->get('dompurify_hide_warning'), '#description' => t('By default, a warning appears on Drupal\'s ' . 'status report if this library is missing. Check this box to ' . 'suppress the warning.'), ); } $form['colorbox_custom_settings'] = [ '#type' => 'details', '#title' => $this->t('Styles and options'), Loading Loading @@ -370,6 +423,7 @@ class ColorboxSettingsForm extends ConfigFormBase { $config = $this->configFactory->getEditable('colorbox.settings'); $config ->set('dompurify_hide_warning', $form_state->getValue('dompurify_hide_warning')) ->set('custom.style', $form_state->getValue('colorbox_style')) ->set('custom.activate', $form_state->getValue('colorbox_custom_settings_activate')) ->set('custom.transition_type', $form_state->getValue('colorbox_transition_type')) Loading Loading
colorbox.install +34 −2 Original line number Diff line number Diff line Loading @@ -5,6 +5,8 @@ * Install, update and uninstall functions for the colorbox module. */ use Drupal\Core\Url; /** * Implements hook_install(). */ Loading @@ -21,9 +23,14 @@ function colorbox_requirements($phase) { } $library = \Drupal::service('library.discovery')->getLibraryByName('colorbox', 'colorbox'); $library_exists = file_exists(DRUPAL_ROOT . '/' . $library['js'][0]['data']); $library_exists = !empty($library['js'][0]['data']) && file_exists(DRUPAL_ROOT . '/' . $library['js'][0]['data']); $dompurify = \Drupal::service('library.discovery')->getLibraryByName('colorbox', 'dompurify'); $dompurify_exists = !empty($dompurify['js'][0]['data']) && file_exists(DRUPAL_ROOT . '/' . $dompurify['js'][0]['data']); return [ $library_requirements = [ 'colorbox_library_downloaded' => [ 'title' => t('Colorbox library'), 'value' => $library_exists ? t('Installed') : t('Not installed'), Loading @@ -31,4 +38,29 @@ function colorbox_requirements($phase) { 'severity' => $library_exists ? REQUIREMENT_OK : REQUIREMENT_ERROR, ], ]; $suppress_warning = \Drupal::config('colorbox.settings')->get('dompurify_hide_warning'); if (!$suppress_warning) { $library_requirements['colorbox_dompurify_downloaded'] = [ 'title' => t('DOMPurify library'), 'value' => $dompurify_exists ? t('Installed') : t('Not installed'), 'description' => $dompurify_exists ? '' : t('The DOMPurify library is not installed. ' . 'The Colorbox module uses this library to sanitize HTML captions. ' . 'Without this library, all captions will be treated as plain text. ' . 'If you intend to have HTML captions in Colorbox content, ' . 'the DOMPurify library needs to be <a href="@url">downloaded</a> ' . 'and extracted into the /libraries/DOMPurify folder in your Drupal ' . 'installation directory. <br /><br />' . 'If you do not intend to use HTML captions, you can suppress this warning on the ' . '<a href="@config">Colorbox configuration page.</a>', [ '@url' => 'https://github.com/cure53/DOMPurify/archive/main.zip', '@config' => Url::fromRoute('colorbox.admin_settings')->toString(), ]), 'severity' => $dompurify_exists ? REQUIREMENT_OK : REQUIREMENT_WARNING, ]; } return $library_requirements; }
colorbox.libraries.yml +11 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,8 @@ colorbox: js: /libraries/colorbox/jquery.colorbox-min.js: { minified: true } dependencies: - core/drupal - core/drupalSettings - core/jquery - core/jquery.once Loading @@ -22,6 +24,15 @@ colorbox-dev: - core/jquery - core/jquery.once dompurify: remote: https://github.com/cure53/DOMPurify version: VERSION license: name: MPL gpl-compatible: false js: /libraries/DOMPurify/dist/purify.min.js: { } init: version: VERSION js: Loading
js/colorbox.js +48 −3 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ * Colorbox JS. */ (function ($, Drupal) { (function ($, Drupal, drupalSettings) { 'use strict'; Loading Loading @@ -36,7 +36,7 @@ // If a title attribute is supplied, sanitize it. var title = $(this).attr('title'); if (title) { extendParams.title = Drupal.checkPlain(title); extendParams.title = Drupal.colorbox.sanitizeMarkup(title); } $(this).colorbox($.extend({}, settings.colorbox, extendParams)); }); Loading Loading @@ -64,4 +64,49 @@ } }; })(jQuery, Drupal); // Create colorbox namespace if it doesn't exist. if (!Drupal.hasOwnProperty('colorbox')) { Drupal.colorbox = {}; } /** * Global function to allow sanitizing captions and control strings. * * @param markup * String containing potential markup. * @return @string * Sanitized string with potentially dangerous markup removed. */ Drupal.colorbox.sanitizeMarkup = function(markup) { // If DOMPurify installed, allow some HTML. Otherwise, treat as plain text. if (typeof DOMPurify !== 'undefined') { var purifyConfig = { ALLOWED_TAGS: [ 'a', 'b', 'strong', 'i', 'em', 'u', 'cite', 'code', 'br' ], ALLOWED_ATTR: [ 'href', 'hreflang', 'title', 'target' ] } if (drupalSettings.hasOwnProperty('dompurify_custom_config')) { purifyConfig = drupalSettings.dompurify_custom_config; } return DOMPurify.sanitize(markup, purifyConfig); } else { return Drupal.checkPlain(markup); } } })(jQuery, Drupal, drupalSettings);
src/Commands/ColorboxCommands.php +81 −0 Original line number Diff line number Diff line Loading @@ -115,4 +115,85 @@ class ColorboxCommands extends DrushCommands { } } /** * Download and install the DOMPurify plugin. * * @param mixed $path * Optional. A path where to install the DOMPurify plugin. * If omitted Drush will use the default location. * * @command colorbox:dompurify * @aliases colorboxdompurify,colorbox-dompurify */ public function domPurify($path = '') { $fs = new Filesystem(); if (empty($path)) { $path = DRUPAL_ROOT . '/libraries/DOMPurify'; } // Create path if it doesn't exist // Exit with a message otherwise. if (!$fs->exists($path)) { $fs->mkdir($path); } else { $this->logger()->notice(dt('DOMPurify is already present at @path. No download required.', ['@path' => $path])); return; } // Load the DOMPurify defined library. if ($dompurify_library = $this->libraryDiscovery->getLibraryByName('colorbox', 'dompurify')) { // Download the file. $client = new Client(); $destination = tempnam(sys_get_temp_dir(), 'DOMPurify-tmp'); try { $client->get($dompurify_library['remote'] . '/archive/main.zip', ['save_to' => $destination]); } catch (RequestException $e) { // Remove the directory. $fs->remove($path); $this->logger()->error(dt('Drush was unable to download the DOMPurify library from @remote. @exception', [ '@remote' => $dompurify_library['remote'] . '/archive/main.zip', '@exception' => $e->getMessage(), ], 'error')); return; } // Move downloaded file. $fs->rename($destination, $path . '/DOMPurify.zip'); // Unzip the file. $zip = new \ZipArchive(); $res = $zip->open($path . '/DOMPurify.zip'); if ($res === TRUE) { $zip->extractTo($path); $zip->close(); } else { // Remove the directory if unzip fails and exit. $fs->remove($path); $this->logger()->error(dt('Error: unable to unzip DOMPurify file.', [], 'error')); return; } // Remove the downloaded zip file. $fs->remove($path . '/DOMPurify.zip'); // Move the dist directory. $fs->mirror($path . '/DOMPurify-main/dist', $path . '/dist', NULL, ['override' => TRUE]); $fs->remove($path . '/DOMPurify-main'); // Success. $this->logger()->notice(dt('The DOMPurify library has been successfully downloaded to @path.', [ '@path' => $path, ], 'success')); } else { $this->logger()->error(dt('Drush was unable to load the DOMPurify library')); } } }
src/Form/ColorboxSettingsForm.php +56 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ namespace Drupal\colorbox\Form; use Drupal\Core\Asset\LibraryDiscoveryInterface; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Form\ConfigFormBase; Loading @@ -21,6 +22,13 @@ class ColorboxSettingsForm extends ConfigFormBase { */ protected $extensionListModule; /** * Library discovery service. * * @var LibraryDiscoveryInterface */ protected $libraryDiscovery; /** * A state that represents the custom settings being enabled. */ Loading @@ -47,11 +55,17 @@ class ColorboxSettingsForm extends ConfigFormBase { * The module handler service. * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module * The list of available modules. * @param \Drupal\Core\Asset\LibraryDiscoveryInterface $libraryDiscovery * The library discovery service. */ public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $moduleHandler, ModuleExtensionList $extension_list_module) { public function __construct(ConfigFactoryInterface $config_factory, ModuleHandlerInterface $moduleHandler, ModuleExtensionList $extension_list_module, LibraryDiscoveryInterface $libraryDiscovery) { parent::__construct($config_factory); $this->moduleHandler = $moduleHandler; $this->extensionListModule = $extension_list_module; $this->libraryDiscovery = $libraryDiscovery; } /** Loading @@ -61,7 +75,8 @@ class ColorboxSettingsForm extends ConfigFormBase { return new static( $container->get('config.factory'), $container->get('module_handler'), $container->get('extension.list.module') $container->get('extension.list.module'), $container->get('library.discovery') ); } Loading Loading @@ -89,6 +104,44 @@ class ColorboxSettingsForm extends ConfigFormBase { $config = $this->configFactory->get('colorbox.settings'); $dompurify = $this->libraryDiscovery->getLibraryByName('colorbox', 'dompurify'); $dompurify_file = !empty($dompurify['js'][0]['data']) ? DRUPAL_ROOT . '/' . $dompurify['js'][0]['data'] : NULL; $dompurify_exists = !empty($dompurify) && !empty($dompurify_file) && file_exists($dompurify_file); $form['colorbox_dompurify'] = [ '#type' => 'details', '#title' => $this->t('DOMPurify Library'), '#open' => TRUE, ]; $dompurify_message = $dompurify_exists ? $this->t('The DOMPurify library is installed. ' . 'This library will sanitize HTML in Colorbox captions.') : $this->t('The <a href="@dompurify_link">DOMPurify</a> ' . 'library is not installed. ' . 'This library is necessary if you want to use HTML in Colorbox captions. ' . 'Without it, all captions will be treated as plain text.', [ '@dompurify_link' => 'https://github.com/cure53/DOMPurify/archive/main.zip' ]); $form['colorbox_dompurify']['dompurify_message'] = array( '#type' => 'markup', '#prefix' => '<p>', '#suffix' => '</p>', '#markup' => $dompurify_message, ); if (!$dompurify_exists) { $form['colorbox_dompurify']['dompurify_hide_warning'] = array( '#type' => 'checkbox', '#title' => t('Don\'t show warning on status report'), '#default_value' => $config->get('dompurify_hide_warning'), '#description' => t('By default, a warning appears on Drupal\'s ' . 'status report if this library is missing. Check this box to ' . 'suppress the warning.'), ); } $form['colorbox_custom_settings'] = [ '#type' => 'details', '#title' => $this->t('Styles and options'), Loading Loading @@ -370,6 +423,7 @@ class ColorboxSettingsForm extends ConfigFormBase { $config = $this->configFactory->getEditable('colorbox.settings'); $config ->set('dompurify_hide_warning', $form_state->getValue('dompurify_hide_warning')) ->set('custom.style', $form_state->getValue('colorbox_style')) ->set('custom.activate', $form_state->getValue('colorbox_custom_settings_activate')) ->set('custom.transition_type', $form_state->getValue('colorbox_transition_type')) Loading