Skip to content

Commit 809e398

Browse files
author
Jen Lampton
committed
Issue #3262686: Add the DOMPurify library for HTML in captions.
1 parent d3224b8 commit 809e398

17 files changed

+5342
-82
lines changed

README.md

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,25 @@ Installation
2828
- Install this module using the official Backdrop CMS instructions at
2929
https://backdropcms.org/user-guide/modules
3030

31-
- Visit the configuration page under Administration > Configuration > Media >
32-
Colorbox (admin/config/media/colorbox) and configure as necessary.
31+
- Configure your image fields or views to display images in colorboxes.
3332

33+
- (Optional) Visit the configuration page under Administration > Configuration >
34+
Media > Colorbox (admin/config/media/colorbox) and configure as necessary.
3435

35-
Documentation
36-
-------------
3736

38-
Documentation is located in the Wiki:
39-
https://github.com/backdrop-contrib/colorbox/wiki/Documentation
37+
Differences from Drupal
38+
-----------------------
39+
40+
- If you would like to use HTML tags in colorbox captions, you will need to enable
41+
the new setting `Allow HTML in Colorbox captions`. This configuration will use
42+
the DOMpurify library for sanitization. Please note: **The DOMpurify library
43+
has several dependencies with security issues.** It is unknown whether the
44+
colorbox use of DOMpurify could introduce a vulnerablity to your site. For
45+
this reason it is recommend to leave this setting disabled.
46+
- The Backdrop version of Colorbox module does not require that you download or
47+
install the Color library separately.
48+
- The Backdrop version of Colorbox module does not require that you download or
49+
install the DomPurify library separately.
4050

4151

4252
Current Maintainers
@@ -50,6 +60,7 @@ Credits
5060
-------
5161

5262
- Ported to Backdrop by [Andy Martha](https://github.com/biolithic)
63+
- Drupal module maintainer [Paul McKibben](https://www.drupal.org/u/paulmckibben)
5364
- Drupal module maintainer [Fredrik Jonsson](https://drupal.org/user/5546)
5465
- Drupal module maintainer [Sam Becker](https://www.drupal.org/u/sam152)
5566
- Drupal module maintainer [Andrii Podanenko](https://www.drupal.org/u/podarok)
@@ -58,8 +69,10 @@ Credits
5869
- The [Colorbox jQuery library](http://www.jacklmoore.com)
5970

6071

61-
License
62-
-------
72+
Licenses
73+
--------
6374

64-
This project is GPL v2 software. See the LICENSE.txt file in this directory for
65-
complete text.
75+
* This project is GPL v2 software. See the LICENSE.txt file in this directory
76+
for complete text.
77+
* The Colorbox jQuery library is released under the [MIT License](https://opensource.org/licenses/mit-license.php).
78+
* The DOMpurify library is released under [a dual license of Apache-2.0 and MPL-2.0](https://github.com/cure53/DOMPurify/blob/main/LICENSE).

colorbox.admin.inc

Lines changed: 97 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,43 @@
88
* General configuration form for controlling the colorbox behaviour.
99
*/
1010
function colorbox_admin_settings() {
11-
$colorbox_path = backdrop_get_path('module', 'colorbox') . '/libraries/colorbox';
12-
$colorbox_styles = array(
13-
'default' => t('Default'),
14-
'plain' => t('Plain (mainly for images)'),
15-
'stockholmsyndrome' => t('Stockholm Syndrome'),
16-
$colorbox_path . '/example1' => t('Example 1'),
17-
$colorbox_path . '/example2' => t('Example 2'),
18-
$colorbox_path . '/example3' => t('Example 3'),
19-
$colorbox_path . '/example4' => t('Example 4'),
20-
$colorbox_path . '/example5' => t('Example 5'),
21-
'none' => t('None'),
11+
$module_path = backdrop_get_path('module', 'colorbox');
12+
$colorbox_path = $module_path . '/libraries/colorbox';
13+
backdrop_add_js($module_path . '/js/colorbox_admin_settings.js', array('preprocess' => FALSE));
14+
15+
$form['colorbox_extra_features'] = array(
16+
'#type' => 'fieldset',
17+
'#title' => t('Extra features'),
2218
);
23-
$form['colorbox_style'] = array(
24-
'#type' => 'select',
25-
'#title' => t('Colorbox style'),
26-
'#options' => $colorbox_styles,
27-
'#default_value' => config_get('colorbox.settings', 'colorbox_style'),
28-
'#description' => t('Select "None" if Colorbox styles are provided by your theme.'),
19+
$form['colorbox_extra_features']['colorbox_load'] = array(
20+
'#type' => 'checkbox',
21+
'#title' => t('Enable Colorbox load'),
22+
'#default_value' => config_get('colorbox.settings', 'colorbox_load'),
23+
'#description' => t('This enables custom links that can open forms and paths in a Colorbox. Add the class "colorbox-load" to the link and build the url like this for paths "[path]?width=500&height=500&iframe=true" or "[path]?width=500&height=500" if you don\'t want an iframe. Other modules may activate this for easy Colorbox integration.'),
24+
);
25+
$form['colorbox_extra_features']['colorbox_inline'] = array(
26+
'#type' => 'checkbox',
27+
'#title' => t('Enable Colorbox inline'),
28+
'#default_value' => config_get('colorbox.settings', 'colorbox_inline'),
29+
'#description' => t('This enables custom links that can open inline content in a Colorbox. Add the class "colorbox-inline" to the link and build the url like this "?width=500&height=500&inline=true#id-of-content". Other modules may activate this for easy Colorbox integration.'),
30+
);
31+
32+
$form['colorbox_dompurify'] = array(
33+
'#type' => 'fieldset',
34+
'#title' => t('HTML Captions'),
35+
'#description' => t('The <a href="!dompurify_link">DOMPurify</a> ' .
36+
'library is necessary if you want to use HTML in Colorbox captions. ' .
37+
'Without it, all captions will be treated as plain text.',
38+
array(
39+
'!dompurify_link' => 'https://github.com/cure53/DOMPurify',
40+
)
41+
),
42+
);
43+
$form['colorbox_dompurify']['colorbox_dompurify_include'] = array(
44+
'#type' => 'checkbox',
45+
'#title' => t('Allow HTML in Colorbox captions'),
46+
'#default_value' => config_get('colorbox.settings', 'colorbox_dompurify_include'),
47+
'#description' => t('This setting will add the DOMPurity library.'),
2948
);
3049

3150
if (module_exists('insert')) {
@@ -51,24 +70,44 @@ function colorbox_admin_settings() {
5170
);
5271
}
5372

54-
$form['colorbox_custom_settings_activate'] = array(
55-
'#type' => 'radios',
56-
'#title' => t('Colorbox custom options'),
57-
'#options' => array(
58-
0 => t('Disabled'),
59-
1 => t('Enabled'),
60-
),
61-
'#default_value' => config_get('colorbox.settings', 'colorbox_custom_settings_activate'),
62-
);
6373
$form['colorbox_custom_settings'] = array(
6474
'#type' => 'fieldset',
65-
'#title' => t('Colorbox custom options'),
66-
'#states' => array(
67-
'visible' => array(
68-
':input[name="colorbox_custom_settings_activate"]' => array('value' => '1'),
69-
),
70-
),
75+
'#title' => t('Styles and options'),
76+
);
77+
$colorbox_styles = array(
78+
'default' => t('Default'),
79+
'plain' => t('Plain (mainly for images)'),
80+
'stockholmsyndrome' => t('Stockholm Syndrome'),
81+
$library_colorbox['library path'] . '/example1' => t('Example 1'),
82+
$library_colorbox['library path'] . '/example2' => t('Example 2'),
83+
$library_colorbox['library path'] . '/example3' => t('Example 3'),
84+
$library_colorbox['library path'] . '/example4' => t('Example 4'),
85+
$library_colorbox['library path'] . '/example5' => t('Example 5'),
86+
'none' => t('None'),
87+
);
88+
$form['colorbox_custom_settings']['colorbox_style'] = array(
89+
'#type' => 'select',
90+
'#title' => t('Style'),
91+
'#options' => $colorbox_styles,
92+
'#default_value' => config_get('colorbox.settings', 'colorbox_style'),
93+
'#description' => t('Select "None" if Colorbox styles are provided by your theme.'),
94+
);
95+
96+
$colorbox_custom_settings_activate = config_get('colorbox.settings', 'colorbox_custom_settings_activate');
97+
$form['colorbox_custom_settings']['colorbox_custom_settings_activate'] = array(
98+
'#type' => 'radios',
99+
'#title' => t('Colorbox options'),
100+
'#options' => array(0 => t('Use default options'), 1 => t('Use custom options')),
101+
'#default_value' => $colorbox_custom_settings_activate,
102+
'#prefix' => '<div class="colorbox-custom-settings-activate">',
103+
'#suffix' => '</div>',
104+
);
105+
106+
$js_hide_activate = $colorbox_custom_settings_activate ? '' : ' js-hide';
107+
$form['colorbox_custom_settings']['wrapper_start'] = array(
108+
'#markup' => '<div class="colorbox-custom-settings' . $js_hide_activate . '">',
71109
);
110+
72111
$form['colorbox_custom_settings']['colorbox_transition_type'] = array(
73112
'#type' => 'radios',
74113
'#title' => t('Transition type'),
@@ -200,6 +239,7 @@ function colorbox_admin_settings() {
200239
'#default_value' => config_get('colorbox.settings', 'colorbox_fixed'),
201240
'#description' => t('If the Colorbox should be displayed in a fixed position within the visitor\'s viewport or relative to the document.'),
202241
);
242+
203243
$form['colorbox_custom_settings']['colorbox_scrolling'] = array(
204244
'#type' => 'radios',
205245
'#title' => t('Scrollbars'),
@@ -208,31 +248,33 @@ function colorbox_admin_settings() {
208248
'#description' => t('If set to Off, Colorbox will hide scrollbars for overflowing content. This could be used in conjunction with the resize method for a smoother transition if you are appending content to an already open instance of Colorbox.'),
209249
);
210250

211-
$form['colorbox_slideshow'] = array(
251+
$form['colorbox_custom_settings']['colorbox_slideshow_settings'] = array(
252+
'#type' => 'fieldset',
253+
'#title' => t('Slideshow settings'),
254+
'#collapsible' => TRUE,
255+
'#collapsed' => TRUE,
256+
);
257+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshow'] = array(
212258
'#type' => 'radios',
213-
'#title' => t('Automatic Slideshow'),
214-
'#options' => array(
215-
0 => t('Off'),
216-
1 => t('On'),
217-
),
259+
'#title' => t('Slideshow'),
260+
'#options' => array(0 => t('Off'), 1 => t('On')),
218261
'#default_value' => config_get('colorbox.settings', 'colorbox_slideshow'),
219262
'#description' => t('An automatic slideshow to a content group / gallery.'),
263+
'#prefix' => '<div class="colorbox-slideshow-settings-activate">',
264+
'#suffix' => '</div>',
220265
);
221-
$form['colorbox_slideshow_settings'] = array(
222-
'#type' => 'fieldset',
223-
'#title' => t('Slideshow settings'),
224-
'#states' => array(
225-
'visible' => array(
226-
':input[name="colorbox_slideshow"]' => array('value' => '1'),
227-
),
228-
),
266+
267+
$js_hide_slideshow = config_get('colorbox.settings', 'colorbox_slideshow') ? '' : ' js-hide';
268+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['wrapper_start'] = array(
269+
'#markup' => '<div class="colorbox-slideshow-settings' . $js_hide_slideshow . '">',
229270
);
230-
$form['colorbox_slideshow_settings']['colorbox_slideshowauto'] = array(
271+
272+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshowauto'] = array(
231273
'#type' => 'checkbox',
232274
'#title' => t('Automatically start to play the slideshow'),
233275
'#default_value' => config_get('colorbox.settings', 'colorbox_slideshowauto'),
234276
);
235-
$form['colorbox_slideshow_settings']['colorbox_slideshowspeed'] = array(
277+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_slideshowspeed'] = array(
236278
'#type' => 'select',
237279
'#title' => t('Slideshow speed'),
238280
'#field_suffix' => t('milliseconds'),
@@ -251,34 +293,25 @@ function colorbox_admin_settings() {
251293
)),
252294
'#default_value' => config_get('colorbox.settings', 'colorbox_slideshowspeed'),
253295
);
254-
$form['colorbox_slideshow_settings']['colorbox_text_start'] = array(
296+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_text_start'] = array(
255297
'#type' => 'textfield',
256298
'#title' => t('Start button text'),
257299
'#default_value' => config_get('colorbox.settings', 'colorbox_text_start'),
258300
'#size' => 30,
259301
);
260-
$form['colorbox_slideshow_settings']['colorbox_text_stop'] = array(
302+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['colorbox_text_stop'] = array(
261303
'#type' => 'textfield',
262304
'#title' => t('Stop button text'),
263305
'#default_value' => config_get('colorbox.settings', 'colorbox_text_stop'),
264306
'#size' => 30,
265307
);
266308

267-
$form['colorbox_extra_features'] = array(
268-
'#type' => 'fieldset',
269-
'#title' => t('Extra features'),
309+
$form['colorbox_custom_settings']['colorbox_slideshow_settings']['wrapper_stop'] = array(
310+
'#markup' => '</div>',
270311
);
271-
$form['colorbox_extra_features']['colorbox_load'] = array(
272-
'#type' => 'checkbox',
273-
'#title' => t('Enable Colorbox load'),
274-
'#default_value' => config_get('colorbox.settings', 'colorbox_load'),
275-
'#description' => t('This enables custom links that can open forms and paths in a Colorbox. Add the class "colorbox-load" to the link and build the url like this for paths "[path]?width=500&height=500&iframe=true" or "[path]?width=500&height=500" if you don\'t want an iframe. Other modules may activate this for easy Colorbox integration.'),
276-
);
277-
$form['colorbox_extra_features']['colorbox_inline'] = array(
278-
'#type' => 'checkbox',
279-
'#title' => t('Enable Colorbox inline'),
280-
'#default_value' => config_get('colorbox.settings', 'colorbox_inline'),
281-
'#description' => t('This enables custom links that can open inline content in a Colorbox. Add the class "colorbox-inline" to the link and build the url like this "?width=500&height=500&inline=true#id-of-content". Other modules may activate this for easy Colorbox integration.'),
312+
313+
$form['colorbox_custom_settings']['wrapper_stop'] = array(
314+
'#markup' => '</div>',
282315
);
283316

284317
$form['colorbox_advanced_settings'] = array(

colorbox.module

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ function colorbox_library_info() {
105105
backdrop_get_path('module', 'colorbox') . '/libraries/colorbox/jquery.colorbox.js' => array(),
106106
),
107107
);
108+
$libraries['DOMPurify'] = array(
109+
'title' => 'DOMPurify',
110+
'website' => 'https://github.com/cure53/DOMPurify',
111+
'version' => '2.3.6',
112+
'js' => array(
113+
backdrop_get_path('module', 'colorbox') . '/libraries/DOMPurify/purify.min.js',
114+
),
115+
);
116+
$libraries['DOMPurify-source'] = array(
117+
'title' => 'DOMPurify',
118+
'website' => 'https://github.com/cure53/DOMPurify',
119+
'version' => '2.3.6',
120+
'js' => array(
121+
backdrop_get_path('module', 'colorbox') . '/libraries/DOMPurify/purify.js',
122+
),
123+
);
108124

109125
return $libraries;
110126
}
@@ -220,13 +236,20 @@ function _colorbox_doheader() {
220236

221237
backdrop_add_js(array('colorbox' => $js_settings), array('type' => 'setting', 'scope' => JS_DEFAULT));
222238

223-
// Add and initialise the Colorbox plugin.
239+
// Add and initialize the Colorbox and DOMPurify libraries.
224240
$variant = config_get('colorbox.settings', 'colorbox_compression_type');
241+
$dompurify = config_get('colorbox.settings', 'colorbox_dompurify_include');
225242
if ($variant == 'minified') {
226243
backdrop_add_library('colorbox', 'colorbox');
244+
if ($dompurify) {
245+
backdrop_add_library('colorbox', 'DOMPurify');
246+
}
227247
}
228248
elseif ($variant == 'source') {
229249
backdrop_add_library('colorbox', 'colorbox-source');
250+
if ($dompurify) {
251+
backdrop_add_library('colorbox', 'DOMPurify-source');
252+
}
230253
}
231254

232255
backdrop_add_js($path . '/js/colorbox.js');

js/colorbox.js

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Backdrop.behaviors.initColorbox = {
3939
// If a title attribute is supplied, sanitize it.
4040
var title = $(this).attr('title');
4141
if (title) {
42-
extendParams.title = Backdrop.checkPlain(title);
42+
extendParams.title = Backdrop.colorbox.sanitizeMarkup(title);
4343
}
4444
$(this).colorbox($.extend({}, settings.colorbox, extendParams));
4545
});
@@ -50,4 +50,49 @@ Backdrop.behaviors.initColorbox = {
5050
}
5151
};
5252

53+
// Create colorbox namespace if it doesn't exist.
54+
if (!Backdrop.hasOwnProperty('colorbox')) {
55+
Backdrop.colorbox = {};
56+
}
57+
58+
/**
59+
* Global function to allow sanitizing captions and control strings.
60+
*
61+
* @param markup
62+
* String containing potential markup.
63+
* @return @string
64+
* Sanitized string with potentially dangerous markup removed.
65+
*/
66+
Backdrop.colorbox.sanitizeMarkup = function(markup) {
67+
// If DOMPurify installed, allow some HTML. Otherwise, treat as plain text.
68+
if (typeof DOMPurify !== 'undefined') {
69+
var purifyConfig = {
70+
ALLOWED_TAGS: [
71+
'a',
72+
'b',
73+
'strong',
74+
'i',
75+
'em',
76+
'u',
77+
'cite',
78+
'code',
79+
'br'
80+
],
81+
ALLOWED_ATTR: [
82+
'href',
83+
'hreflang',
84+
'title',
85+
'target'
86+
]
87+
}
88+
if (Backdrop.settings.hasOwnProperty('dompurify_custom_config')) {
89+
purifyConfig = Backdrop.settings.dompurify_custom_config;
90+
}
91+
return DOMPurify.sanitize(markup, purifyConfig);
92+
}
93+
else {
94+
return Backdrop.checkPlain(markup);
95+
}
96+
}
97+
5398
})(jQuery);

js/colorbox_admin_settings.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ Backdrop.behaviors.initColorboxAdminSettings = {
1010

1111
$('div.colorbox-custom-settings-activate input.form-radio', context).click(function () {
1212
if (this.value == 1) {
13+
console.log('show');
1314
$('div.colorbox-custom-settings', context).show();
1415
}
1516
else {
17+
console.log('hide');
1618
$('div.colorbox-custom-settings', context).hide();
1719
}
1820
});

0 commit comments

Comments
 (0)