Update core 8.3.0
This commit is contained in:
parent
da7a7918f8
commit
cd7a898e66
6144 changed files with 132297 additions and 87747 deletions
|
@ -27,77 +27,77 @@ use Drupal\editor\Entity\Editor;
|
|||
function editor_image_upload_settings_form(Editor $editor) {
|
||||
// Defaults.
|
||||
$image_upload = $editor->getImageUploadSettings();
|
||||
$image_upload += array(
|
||||
$image_upload += [
|
||||
'status' => FALSE,
|
||||
'scheme' => file_default_scheme(),
|
||||
'directory' => 'inline-images',
|
||||
'max_size' => '',
|
||||
'max_dimensions' => array('width' => '', 'height' => ''),
|
||||
);
|
||||
'max_dimensions' => ['width' => '', 'height' => ''],
|
||||
];
|
||||
|
||||
$form['status'] = array(
|
||||
$form['status'] = [
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Enable image uploads'),
|
||||
'#default_value' => $image_upload['status'],
|
||||
'#attributes' => array(
|
||||
'#attributes' => [
|
||||
'data-editor-image-upload' => 'status',
|
||||
),
|
||||
);
|
||||
$show_if_image_uploads_enabled = array(
|
||||
'visible' => array(
|
||||
':input[data-editor-image-upload="status"]' => array('checked' => TRUE),
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
$show_if_image_uploads_enabled = [
|
||||
'visible' => [
|
||||
':input[data-editor-image-upload="status"]' => ['checked' => TRUE],
|
||||
],
|
||||
];
|
||||
|
||||
// Any visible, writable wrapper can potentially be used for uploads,
|
||||
// including a remote file system that integrates with a CDN.
|
||||
$options = \Drupal::service('stream_wrapper_manager')->getDescriptions(StreamWrapperInterface::WRITE_VISIBLE);
|
||||
if (!empty($options)) {
|
||||
$form['scheme'] = array(
|
||||
$form['scheme'] = [
|
||||
'#type' => 'radios',
|
||||
'#title' => t('File storage'),
|
||||
'#default_value' => $image_upload['scheme'],
|
||||
'#options' => $options,
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
'#access' => count($options) > 1,
|
||||
);
|
||||
];
|
||||
}
|
||||
// Set data- attributes with human-readable names for all possible stream
|
||||
// wrappers, so that drupal.ckeditor.drupalimage.admin's summary rendering
|
||||
// can use that.
|
||||
foreach (\Drupal::service('stream_wrapper_manager')->getNames(StreamWrapperInterface::WRITE_VISIBLE) as $scheme => $name) {
|
||||
$form['scheme'][$scheme]['#attributes']['data-label'] = t('Storage: @name', array('@name' => $name));
|
||||
$form['scheme'][$scheme]['#attributes']['data-label'] = t('Storage: @name', ['@name' => $name]);
|
||||
}
|
||||
|
||||
$form['directory'] = array(
|
||||
$form['directory'] = [
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $image_upload['directory'],
|
||||
'#title' => t('Upload directory'),
|
||||
'#description' => t("A directory relative to Drupal's files directory where uploaded images will be stored."),
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
);
|
||||
];
|
||||
|
||||
$default_max_size = format_size(file_upload_max_size());
|
||||
$form['max_size'] = array(
|
||||
$form['max_size'] = [
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => $image_upload['max_size'],
|
||||
'#title' => t('Maximum file size'),
|
||||
'#description' => t('If this is left empty, then the file size will be limited by the PHP maximum upload size of @size.', array('@size' => $default_max_size)),
|
||||
'#description' => t('If this is left empty, then the file size will be limited by the PHP maximum upload size of @size.', ['@size' => $default_max_size]),
|
||||
'#maxlength' => 20,
|
||||
'#size' => 10,
|
||||
'#placeholder' => $default_max_size,
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
);
|
||||
];
|
||||
|
||||
$form['max_dimensions'] = array(
|
||||
$form['max_dimensions'] = [
|
||||
'#type' => 'item',
|
||||
'#title' => t('Maximum dimensions'),
|
||||
'#field_prefix' => '<div class="container-inline clearfix">',
|
||||
'#field_suffix' => '</div>',
|
||||
'#description' => t('Images larger than these dimensions will be scaled down.'),
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
);
|
||||
$form['max_dimensions']['width'] = array(
|
||||
];
|
||||
$form['max_dimensions']['width'] = [
|
||||
'#title' => t('Width'),
|
||||
'#title_display' => 'invisible',
|
||||
'#type' => 'number',
|
||||
|
@ -109,8 +109,8 @@ function editor_image_upload_settings_form(Editor $editor) {
|
|||
'#placeholder' => t('width'),
|
||||
'#field_suffix' => ' x ',
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
);
|
||||
$form['max_dimensions']['height'] = array(
|
||||
];
|
||||
$form['max_dimensions']['height'] = [
|
||||
'#title' => t('Height'),
|
||||
'#title_display' => 'invisible',
|
||||
'#type' => 'number',
|
||||
|
@ -122,7 +122,7 @@ function editor_image_upload_settings_form(Editor $editor) {
|
|||
'#placeholder' => t('height'),
|
||||
'#field_suffix' => t('pixels'),
|
||||
'#states' => $show_if_image_uploads_enabled,
|
||||
);
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ function hook_editor_info_alter(array &$editors) {
|
|||
function hook_editor_js_settings_alter(array &$settings) {
|
||||
if (isset($settings['editor']['formats']['basic_html'])) {
|
||||
$settings['editor']['formats']['basic_html']['editor'] = 'MyDifferentEditor';
|
||||
$settings['editor']['formats']['basic_html']['editorSettings']['buttons'] = array('strong', 'italic', 'underline');
|
||||
$settings['editor']['formats']['basic_html']['editorSettings']['buttons'] = ['strong', 'italic', 'underline'];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ function editor_help($route_name, RouteMatchInterface $route_match) {
|
|||
case 'help.page.editor':
|
||||
$output = '';
|
||||
$output .= '<h3>' . t('About') . '</h3>';
|
||||
$output .= '<p>' . t('The Text Editor module provides a framework that other modules (such as <a href=":ckeditor">CKEditor module</a>) can use to provide toolbars and other functionality that allow users to format text more easily than typing HTML tags directly. For more information, see the <a href=":documentation">online documentation for the Text Editor module</a>.', array(':documentation' => 'https://www.drupal.org/documentation/modules/editor', ':ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', array('name' => 'ckeditor')) : '#')) . '</p>';
|
||||
$output .= '<p>' . t('The Text Editor module provides a framework that other modules (such as <a href=":ckeditor">CKEditor module</a>) can use to provide toolbars and other functionality that allow users to format text more easily than typing HTML tags directly. For more information, see the <a href=":documentation">online documentation for the Text Editor module</a>.', [':documentation' => 'https://www.drupal.org/documentation/modules/editor', ':ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', ['name' => 'ckeditor']) : '#']) . '</p>';
|
||||
$output .= '<h3>' . t('Uses') . '</h3>';
|
||||
$output .= '<dl>';
|
||||
$output .= '<dt>' . t('Installing text editors') . '</dt>';
|
||||
$output .= '<dd>' . t('The Text Editor module provides a framework for managing editors. To use it, you also need to enable a text editor. This can either be the core <a href=":ckeditor">CKEditor module</a>, which can be enabled on the <a href=":extend">Extend page</a>, or a contributed module for any other text editor. When installing a contributed text editor module, be sure to check the installation instructions, because you will most likely need to download and install an external library as well as the Drupal module.', array(':ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', array('name' => 'ckeditor')) : '#', ':extend' => \Drupal::url('system.modules_list'))) . '</dd>';
|
||||
$output .= '<dd>' . t('The Text Editor module provides a framework for managing editors. To use it, you also need to enable a text editor. This can either be the core <a href=":ckeditor">CKEditor module</a>, which can be enabled on the <a href=":extend">Extend page</a>, or a contributed module for any other text editor. When installing a contributed text editor module, be sure to check the installation instructions, because you will most likely need to download and install an external library as well as the Drupal module.', [':ckeditor' => (\Drupal::moduleHandler()->moduleExists('ckeditor')) ? \Drupal::url('help.page', ['name' => 'ckeditor']) : '#', ':extend' => \Drupal::url('system.modules_list')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Enabling a text editor for a text format') . '</dt>';
|
||||
$output .= '<dd>' . t('On the <a href=":formats">Text formats and editors page</a> you can see which text editor is associated with each text format. You can change this by clicking on the <em>Configure</em> link, and then choosing a text editor or <em>none</em> from the <em>Text editor</em> drop-down list. The text editor will then be displayed with any text field for which this text format is chosen.', array(':formats' => \Drupal::url('filter.admin_overview'))) . '</dd>';
|
||||
$output .= '<dd>' . t('On the <a href=":formats">Text formats and editors page</a> you can see which text editor is associated with each text format. You can change this by clicking on the <em>Configure</em> link, and then choosing a text editor or <em>none</em> from the <em>Text editor</em> drop-down list. The text editor will then be displayed with any text field for which this text format is chosen.', [':formats' => \Drupal::url('filter.admin_overview')]) . '</dd>';
|
||||
$output .= '<dt>' . t('Configuring a text editor') . '</dt>';
|
||||
$output .= '<dd>' . t('Once a text editor is associated with a text format, you can configure it by clicking on the <em>Configure</em> link for this format. Depending on the specific text editor, you can configure it for example by adding buttons to its toolbar. Typically these buttons provide formatting or editing tools, and they often insert HTML tags into the field source. For details, see the help page of the specific text editor.') . '</dd>';
|
||||
$output .= '<dt>' . t('Using different text editors and formats') . '</dt>';
|
||||
|
@ -86,7 +86,7 @@ function editor_form_filter_admin_overview_alter(&$form, FormStateInterface $for
|
|||
// @todo Cleanup column injection: https://www.drupal.org/node/1876718.
|
||||
// Splice in the column for "Text editor" into the header.
|
||||
$position = array_search('name', $form['formats']['#header']) + 1;
|
||||
$start = array_splice($form['formats']['#header'], 0, $position, array('editor' => t('Text editor')));
|
||||
$start = array_splice($form['formats']['#header'], 0, $position, ['editor' => t('Text editor')]);
|
||||
$form['formats']['#header'] = array_merge($start, $form['formats']['#header']);
|
||||
|
||||
// Then splice in the name of each text editor for each text format.
|
||||
|
@ -94,7 +94,7 @@ function editor_form_filter_admin_overview_alter(&$form, FormStateInterface $for
|
|||
foreach (Element::children($form['formats']) as $format_id) {
|
||||
$editor = editor_load($format_id);
|
||||
$editor_name = ($editor && isset($editors[$editor->getEditor()])) ? $editors[$editor->getEditor()]['label'] : '—';
|
||||
$editor_column['editor'] = array('#markup' => $editor_name);
|
||||
$editor_column['editor'] = ['#markup' => $editor_name];
|
||||
$position = array_search('name', array_keys($form['formats'][$format_id])) + 1;
|
||||
$start = array_splice($form['formats'][$format_id], 0, $position, $editor_column);
|
||||
$form['formats'][$format_id] = array_merge($start, $form['formats'][$format_id]);
|
||||
|
@ -116,37 +116,37 @@ function editor_form_filter_format_form_alter(&$form, FormStateInterface $form_s
|
|||
// Associate a text editor with this text format.
|
||||
$manager = \Drupal::service('plugin.manager.editor');
|
||||
$editor_options = $manager->listOptions();
|
||||
$form['editor'] = array(
|
||||
$form['editor'] = [
|
||||
// Position the editor selection before the filter settings (weight of 0),
|
||||
// but after the filter label and name (weight of -20).
|
||||
'#weight' => -9,
|
||||
);
|
||||
$form['editor']['editor'] = array(
|
||||
];
|
||||
$form['editor']['editor'] = [
|
||||
'#type' => 'select',
|
||||
'#title' => t('Text editor'),
|
||||
'#options' => $editor_options,
|
||||
'#empty_option' => t('None'),
|
||||
'#default_value' => $editor ? $editor->getEditor() : '',
|
||||
'#ajax' => array(
|
||||
'trigger_as' => array('name' => 'editor_configure'),
|
||||
'#ajax' => [
|
||||
'trigger_as' => ['name' => 'editor_configure'],
|
||||
'callback' => 'editor_form_filter_admin_form_ajax',
|
||||
'wrapper' => 'editor-settings-wrapper',
|
||||
),
|
||||
],
|
||||
'#weight' => -10,
|
||||
);
|
||||
$form['editor']['configure'] = array(
|
||||
];
|
||||
$form['editor']['configure'] = [
|
||||
'#type' => 'submit',
|
||||
'#name' => 'editor_configure',
|
||||
'#value' => t('Configure'),
|
||||
'#limit_validation_errors' => array(array('editor')),
|
||||
'#submit' => array('editor_form_filter_admin_format_editor_configure'),
|
||||
'#ajax' => array(
|
||||
'#limit_validation_errors' => [['editor']],
|
||||
'#submit' => ['editor_form_filter_admin_format_editor_configure'],
|
||||
'#ajax' => [
|
||||
'callback' => 'editor_form_filter_admin_form_ajax',
|
||||
'wrapper' => 'editor-settings-wrapper',
|
||||
),
|
||||
],
|
||||
'#weight' => -10,
|
||||
'#attributes' => array('class' => array('js-hide')),
|
||||
);
|
||||
'#attributes' => ['class' => ['js-hide']],
|
||||
];
|
||||
|
||||
// If there aren't any options (other than "None"), disable the select list.
|
||||
if (empty($editor_options)) {
|
||||
|
@ -154,26 +154,27 @@ function editor_form_filter_format_form_alter(&$form, FormStateInterface $form_s
|
|||
$form['editor']['editor']['#description'] = t('This option is disabled because no modules that provide a text editor are currently enabled.');
|
||||
}
|
||||
|
||||
$form['editor']['settings'] = array(
|
||||
$form['editor']['settings'] = [
|
||||
'#tree' => TRUE,
|
||||
'#weight' => -8,
|
||||
'#type' => 'container',
|
||||
'#id' => 'editor-settings-wrapper',
|
||||
'#attached' => array(
|
||||
'library' => array(
|
||||
'#attached' => [
|
||||
'library' => [
|
||||
'editor/drupal.editor.admin',
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Add editor-specific validation and submit handlers.
|
||||
if ($editor) {
|
||||
/** @var $plugin \Drupal\editor\Plugin\EditorPluginInterface */
|
||||
$plugin = $manager->createInstance($editor->getEditor());
|
||||
$settings_form = array();
|
||||
$settings_form['#element_validate'][] = array($plugin, 'settingsFormValidate');
|
||||
$form['editor']['settings']['subform'] = $plugin->settingsForm($settings_form, $form_state, $editor);
|
||||
$form['editor']['settings']['subform']['#parents'] = array('editor', 'settings');
|
||||
$form['actions']['submit']['#submit'][] = array($plugin, 'settingsFormSubmit');
|
||||
$settings_form = [];
|
||||
$settings_form['#element_validate'][] = [$plugin, 'validateConfigurationForm'];
|
||||
$form['editor']['settings']['subform'] = $plugin->buildConfigurationForm($settings_form, $form_state);
|
||||
$form['editor']['settings']['subform']['#parents'] = ['editor', 'settings'];
|
||||
$form['actions']['submit']['#submit'][] = [$plugin, 'submitConfigurationForm'];
|
||||
}
|
||||
|
||||
$form['#validate'][] = 'editor_form_filter_admin_format_validate';
|
||||
|
@ -185,7 +186,7 @@ function editor_form_filter_format_form_alter(&$form, FormStateInterface $form_s
|
|||
*/
|
||||
function editor_form_filter_admin_format_editor_configure($form, FormStateInterface $form_state) {
|
||||
$editor = $form_state->get('editor');
|
||||
$editor_value = $form_state->getValue(array('editor', 'editor'));
|
||||
$editor_value = $form_state->getValue(['editor', 'editor']);
|
||||
if ($editor_value !== NULL) {
|
||||
if ($editor_value === '') {
|
||||
$form_state->set('editor', FALSE);
|
||||
|
@ -235,7 +236,7 @@ function editor_form_filter_admin_format_submit($form, FormStateInterface $form_
|
|||
$format = $form_state->getFormObject()->getEntity();
|
||||
$format_id = $format->isNew() ? NULL : $format->id();
|
||||
$original_editor = editor_load($format_id);
|
||||
if ($original_editor && $original_editor->getEditor() != $form_state->getValue(array('editor', 'editor'))) {
|
||||
if ($original_editor && $original_editor->getEditor() != $form_state->getValue(['editor', 'editor'])) {
|
||||
$original_editor->delete();
|
||||
}
|
||||
|
||||
|
@ -549,7 +550,7 @@ function editor_file_download($uri) {
|
|||
* An array of file entity UUIDs.
|
||||
*/
|
||||
function _editor_get_file_uuids_by_field(EntityInterface $entity) {
|
||||
$uuids = array();
|
||||
$uuids = [];
|
||||
|
||||
$formatted_text_fields = _editor_get_formatted_text_fields($entity);
|
||||
foreach ($formatted_text_fields as $formatted_text_field) {
|
||||
|
@ -578,12 +579,12 @@ function _editor_get_file_uuids_by_field(EntityInterface $entity) {
|
|||
function _editor_get_formatted_text_fields(FieldableEntityInterface $entity) {
|
||||
$field_definitions = $entity->getFieldDefinitions();
|
||||
if (empty($field_definitions)) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
// Only return formatted text fields.
|
||||
return array_keys(array_filter($field_definitions, function (FieldDefinitionInterface $definition) {
|
||||
return in_array($definition->getType(), array('text', 'text_long', 'text_with_summary'), TRUE);
|
||||
return in_array($definition->getType(), ['text', 'text_long', 'text_with_summary'], TRUE);
|
||||
}));
|
||||
}
|
||||
|
||||
|
@ -600,7 +601,7 @@ function _editor_get_formatted_text_fields(FieldableEntityInterface $entity) {
|
|||
function _editor_parse_file_uuids($text) {
|
||||
$dom = Html::load($text);
|
||||
$xpath = new \DOMXPath($dom);
|
||||
$uuids = array();
|
||||
$uuids = [];
|
||||
foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid]') as $node) {
|
||||
$uuids[] = $node->getAttribute('data-entity-uuid');
|
||||
}
|
||||
|
|
|
@ -5,17 +5,8 @@
|
|||
* Post update functions for Editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @addtogroup updates-8.2.x
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Clear the render cache to fix file references added by Editor.
|
||||
*/
|
||||
function editor_post_update_clear_cache_for_file_reference_filter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "addtogroup updates-8.2.x".
|
||||
*/
|
||||
|
|
|
@ -33,10 +33,10 @@ class EditorDialogSave implements CommandInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function render() {
|
||||
return array(
|
||||
return [
|
||||
'command' => 'editorDialogSave',
|
||||
'values' => $this->values,
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class EditorController extends ControllerBase {
|
|||
|
||||
// Direct text editing is only supported for single-valued fields.
|
||||
$field = $entity->getTranslation($langcode)->$field_name;
|
||||
$editable_text = check_markup($field->value, $field->format, $langcode, array(FilterInterface::TYPE_TRANSFORM_REVERSIBLE, FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE));
|
||||
$editable_text = check_markup($field->value, $field->format, $langcode, [FilterInterface::TYPE_TRANSFORM_REVERSIBLE, FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE]);
|
||||
$response->addCommand(new GetUntransformedTextCommand($editable_text));
|
||||
|
||||
return $response;
|
||||
|
|
|
@ -35,7 +35,7 @@ class Standard extends Xss implements EditorXssFilterInterface {
|
|||
// directly.
|
||||
// <iframe> is considered safe because it only allows HTML content to be
|
||||
// embedded, hence ensuring the same origin policy always applies.
|
||||
$dangerous_tags = array('script', 'style', 'link', 'embed', 'object');
|
||||
$dangerous_tags = ['script', 'style', 'link', 'embed', 'object'];
|
||||
|
||||
// Simply blacklisting these five dangerous tags would bring safety, but
|
||||
// also user frustration: what if a text format is configured to allow
|
||||
|
@ -130,13 +130,13 @@ class Standard extends Xss implements EditorXssFilterInterface {
|
|||
*/
|
||||
protected static function getAllowedTags($restrictions) {
|
||||
if ($restrictions === FALSE || !isset($restrictions['allowed'])) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
$allowed_tags = array_keys($restrictions['allowed']);
|
||||
// Exclude the wildcard tag, which is used to set attribute restrictions on
|
||||
// all tags simultaneously.
|
||||
$allowed_tags = array_diff($allowed_tags, array('*'));
|
||||
$allowed_tags = array_diff($allowed_tags, ['*']);
|
||||
|
||||
return $allowed_tags;
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ class Standard extends Xss implements EditorXssFilterInterface {
|
|||
*/
|
||||
protected static function getForbiddenTags($restrictions) {
|
||||
if ($restrictions === FALSE || !isset($restrictions['forbidden_tags'])) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
else {
|
||||
return $restrictions['forbidden_tags'];
|
||||
|
|
|
@ -32,7 +32,7 @@ class Element {
|
|||
/**
|
||||
* Additional #pre_render callback for 'text_format' elements.
|
||||
*/
|
||||
function preRenderTextFormat(array $element) {
|
||||
public function preRenderTextFormat(array $element) {
|
||||
// Allow modules to programmatically enforce no client-side editor by
|
||||
// setting the #editor property to FALSE.
|
||||
if (isset($element['#editor']) && !$element['#editor']) {
|
||||
|
@ -64,14 +64,14 @@ class Element {
|
|||
if (!$element['format']['format']['#access']) {
|
||||
// Use the first (and only) available text format.
|
||||
$format_id = $format_ids[0];
|
||||
$element['format']['editor'] = array(
|
||||
$element['format']['editor'] = [
|
||||
'#type' => 'hidden',
|
||||
'#name' => $element['format']['format']['#name'],
|
||||
'#value' => $format_id,
|
||||
'#attributes' => array(
|
||||
'#attributes' => [
|
||||
'data-editor-for' => $field_id,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
}
|
||||
// Otherwise, attach to text format selector.
|
||||
else {
|
||||
|
|
|
@ -49,14 +49,14 @@ class Editor extends ConfigEntityBase implements EditorInterface {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $settings = array();
|
||||
protected $settings = [];
|
||||
|
||||
/**
|
||||
* The structured array of image upload settings.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $image_upload = array();
|
||||
protected $image_upload = [];
|
||||
|
||||
/**
|
||||
* The filter format this text editor is associated with.
|
||||
|
|
|
@ -94,26 +94,26 @@ class EditorImageDialog extends FormBase {
|
|||
$existing_file = isset($image_element['data-entity-uuid']) ? \Drupal::entityManager()->loadEntityByUuid('file', $image_element['data-entity-uuid']) : NULL;
|
||||
$fid = $existing_file ? $existing_file->id() : NULL;
|
||||
|
||||
$form['fid'] = array(
|
||||
$form['fid'] = [
|
||||
'#title' => $this->t('Image'),
|
||||
'#type' => 'managed_file',
|
||||
'#upload_location' => $image_upload['scheme'] . '://' . $image_upload['directory'],
|
||||
'#default_value' => $fid ? array($fid) : NULL,
|
||||
'#upload_validators' => array(
|
||||
'file_validate_extensions' => array('gif png jpg jpeg'),
|
||||
'file_validate_size' => array($max_filesize),
|
||||
'file_validate_image_resolution' => array($max_dimensions),
|
||||
),
|
||||
'#default_value' => $fid ? [$fid] : NULL,
|
||||
'#upload_validators' => [
|
||||
'file_validate_extensions' => ['gif png jpg jpeg'],
|
||||
'file_validate_size' => [$max_filesize],
|
||||
'file_validate_image_resolution' => [$max_dimensions],
|
||||
],
|
||||
'#required' => TRUE,
|
||||
);
|
||||
];
|
||||
|
||||
$form['attributes']['src'] = array(
|
||||
$form['attributes']['src'] = [
|
||||
'#title' => $this->t('URL'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => isset($image_element['src']) ? $image_element['src'] : '',
|
||||
'#maxlength' => 2048,
|
||||
'#required' => TRUE,
|
||||
);
|
||||
];
|
||||
|
||||
// If the editor has image uploads enabled, show a managed_file form item,
|
||||
// otherwise show a (file URL) text form item.
|
||||
|
@ -137,7 +137,7 @@ class EditorImageDialog extends FormBase {
|
|||
if ($alt === '' && !empty($image_element['src'])) {
|
||||
$alt = '""';
|
||||
}
|
||||
$form['attributes']['alt'] = array(
|
||||
$form['attributes']['alt'] = [
|
||||
'#title' => $this->t('Alternative text'),
|
||||
'#placeholder' => $this->t('Short description for the visually impaired'),
|
||||
'#type' => 'textfield',
|
||||
|
@ -145,51 +145,51 @@ class EditorImageDialog extends FormBase {
|
|||
'#required_error' => $this->t('Alternative text is required.<br />(Only in rare cases should this be left empty. To create empty alternative text, enter <code>""</code> — two double quotes without any content).'),
|
||||
'#default_value' => $alt,
|
||||
'#maxlength' => 2048,
|
||||
);
|
||||
];
|
||||
|
||||
// When Drupal core's filter_align is being used, the text editor may
|
||||
// offer the ability to change the alignment.
|
||||
if (isset($image_element['data-align']) && $editor->getFilterFormat()->filters('filter_align')->status) {
|
||||
$form['align'] = array(
|
||||
$form['align'] = [
|
||||
'#title' => $this->t('Align'),
|
||||
'#type' => 'radios',
|
||||
'#options' => array(
|
||||
'#options' => [
|
||||
'none' => $this->t('None'),
|
||||
'left' => $this->t('Left'),
|
||||
'center' => $this->t('Center'),
|
||||
'right' => $this->t('Right'),
|
||||
),
|
||||
],
|
||||
'#default_value' => $image_element['data-align'] === '' ? 'none' : $image_element['data-align'],
|
||||
'#wrapper_attributes' => array('class' => array('container-inline')),
|
||||
'#attributes' => array('class' => array('container-inline')),
|
||||
'#parents' => array('attributes', 'data-align'),
|
||||
);
|
||||
'#wrapper_attributes' => ['class' => ['container-inline']],
|
||||
'#attributes' => ['class' => ['container-inline']],
|
||||
'#parents' => ['attributes', 'data-align'],
|
||||
];
|
||||
}
|
||||
|
||||
// When Drupal core's filter_caption is being used, the text editor may
|
||||
// offer the ability to in-place edit the image's caption: show a toggle.
|
||||
if (isset($image_element['hasCaption']) && $editor->getFilterFormat()->filters('filter_caption')->status) {
|
||||
$form['caption'] = array(
|
||||
$form['caption'] = [
|
||||
'#title' => $this->t('Caption'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => $image_element['hasCaption'] === 'true',
|
||||
'#parents' => array('attributes', 'hasCaption'),
|
||||
);
|
||||
'#parents' => ['attributes', 'hasCaption'],
|
||||
];
|
||||
}
|
||||
|
||||
$form['actions'] = array(
|
||||
$form['actions'] = [
|
||||
'#type' => 'actions',
|
||||
);
|
||||
$form['actions']['save_modal'] = array(
|
||||
];
|
||||
$form['actions']['save_modal'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
// No regular submit-handler. This form only works via JavaScript.
|
||||
'#submit' => array(),
|
||||
'#ajax' => array(
|
||||
'#submit' => [],
|
||||
'#ajax' => [
|
||||
'callback' => '::submitForm',
|
||||
'event' => 'click',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
@ -202,22 +202,22 @@ class EditorImageDialog extends FormBase {
|
|||
|
||||
// Convert any uploaded files from the FID values to data-entity-uuid
|
||||
// attributes and set data-entity-type to 'file'.
|
||||
$fid = $form_state->getValue(array('fid', 0));
|
||||
$fid = $form_state->getValue(['fid', 0]);
|
||||
if (!empty($fid)) {
|
||||
$file = $this->fileStorage->load($fid);
|
||||
$file_url = file_create_url($file->getFileUri());
|
||||
// Transform absolute image URLs to relative image URLs: prevent problems
|
||||
// on multisite set-ups and prevent mixed content errors.
|
||||
$file_url = file_url_transform_relative($file_url);
|
||||
$form_state->setValue(array('attributes', 'src'), $file_url);
|
||||
$form_state->setValue(array('attributes', 'data-entity-uuid'), $file->uuid());
|
||||
$form_state->setValue(array('attributes', 'data-entity-type'), 'file');
|
||||
$form_state->setValue(['attributes', 'src'], $file_url);
|
||||
$form_state->setValue(['attributes', 'data-entity-uuid'], $file->uuid());
|
||||
$form_state->setValue(['attributes', 'data-entity-type'], 'file');
|
||||
}
|
||||
|
||||
// When the alt attribute is set to two double quotes, transform it to the
|
||||
// empty string: two double quotes signify "empty alt attribute". See above.
|
||||
if (trim($form_state->getValue(array('attributes', 'alt'))) === '""') {
|
||||
$form_state->setValue(array('attributes', 'alt'), '');
|
||||
if (trim($form_state->getValue(['attributes', 'alt'])) === '""') {
|
||||
$form_state->setValue(['attributes', 'alt'], '');
|
||||
}
|
||||
|
||||
if ($form_state->getErrors()) {
|
||||
|
|
|
@ -32,7 +32,7 @@ class EditorLinkDialog extends FormBase {
|
|||
// The default values are set directly from \Drupal::request()->request,
|
||||
// provided by the editor plugin opening the dialog.
|
||||
$user_input = $form_state->getUserInput();
|
||||
$input = isset($user_input['editor_object']) ? $user_input['editor_object'] : array();
|
||||
$input = isset($user_input['editor_object']) ? $user_input['editor_object'] : [];
|
||||
|
||||
$form['#tree'] = TRUE;
|
||||
$form['#attached']['library'][] = 'editor/drupal.editor.dialog';
|
||||
|
@ -41,26 +41,26 @@ class EditorLinkDialog extends FormBase {
|
|||
|
||||
// Everything under the "attributes" key is merged directly into the
|
||||
// generated link tag's attributes.
|
||||
$form['attributes']['href'] = array(
|
||||
$form['attributes']['href'] = [
|
||||
'#title' => $this->t('URL'),
|
||||
'#type' => 'textfield',
|
||||
'#default_value' => isset($input['href']) ? $input['href'] : '',
|
||||
'#maxlength' => 2048,
|
||||
);
|
||||
];
|
||||
|
||||
$form['actions'] = array(
|
||||
$form['actions'] = [
|
||||
'#type' => 'actions',
|
||||
);
|
||||
$form['actions']['save_modal'] = array(
|
||||
];
|
||||
$form['actions']['save_modal'] = [
|
||||
'#type' => 'submit',
|
||||
'#value' => $this->t('Save'),
|
||||
// No regular submit-handler. This form only works via JavaScript.
|
||||
'#submit' => array(),
|
||||
'#ajax' => array(
|
||||
'#submit' => [],
|
||||
'#ajax' => [
|
||||
'callback' => '::submitForm',
|
||||
'event' => 'click',
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
|
|
@ -26,26 +26,56 @@ abstract class EditorBase extends PluginBase implements EditorPluginInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultSettings() {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Remove in Drupal 9.0.0.
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
|
||||
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.3.x and will be removed in 9.0.0.', E_USER_DEPRECATED);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Remove in Drupal 9.0.0.
|
||||
*/
|
||||
public function settingsFormValidate(array $form, FormStateInterface $form_state) {
|
||||
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.3.x and will be removed in 9.0.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @todo Remove in Drupal 9.0.0.
|
||||
*/
|
||||
public function settingsFormSubmit(array $form, FormStateInterface $form_state) {
|
||||
@trigger_error('The ' . __METHOD__ . ' method is deprecated since version 8.3.x and will be removed in 9.0.0.', E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsFormSubmit(array $form, FormStateInterface $form_state) {
|
||||
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
||||
return $this->settingsForm($form, $form_state, $form_state->get('editor'));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
return $this->settingsFormValidate($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
||||
return $this->settingsFormSubmit($form, $form_state);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class EditorManager extends DefaultPluginManager {
|
|||
* An array of translated text editor labels, keyed by ID.
|
||||
*/
|
||||
public function listOptions() {
|
||||
$options = array();
|
||||
$options = [];
|
||||
foreach ($this->getDefinitions() as $key => $definition) {
|
||||
$options[$key] = $definition['label'];
|
||||
}
|
||||
|
@ -59,9 +59,9 @@ class EditorManager extends DefaultPluginManager {
|
|||
* @see \Drupal\Core\Render\AttachmentsResponseProcessorInterface::processAttachments()
|
||||
*/
|
||||
public function getAttachments(array $format_ids) {
|
||||
$attachments = array('library' => array());
|
||||
$attachments = ['library' => []];
|
||||
|
||||
$settings = array();
|
||||
$settings = [];
|
||||
foreach ($format_ids as $format_id) {
|
||||
$editor = editor_load($format_id);
|
||||
if (!$editor) {
|
||||
|
@ -75,20 +75,20 @@ class EditorManager extends DefaultPluginManager {
|
|||
$attachments['library'] = array_merge($attachments['library'], $plugin->getLibraries($editor));
|
||||
|
||||
// Format-specific JavaScript settings.
|
||||
$settings['editor']['formats'][$format_id] = array(
|
||||
$settings['editor']['formats'][$format_id] = [
|
||||
'format' => $format_id,
|
||||
'editor' => $editor->getEditor(),
|
||||
'editorSettings' => $plugin->getJSSettings($editor),
|
||||
'editorSupportsContentFiltering' => $plugin_definition['supports_content_filtering'],
|
||||
'isXssSafe' => $plugin_definition['is_xss_safe'],
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// Allow other modules to alter all JavaScript settings.
|
||||
$this->moduleHandler->alter('editor_js_settings', $settings);
|
||||
|
||||
if (empty($attachments['library']) && empty($settings)) {
|
||||
return array();
|
||||
return [];
|
||||
}
|
||||
|
||||
$attachments['drupalSettings'] = $settings;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Drupal\editor\Plugin;
|
||||
|
||||
use Drupal\Component\Plugin\PluginInspectionInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\Core\Plugin\PluginFormInterface;
|
||||
use Drupal\editor\Entity\Editor;
|
||||
|
||||
/**
|
||||
|
@ -12,12 +12,17 @@ use Drupal\editor\Entity\Editor;
|
|||
* Modules implementing this interface may want to extend the EditorBase class,
|
||||
* which provides default implementations of each method where appropriate.
|
||||
*
|
||||
* If the editor's behavior depends on extensive options and/or external data,
|
||||
* then the implementing module can choose to provide a separate, global
|
||||
* configuration page rather than per-text-format settings. In that case, this
|
||||
* form should provide a link to the separate settings page.
|
||||
*
|
||||
* @see \Drupal\editor\Annotation\Editor
|
||||
* @see \Drupal\editor\Plugin\EditorBase
|
||||
* @see \Drupal\editor\Plugin\EditorManager
|
||||
* @see plugin_api
|
||||
*/
|
||||
interface EditorPluginInterface extends PluginInspectionInterface {
|
||||
interface EditorPluginInterface extends PluginInspectionInterface, PluginFormInterface {
|
||||
|
||||
/**
|
||||
* Returns the default settings for this configurable text editor.
|
||||
|
@ -28,53 +33,6 @@ interface EditorPluginInterface extends PluginInspectionInterface {
|
|||
*/
|
||||
public function getDefaultSettings();
|
||||
|
||||
/**
|
||||
* Returns a settings form to configure this text editor.
|
||||
*
|
||||
* If the editor's behavior depends on extensive options and/or external data,
|
||||
* then the implementing module can choose to provide a separate, global
|
||||
* configuration page rather than per-text-format settings. In that case, this
|
||||
* form should provide a link to the separate settings page.
|
||||
*
|
||||
* @param array $form
|
||||
* An empty form array to be populated with a configuration form, if any.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The state of the entire filter administration form.
|
||||
* @param \Drupal\editor\Entity\Editor $editor
|
||||
* A configured text editor object.
|
||||
*
|
||||
* @return array
|
||||
* A render array for the settings form.
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor);
|
||||
|
||||
/**
|
||||
* Validates the settings form for an editor.
|
||||
*
|
||||
* The contents of the editor settings are located in
|
||||
* $form_state->getValue(array('editor', 'settings')). Calls to $form_state->setError()
|
||||
* should reflect this location in the settings form.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*/
|
||||
public function settingsFormValidate(array $form, FormStateInterface $form_state);
|
||||
|
||||
/**
|
||||
* Modifies any values in the form state to prepare them for saving.
|
||||
*
|
||||
* Values in $form_state->getValue(array('editor', 'settings')) are saved by
|
||||
* Editor module in editor_form_filter_admin_format_submit().
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param \Drupal\Core\Form\FormStateInterface $form_state
|
||||
* The current state of the form.
|
||||
*/
|
||||
public function settingsFormSubmit(array $form, FormStateInterface $form_state);
|
||||
|
||||
/**
|
||||
* Returns JavaScript settings to be attached.
|
||||
*
|
||||
|
|
|
@ -68,7 +68,7 @@ class EditorFileReference extends FilterBase implements ContainerFactoryPluginIn
|
|||
if (stristr($text, 'data-entity-type="file"') !== FALSE) {
|
||||
$dom = Html::load($text);
|
||||
$xpath = new \DOMXPath($dom);
|
||||
$processed_uuids = array();
|
||||
$processed_uuids = [];
|
||||
foreach ($xpath->query('//*[@data-entity-type="file" and @data-entity-uuid]') as $node) {
|
||||
$uuid = $node->getAttribute('data-entity-uuid');
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ class Editor extends PluginBase implements InPlaceEditorInterface {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getMetadata(FieldItemListInterface $items) {
|
||||
public function getMetadata(FieldItemListInterface $items) {
|
||||
$format_id = $items[0]->format;
|
||||
$metadata['format'] = $format_id;
|
||||
$metadata['formatHasTransformations'] = $this->textFormatHasTransformationFilters($format_id);
|
||||
|
@ -60,7 +60,7 @@ class Editor extends PluginBase implements InPlaceEditorInterface {
|
|||
*/
|
||||
protected function textFormatHasTransformationFilters($format_id) {
|
||||
$format = FilterFormat::load($format_id);
|
||||
return (bool) count(array_intersect(array(FilterInterface::TYPE_TRANSFORM_REVERSIBLE, FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE), $format->getFiltertypes()));
|
||||
return (bool) count(array_intersect([FilterInterface::TYPE_TRANSFORM_REVERSIBLE, FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE], $format->getFiltertypes()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ class Editor extends PluginBase implements InPlaceEditorInterface {
|
|||
$definitions = $manager->getDefinitions();
|
||||
|
||||
// Filter the current user's formats to those that support inline editing.
|
||||
$formats = array();
|
||||
$formats = [];
|
||||
foreach ($user_format_ids as $format_id) {
|
||||
if ($editor = editor_load($format_id)) {
|
||||
$editor_id = $editor->getEditor();
|
||||
|
|
|
@ -20,7 +20,7 @@ class EditorAdminTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('filter', 'editor');
|
||||
public static $modules = ['filter', 'editor'];
|
||||
|
||||
/**
|
||||
* A user with the 'administer filters' permission.
|
||||
|
@ -33,16 +33,16 @@ class EditorAdminTest extends WebTestBase {
|
|||
parent::setUp();
|
||||
|
||||
// Add text format.
|
||||
$filtered_html_format = FilterFormat::create(array(
|
||||
$filtered_html_format = FilterFormat::create([
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
'weight' => 0,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$filtered_html_format->save();
|
||||
|
||||
// Create admin user.
|
||||
$this->adminUser = $this->drupalCreateUser(array('administer filters'));
|
||||
$this->adminUser = $this->drupalCreateUser(['administer filters']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,9 +83,9 @@ class EditorAdminTest extends WebTestBase {
|
|||
$this->verifyUnicornEditorConfiguration('filtered_html', FALSE);
|
||||
|
||||
// Switch back to 'None' and check the Unicorn Editor's settings are gone.
|
||||
$edit = array(
|
||||
$edit = [
|
||||
'editor[editor]' => '',
|
||||
);
|
||||
];
|
||||
$this->drupalPostAjaxForm(NULL, $edit, 'editor_configure');
|
||||
$unicorn_setting = $this->xpath('//input[@name="editor[settings][ponies_too]" and @type="checkbox" and @checked]');
|
||||
$this->assertTrue(count($unicorn_setting) === 0, "Unicorn Editor's settings form is no longer present.");
|
||||
|
@ -135,7 +135,7 @@ class EditorAdminTest extends WebTestBase {
|
|||
$this->drupalLogin($account);
|
||||
|
||||
// The node edit page header.
|
||||
$text = t('<em>Edit @type</em> @title', array('@type' => $node_type->label(), '@title' => $node->label()));
|
||||
$text = t('<em>Edit @type</em> @title', ['@type' => $node_type->label(), '@title' => $node->label()]);
|
||||
|
||||
// Go to node edit form.
|
||||
$this->drupalGet('node/' . $node->id() . '/edit');
|
||||
|
@ -162,10 +162,10 @@ class EditorAdminTest extends WebTestBase {
|
|||
$this->drupalLogin($this->adminUser);
|
||||
$this->drupalGet('admin/config/content/formats/add');
|
||||
// Configure the text format name.
|
||||
$edit = array(
|
||||
$edit = [
|
||||
'name' => $format_name,
|
||||
'format' => $format_id,
|
||||
);
|
||||
];
|
||||
$edit += $this->selectUnicornEditor();
|
||||
$this->drupalPostForm(NULL, $edit, t('Save configuration'));
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ class EditorAdminTest extends WebTestBase {
|
|||
*/
|
||||
protected function enableUnicornEditor() {
|
||||
if (!$this->container->get('module_handler')->moduleExists('editor_test')) {
|
||||
$this->container->get('module_installer')->install(array('editor_test'));
|
||||
$this->container->get('module_installer')->install(['editor_test']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -200,9 +200,9 @@ class EditorAdminTest extends WebTestBase {
|
|||
$this->assertNoRaw(t('This option is disabled because no modules that provide a text editor are currently enabled.'), 'Description for select absent that tells users to install a text editor module.');
|
||||
|
||||
// Select the "Unicorn Editor" editor and click the "Configure" button.
|
||||
$edit = array(
|
||||
$edit = [
|
||||
'editor[editor]' => 'unicorn',
|
||||
);
|
||||
];
|
||||
$this->drupalPostAjaxForm(NULL, $edit, 'editor_configure');
|
||||
$unicorn_setting = $this->xpath('//input[@name="editor[settings][ponies_too]" and @type="checkbox" and @checked]');
|
||||
$this->assertTrue(count($unicorn_setting), "Unicorn Editor's settings form is present.");
|
||||
|
|
|
@ -20,7 +20,7 @@ class EditorLoadingTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('filter', 'editor', 'editor_test', 'node');
|
||||
public static $modules = ['filter', 'editor', 'editor_test', 'node'];
|
||||
|
||||
/**
|
||||
* An untrusted user, with access to the 'plain_text' format.
|
||||
|
@ -51,57 +51,57 @@ class EditorLoadingTest extends WebTestBase {
|
|||
\Drupal::service('plugin.manager.editor')->clearCachedDefinitions();
|
||||
|
||||
// Add text formats.
|
||||
$filtered_html_format = FilterFormat::create(array(
|
||||
$filtered_html_format = FilterFormat::create([
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
'weight' => 0,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$filtered_html_format->save();
|
||||
$full_html_format = FilterFormat::create(array(
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
'weight' => 1,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Create article node type.
|
||||
$this->drupalCreateContentType(array(
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
));
|
||||
]);
|
||||
|
||||
// Create page node type, but remove the body.
|
||||
$this->drupalCreateContentType(array(
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'page',
|
||||
'name' => 'Page',
|
||||
));
|
||||
]);
|
||||
$body = FieldConfig::loadByName('node', 'page', 'body');
|
||||
$body->delete();
|
||||
|
||||
// Create a formatted text field, which uses an <input type="text">.
|
||||
FieldStorageConfig::create(array(
|
||||
FieldStorageConfig::create([
|
||||
'field_name' => 'field_text',
|
||||
'entity_type' => 'node',
|
||||
'type' => 'text',
|
||||
))->save();
|
||||
])->save();
|
||||
|
||||
FieldConfig::create(array(
|
||||
FieldConfig::create([
|
||||
'field_name' => 'field_text',
|
||||
'entity_type' => 'node',
|
||||
'label' => 'Textfield',
|
||||
'bundle' => 'page',
|
||||
))->save();
|
||||
])->save();
|
||||
|
||||
entity_get_form_display('node', 'page', 'default')
|
||||
->setComponent('field_text')
|
||||
->save();
|
||||
|
||||
// Create 3 users, each with access to different text formats.
|
||||
$this->untrustedUser = $this->drupalCreateUser(array('create article content', 'edit any article content'));
|
||||
$this->normalUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'use text format filtered_html'));
|
||||
$this->privilegedUser = $this->drupalCreateUser(array('create article content', 'edit any article content', 'create page content', 'edit any page content', 'use text format filtered_html', 'use text format full_html'));
|
||||
$this->untrustedUser = $this->drupalCreateUser(['create article content', 'edit any article content']);
|
||||
$this->normalUser = $this->drupalCreateUser(['create article content', 'edit any article content', 'use text format filtered_html']);
|
||||
$this->privilegedUser = $this->drupalCreateUser(['create article content', 'edit any article content', 'create page content', 'edit any page content', 'use text format filtered_html', 'use text format full_html']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,13 +112,13 @@ class EditorLoadingTest extends WebTestBase {
|
|||
$editor = Editor::create([
|
||||
'format' => 'full_html',
|
||||
'editor' => 'unicorn',
|
||||
'image_upload' => array(
|
||||
'image_upload' => [
|
||||
'status' => FALSE,
|
||||
'scheme' => file_default_scheme(),
|
||||
'directory' => 'inline-images',
|
||||
'max_size' => '',
|
||||
'max_dimensions' => array('width' => '', 'height' => ''),
|
||||
)
|
||||
'max_dimensions' => ['width' => '', 'height' => ''],
|
||||
]
|
||||
]);
|
||||
$editor->save();
|
||||
|
||||
|
@ -140,13 +140,13 @@ class EditorLoadingTest extends WebTestBase {
|
|||
$this->drupalLogin($this->privilegedUser);
|
||||
$this->drupalGet('node/add/article');
|
||||
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
|
||||
$expected = array('formats' => array('full_html' => array(
|
||||
$expected = ['formats' => ['full_html' => [
|
||||
'format' => 'full_html',
|
||||
'editor' => 'unicorn',
|
||||
'editorSettings' => array('ponyModeEnabled' => TRUE),
|
||||
'editorSettings' => ['ponyModeEnabled' => TRUE],
|
||||
'editorSupportsContentFiltering' => TRUE,
|
||||
'isXssSafe' => FALSE,
|
||||
)));
|
||||
]]];
|
||||
$this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
|
||||
$this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
|
||||
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
|
||||
|
@ -174,13 +174,13 @@ class EditorLoadingTest extends WebTestBase {
|
|||
$this->drupalLogin($this->untrustedUser);
|
||||
$this->drupalGet('node/add/article');
|
||||
list($settings, $editor_settings_present, $editor_js_present, $body, $format_selector) = $this->getThingsToCheck('body');
|
||||
$expected = array('formats' => array('plain_text' => array(
|
||||
$expected = ['formats' => ['plain_text' => [
|
||||
'format' => 'plain_text',
|
||||
'editor' => 'unicorn',
|
||||
'editorSettings' => array('ponyModeEnabled' => TRUE),
|
||||
'editorSettings' => ['ponyModeEnabled' => TRUE],
|
||||
'editorSupportsContentFiltering' => TRUE,
|
||||
'isXssSafe' => FALSE,
|
||||
)));
|
||||
]]];
|
||||
$this->assertTrue($editor_settings_present, "Text Editor module's JavaScript settings are on the page.");
|
||||
$this->assertIdentical($expected, $settings['editor'], "Text Editor module's JavaScript settings on the page are correct.");
|
||||
$this->assertTrue($editor_js_present, 'Text Editor JavaScript is present.');
|
||||
|
@ -191,12 +191,12 @@ class EditorLoadingTest extends WebTestBase {
|
|||
|
||||
// Create an "article" node that uses the full_html text format, then try
|
||||
// to let the untrusted user edit it.
|
||||
$this->drupalCreateNode(array(
|
||||
$this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'body' => array(
|
||||
array('value' => $this->randomMachineName(32), 'format' => 'full_html')
|
||||
),
|
||||
));
|
||||
'body' => [
|
||||
['value' => $this->randomMachineName(32), 'format' => 'full_html']
|
||||
],
|
||||
]);
|
||||
|
||||
// The untrusted user tries to edit content that is written in a text format
|
||||
// that (s)he is not allowed to use. The editor is still loaded. CKEditor,
|
||||
|
@ -220,23 +220,23 @@ class EditorLoadingTest extends WebTestBase {
|
|||
$editor = Editor::create([
|
||||
'format' => 'full_html',
|
||||
'editor' => 'unicorn',
|
||||
'image_upload' => array(
|
||||
'image_upload' => [
|
||||
'status' => FALSE,
|
||||
'scheme' => file_default_scheme(),
|
||||
'directory' => 'inline-images',
|
||||
'max_size' => '',
|
||||
'max_dimensions' => array('width' => '', 'height' => ''),
|
||||
)
|
||||
'max_dimensions' => ['width' => '', 'height' => ''],
|
||||
]
|
||||
]);
|
||||
$editor->save();
|
||||
|
||||
// Create an "page" node that uses the full_html text format.
|
||||
$this->drupalCreateNode(array(
|
||||
$this->drupalCreateNode([
|
||||
'type' => 'page',
|
||||
'field_text' => array(
|
||||
array('value' => $this->randomMachineName(32), 'format' => 'full_html')
|
||||
),
|
||||
));
|
||||
'field_text' => [
|
||||
['value' => $this->randomMachineName(32), 'format' => 'full_html']
|
||||
],
|
||||
]);
|
||||
|
||||
// Assert the unicorn editor works with textfields.
|
||||
$this->drupalLogin($this->privilegedUser);
|
||||
|
@ -268,7 +268,7 @@ class EditorLoadingTest extends WebTestBase {
|
|||
|
||||
protected function getThingsToCheck($field_name, $type = 'textarea') {
|
||||
$settings = $this->getDrupalSettings();
|
||||
return array(
|
||||
return [
|
||||
// JavaScript settings.
|
||||
$settings,
|
||||
// Editor.module's JS settings present.
|
||||
|
@ -279,7 +279,7 @@ class EditorLoadingTest extends WebTestBase {
|
|||
$this->xpath('//' . $type . '[@id="edit-' . $field_name . '-0-value"]'),
|
||||
// Format selector.
|
||||
$this->xpath('//select[contains(@class, "filter-list")]'),
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class EditorSecurityTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('filter', 'editor', 'editor_test', 'node');
|
||||
public static $modules = ['filter', 'editor', 'editor_test', 'node'];
|
||||
|
||||
/**
|
||||
* User with access to Restricted HTML text format without text editor.
|
||||
|
@ -83,74 +83,74 @@ class EditorSecurityTest extends WebTestBase {
|
|||
// With text formats 2, 3 and 5, we also associate a text editor that does
|
||||
// not guarantee XSS safety. "restricted" means the text format has XSS
|
||||
// filters on output, "unrestricted" means the opposite.
|
||||
$format = FilterFormat::create(array(
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'restricted_without_editor',
|
||||
'name' => 'Restricted HTML, without text editor',
|
||||
'weight' => 0,
|
||||
'filters' => array(
|
||||
'filters' => [
|
||||
// A filter of the FilterInterface::TYPE_HTML_RESTRICTOR type.
|
||||
'filter_html' => array(
|
||||
'filter_html' => [
|
||||
'status' => 1,
|
||||
'settings' => array(
|
||||
'settings' => [
|
||||
'allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a>',
|
||||
)
|
||||
),
|
||||
),
|
||||
));
|
||||
]
|
||||
],
|
||||
],
|
||||
]);
|
||||
$format->save();
|
||||
$format = FilterFormat::create(array(
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'restricted_with_editor',
|
||||
'name' => 'Restricted HTML, with text editor',
|
||||
'weight' => 1,
|
||||
'filters' => array(
|
||||
'filters' => [
|
||||
// A filter of the FilterInterface::TYPE_HTML_RESTRICTOR type.
|
||||
'filter_html' => array(
|
||||
'filter_html' => [
|
||||
'status' => 1,
|
||||
'settings' => array(
|
||||
'settings' => [
|
||||
'allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a>',
|
||||
)
|
||||
),
|
||||
),
|
||||
));
|
||||
]
|
||||
],
|
||||
],
|
||||
]);
|
||||
$format->save();
|
||||
$editor = Editor::create([
|
||||
'format' => 'restricted_with_editor',
|
||||
'editor' => 'unicorn',
|
||||
]);
|
||||
$editor->save();
|
||||
$format = FilterFormat::create(array(
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'restricted_plus_dangerous_tag_with_editor',
|
||||
'name' => 'Restricted HTML, dangerous tag allowed, with text editor',
|
||||
'weight' => 1,
|
||||
'filters' => array(
|
||||
'filters' => [
|
||||
// A filter of the FilterInterface::TYPE_HTML_RESTRICTOR type.
|
||||
'filter_html' => array(
|
||||
'filter_html' => [
|
||||
'status' => 1,
|
||||
'settings' => array(
|
||||
'settings' => [
|
||||
'allowed_html' => '<h2> <h3> <h4> <h5> <h6> <p> <br> <strong> <a> <embed>',
|
||||
)
|
||||
),
|
||||
),
|
||||
));
|
||||
]
|
||||
],
|
||||
],
|
||||
]);
|
||||
$format->save();
|
||||
$editor = Editor::create([
|
||||
'format' => 'restricted_plus_dangerous_tag_with_editor',
|
||||
'editor' => 'unicorn',
|
||||
]);
|
||||
$editor->save();
|
||||
$format = FilterFormat::create(array(
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'unrestricted_without_editor',
|
||||
'name' => 'Unrestricted HTML, without text editor',
|
||||
'weight' => 0,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$format->save();
|
||||
$format = FilterFormat::create(array(
|
||||
$format = FilterFormat::create([
|
||||
'format' => 'unrestricted_with_editor',
|
||||
'name' => 'Unrestricted HTML, with text editor',
|
||||
'weight' => 1,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$format->save();
|
||||
$editor = Editor::create([
|
||||
'format' => 'unrestricted_with_editor',
|
||||
|
@ -160,10 +160,10 @@ class EditorSecurityTest extends WebTestBase {
|
|||
|
||||
|
||||
// Create node type.
|
||||
$this->drupalCreateContentType(array(
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
));
|
||||
]);
|
||||
|
||||
// Create 4 users, each with access to different text formats/editors:
|
||||
// - "untrusted": restricted_without_editor
|
||||
|
@ -172,22 +172,22 @@ class EditorSecurityTest extends WebTestBase {
|
|||
// - "privileged": restricted_without_editor, restricted_with_editor,
|
||||
// restricted_plus_dangerous_tag_with_editor,
|
||||
// unrestricted_without_editor and unrestricted_with_editor
|
||||
$this->untrustedUser = $this->drupalCreateUser(array(
|
||||
$this->untrustedUser = $this->drupalCreateUser([
|
||||
'create article content',
|
||||
'edit any article content',
|
||||
'use text format restricted_without_editor',
|
||||
));
|
||||
$this->normalUser = $this->drupalCreateUser(array(
|
||||
]);
|
||||
$this->normalUser = $this->drupalCreateUser([
|
||||
'create article content',
|
||||
'edit any article content',
|
||||
'use text format restricted_with_editor',
|
||||
));
|
||||
$this->trustedUser = $this->drupalCreateUser(array(
|
||||
]);
|
||||
$this->trustedUser = $this->drupalCreateUser([
|
||||
'create article content',
|
||||
'edit any article content',
|
||||
'use text format restricted_plus_dangerous_tag_with_editor',
|
||||
));
|
||||
$this->privilegedUser = $this->drupalCreateUser(array(
|
||||
]);
|
||||
$this->privilegedUser = $this->drupalCreateUser([
|
||||
'create article content',
|
||||
'edit any article content',
|
||||
'use text format restricted_without_editor',
|
||||
|
@ -195,25 +195,25 @@ class EditorSecurityTest extends WebTestBase {
|
|||
'use text format restricted_plus_dangerous_tag_with_editor',
|
||||
'use text format unrestricted_without_editor',
|
||||
'use text format unrestricted_with_editor',
|
||||
));
|
||||
]);
|
||||
|
||||
// Create an "article" node for each possible text format, with the same
|
||||
// sample content, to do our tests on.
|
||||
$samples = array(
|
||||
array('author' => $this->untrustedUser->id(), 'format' => 'restricted_without_editor'),
|
||||
array('author' => $this->normalUser->id(), 'format' => 'restricted_with_editor'),
|
||||
array('author' => $this->trustedUser->id(), 'format' => 'restricted_plus_dangerous_tag_with_editor'),
|
||||
array('author' => $this->privilegedUser->id(), 'format' => 'unrestricted_without_editor'),
|
||||
array('author' => $this->privilegedUser->id(), 'format' => 'unrestricted_with_editor'),
|
||||
);
|
||||
$samples = [
|
||||
['author' => $this->untrustedUser->id(), 'format' => 'restricted_without_editor'],
|
||||
['author' => $this->normalUser->id(), 'format' => 'restricted_with_editor'],
|
||||
['author' => $this->trustedUser->id(), 'format' => 'restricted_plus_dangerous_tag_with_editor'],
|
||||
['author' => $this->privilegedUser->id(), 'format' => 'unrestricted_without_editor'],
|
||||
['author' => $this->privilegedUser->id(), 'format' => 'unrestricted_with_editor'],
|
||||
];
|
||||
foreach ($samples as $sample) {
|
||||
$this->drupalCreateNode(array(
|
||||
$this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'body' => array(
|
||||
array('value' => self::$sampleContent, 'format' => $sample['format'])
|
||||
),
|
||||
'body' => [
|
||||
['value' => self::$sampleContent, 'format' => $sample['format']]
|
||||
],
|
||||
'uid' => $sample['author']
|
||||
));
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,65 +222,65 @@ class EditorSecurityTest extends WebTestBase {
|
|||
*
|
||||
* Tests 8 scenarios. Tests only with a text editor that is not XSS-safe.
|
||||
*/
|
||||
function testInitialSecurity() {
|
||||
$expected = array(
|
||||
array(
|
||||
public function testInitialSecurity() {
|
||||
$expected = [
|
||||
[
|
||||
'node_id' => 1,
|
||||
'format' => 'restricted_without_editor',
|
||||
// No text editor => no XSS filtering.
|
||||
'value' => self::$sampleContent,
|
||||
'users' => array(
|
||||
'users' => [
|
||||
$this->untrustedUser,
|
||||
$this->privilegedUser,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 2,
|
||||
'format' => 'restricted_with_editor',
|
||||
// Text editor => XSS filtering.
|
||||
'value' => self::$sampleContentSecured,
|
||||
'users' => array(
|
||||
'users' => [
|
||||
$this->normalUser,
|
||||
$this->privilegedUser,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 3,
|
||||
'format' => 'restricted_plus_dangerous_tag_with_editor',
|
||||
// Text editor => XSS filtering.
|
||||
'value' => self::$sampleContentSecuredEmbedAllowed,
|
||||
'users' => array(
|
||||
'users' => [
|
||||
$this->trustedUser,
|
||||
$this->privilegedUser,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 4,
|
||||
'format' => 'unrestricted_without_editor',
|
||||
// No text editor => no XSS filtering.
|
||||
'value' => self::$sampleContent,
|
||||
'users' => array(
|
||||
'users' => [
|
||||
$this->privilegedUser,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 5,
|
||||
'format' => 'unrestricted_with_editor',
|
||||
// Text editor, no security filter => no XSS filtering.
|
||||
'value' => self::$sampleContent,
|
||||
'users' => array(
|
||||
'users' => [
|
||||
$this->privilegedUser,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Log in as each user that may edit the content, and assert the value.
|
||||
foreach ($expected as $case) {
|
||||
foreach ($case['users'] as $account) {
|
||||
$this->pass(format_string('Scenario: sample %sample_id, %format.', array(
|
||||
$this->pass(format_string('Scenario: sample %sample_id, %format.', [
|
||||
'%sample_id' => $case['node_id'],
|
||||
'%format' => $case['format'],
|
||||
)));
|
||||
]));
|
||||
$this->drupalLogin($account);
|
||||
$this->drupalGet('node/' . $case['node_id'] . '/edit');
|
||||
$dom_node = $this->xpath('//textarea[@id="edit-body-0-value"]');
|
||||
|
@ -302,26 +302,26 @@ class EditorSecurityTest extends WebTestBase {
|
|||
* format and contains a <script> tag to the Full HTML text format, the
|
||||
* <script> tag would be executed. Unless we apply appropriate filtering.
|
||||
*/
|
||||
function testSwitchingSecurity() {
|
||||
$expected = array(
|
||||
array(
|
||||
public function testSwitchingSecurity() {
|
||||
$expected = [
|
||||
[
|
||||
'node_id' => 1,
|
||||
'value' => self::$sampleContent, // No text editor => no XSS filtering.
|
||||
'format' => 'restricted_without_editor',
|
||||
'switch_to' => array(
|
||||
'switch_to' => [
|
||||
'restricted_with_editor' => self::$sampleContentSecured,
|
||||
// Intersection of restrictions => most strict XSS filtering.
|
||||
'restricted_plus_dangerous_tag_with_editor' => self::$sampleContentSecured,
|
||||
// No text editor => no XSS filtering.
|
||||
'unrestricted_without_editor' => FALSE,
|
||||
'unrestricted_with_editor' => self::$sampleContentSecured,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 2,
|
||||
'value' => self::$sampleContentSecured, // Text editor => XSS filtering.
|
||||
'format' => 'restricted_with_editor',
|
||||
'switch_to' => array(
|
||||
'switch_to' => [
|
||||
// No text editor => no XSS filtering.
|
||||
'restricted_without_editor' => FALSE,
|
||||
// Intersection of restrictions => most strict XSS filtering.
|
||||
|
@ -329,13 +329,13 @@ class EditorSecurityTest extends WebTestBase {
|
|||
// No text editor => no XSS filtering.
|
||||
'unrestricted_without_editor' => FALSE,
|
||||
'unrestricted_with_editor' => self::$sampleContentSecured,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 3,
|
||||
'value' => self::$sampleContentSecuredEmbedAllowed, // Text editor => XSS filtering.
|
||||
'format' => 'restricted_plus_dangerous_tag_with_editor',
|
||||
'switch_to' => array(
|
||||
'switch_to' => [
|
||||
// No text editor => no XSS filtering.
|
||||
'restricted_without_editor' => FALSE,
|
||||
// Intersection of restrictions => most strict XSS filtering.
|
||||
|
@ -344,13 +344,13 @@ class EditorSecurityTest extends WebTestBase {
|
|||
'unrestricted_without_editor' => FALSE,
|
||||
// Intersection of restrictions => most strict XSS filtering.
|
||||
'unrestricted_with_editor' => self::$sampleContentSecured,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 4,
|
||||
'value' => self::$sampleContent, // No text editor => no XSS filtering.
|
||||
'format' => 'unrestricted_without_editor',
|
||||
'switch_to' => array(
|
||||
'switch_to' => [
|
||||
// No text editor => no XSS filtering.
|
||||
'restricted_without_editor' => FALSE,
|
||||
'restricted_with_editor' => self::$sampleContentSecured,
|
||||
|
@ -360,13 +360,13 @@ class EditorSecurityTest extends WebTestBase {
|
|||
// filters: resulting content when viewed was already vulnerable, so
|
||||
// it must be intentional.
|
||||
'unrestricted_with_editor' => FALSE,
|
||||
),
|
||||
),
|
||||
array(
|
||||
],
|
||||
],
|
||||
[
|
||||
'node_id' => 5,
|
||||
'value' => self::$sampleContentSecured, // Text editor => XSS filtering.
|
||||
'format' => 'unrestricted_with_editor',
|
||||
'switch_to' => array(
|
||||
'switch_to' => [
|
||||
// From editor, no security filters to security filters, no editor: no
|
||||
// risk.
|
||||
'restricted_without_editor' => FALSE,
|
||||
|
@ -377,9 +377,9 @@ class EditorSecurityTest extends WebTestBase {
|
|||
// filters: resulting content when viewed was already vulnerable, so
|
||||
// it must be intentional.
|
||||
'unrestricted_without_editor' => FALSE,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
// Log in as the privileged user, and for every sample, do the following:
|
||||
// - switch to every other text format/editor
|
||||
|
@ -395,15 +395,15 @@ class EditorSecurityTest extends WebTestBase {
|
|||
|
||||
// Switch to every other text format/editor and verify the results.
|
||||
foreach ($case['switch_to'] as $format => $expected_filtered_value) {
|
||||
$this->pass(format_string('Scenario: sample %sample_id, switch from %original_format to %format.', array(
|
||||
$this->pass(format_string('Scenario: sample %sample_id, switch from %original_format to %format.', [
|
||||
'%sample_id' => $case['node_id'],
|
||||
'%original_format' => $case['format'],
|
||||
'%format' => $format,
|
||||
)));
|
||||
$post = array(
|
||||
]));
|
||||
$post = [
|
||||
'value' => self::$sampleContent,
|
||||
'original_format_id' => $case['format'],
|
||||
);
|
||||
];
|
||||
$response = $this->drupalPostWithFormat('editor/filter_xss/' . $format, 'json', $post);
|
||||
$this->assertResponse(200);
|
||||
$json = Json::decode($response);
|
||||
|
@ -415,7 +415,7 @@ class EditorSecurityTest extends WebTestBase {
|
|||
/**
|
||||
* Tests the standard text editor XSS filter being overridden.
|
||||
*/
|
||||
function testEditorXssFilterOverride() {
|
||||
public function testEditorXssFilterOverride() {
|
||||
// First: the Standard text editor XSS filter.
|
||||
$this->drupalLogin($this->normalUser);
|
||||
$this->drupalGet('node/2/edit');
|
||||
|
|
|
@ -19,47 +19,47 @@ class QuickEditIntegrationLoadingTest extends WebTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('quickedit', 'filter', 'node', 'editor');
|
||||
public static $modules = ['quickedit', 'filter', 'node', 'editor'];
|
||||
|
||||
/**
|
||||
* The basic permissions necessary to view content and use in-place editing.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $basicPermissions = array('access content', 'create article content', 'use text format filtered_html', 'access contextual links');
|
||||
protected static $basicPermissions = ['access content', 'create article content', 'use text format filtered_html', 'access contextual links'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create a text format.
|
||||
$filtered_html_format = FilterFormat::create(array(
|
||||
$filtered_html_format = FilterFormat::create([
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
'weight' => 0,
|
||||
'filters' => array(
|
||||
'filter_caption' => array(
|
||||
'filters' => [
|
||||
'filter_caption' => [
|
||||
'status' => 1,
|
||||
),
|
||||
),
|
||||
));
|
||||
],
|
||||
],
|
||||
]);
|
||||
$filtered_html_format->save();
|
||||
|
||||
// Create a node type.
|
||||
$this->drupalCreateContentType(array(
|
||||
$this->drupalCreateContentType([
|
||||
'type' => 'article',
|
||||
'name' => 'Article',
|
||||
));
|
||||
]);
|
||||
|
||||
// Create one node of the above node type using the above text format.
|
||||
$this->drupalCreateNode(array(
|
||||
$this->drupalCreateNode([
|
||||
'type' => 'article',
|
||||
'body' => array(
|
||||
0 => array(
|
||||
'body' => [
|
||||
0 => [
|
||||
'value' => '<p>Do you also love Drupal?</p><img src="druplicon.png" data-caption="Druplicon" />',
|
||||
'format' => 'filtered_html',
|
||||
)
|
||||
)
|
||||
));
|
||||
]
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,11 +70,11 @@ class QuickEditIntegrationLoadingTest extends WebTestBase {
|
|||
// or both of the following permissions:
|
||||
// - the 'access in-place editing' permission
|
||||
// - the 'edit any article content' permission (necessary to edit node 1)
|
||||
$users = array(
|
||||
$users = [
|
||||
$this->drupalCreateUser(static::$basicPermissions),
|
||||
$this->drupalCreateUser(array_merge(static::$basicPermissions, array('edit any article content'))),
|
||||
$this->drupalCreateUser(array_merge(static::$basicPermissions, array('access in-place editing')))
|
||||
);
|
||||
$this->drupalCreateUser(array_merge(static::$basicPermissions, ['edit any article content'])),
|
||||
$this->drupalCreateUser(array_merge(static::$basicPermissions, ['access in-place editing']))
|
||||
];
|
||||
|
||||
// Now test with each of the 3 users with insufficient permissions.
|
||||
foreach ($users as $user) {
|
||||
|
@ -84,10 +84,17 @@ class QuickEditIntegrationLoadingTest extends WebTestBase {
|
|||
// Ensure the text is transformed.
|
||||
$this->assertRaw('<p>Do you also love Drupal?</p><figure role="group" class="caption caption-img"><img src="druplicon.png" /><figcaption>Druplicon</figcaption></figure>');
|
||||
|
||||
// Retrieving the untransformed text should result in an empty 403 response.
|
||||
$response = $this->drupalPost('editor/' . 'node/1/body/en/full', '', array(), array('query' => array(MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax')));
|
||||
// Retrieving the untransformed text should result in an 403 response and
|
||||
// return a different error message depending of the missing permission.
|
||||
$response = $this->drupalPost('editor/' . 'node/1/body/en/full', '', [], ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_ajax']]);
|
||||
$this->assertResponse(403);
|
||||
$this->assertIdentical('{}', $response);
|
||||
if (!$user->hasPermission('access in-place editing')) {
|
||||
$message = "A fatal error occurred: The 'access in-place editing' permission is required.";
|
||||
$this->assertIdentical(Json::encode(['message' => $message]), $response);
|
||||
}
|
||||
else {
|
||||
$this->assertIdentical('{}', $response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,7 +102,7 @@ class QuickEditIntegrationLoadingTest extends WebTestBase {
|
|||
* Test loading of untransformed text when a user does have access to it.
|
||||
*/
|
||||
public function testUserWithPermission() {
|
||||
$user = $this->drupalCreateUser(array_merge(static::$basicPermissions, array('edit any article content', 'access in-place editing')));
|
||||
$user = $this->drupalCreateUser(array_merge(static::$basicPermissions, ['edit any article content', 'access in-place editing']));
|
||||
$this->drupalLogin($user);
|
||||
$this->drupalGet('node/1');
|
||||
|
||||
|
|
|
@ -26,18 +26,18 @@ class TRexEditor extends EditorBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefaultSettings() {
|
||||
return array('stumpy_arms' => TRUE);
|
||||
return ['stumpy_arms' => TRUE];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
|
||||
$form['stumpy_arms'] = array(
|
||||
$form['stumpy_arms'] = [
|
||||
'#title' => t('Stumpy arms'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => TRUE,
|
||||
);
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ class TRexEditor extends EditorBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getJSSettings(Editor $editor) {
|
||||
$js_settings = array();
|
||||
$js_settings = [];
|
||||
$settings = $editor->getSettings();
|
||||
if ($settings['stumpy_arms']) {
|
||||
$js_settings['doMyArmsLookStumpy'] = TRUE;
|
||||
|
@ -57,9 +57,9 @@ class TRexEditor extends EditorBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLibraries(Editor $editor) {
|
||||
return array(
|
||||
return [
|
||||
'editor_test/trex',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,27 +26,27 @@ class UnicornEditor extends EditorBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getDefaultSettings() {
|
||||
return array('ponies_too' => TRUE);
|
||||
public function getDefaultSettings() {
|
||||
return ['ponies_too' => TRUE];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
|
||||
$form['ponies_too'] = array(
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
|
||||
$form['ponies_too'] = [
|
||||
'#title' => t('Pony mode'),
|
||||
'#type' => 'checkbox',
|
||||
'#default_value' => TRUE,
|
||||
);
|
||||
];
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getJSSettings(Editor $editor) {
|
||||
$js_settings = array();
|
||||
public function getJSSettings(Editor $editor) {
|
||||
$js_settings = [];
|
||||
$settings = $editor->getSettings();
|
||||
if ($settings['ponies_too']) {
|
||||
$js_settings['ponyModeEnabled'] = TRUE;
|
||||
|
@ -58,9 +58,9 @@ class UnicornEditor extends EditorBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLibraries(Editor $editor) {
|
||||
return array(
|
||||
return [
|
||||
'editor_test/unicorn',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\editor\Tests;
|
||||
namespace Drupal\Tests\editor\Functional;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\editor\Entity\Editor;
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\editor\Tests;
|
||||
namespace Drupal\Tests\editor\Functional;
|
||||
|
||||
use Drupal\file\Entity\File;
|
||||
use Drupal\Tests\BrowserTestBase;
|
||||
|
@ -36,7 +36,7 @@ class EditorPrivateFileReferenceFilterTest extends BrowserTestBase {
|
|||
/**
|
||||
* Tests the editor file reference filter with private files.
|
||||
*/
|
||||
function testEditorPrivateFileReferenceFilter() {
|
||||
public function testEditorPrivateFileReferenceFilter() {
|
||||
$author = $this->drupalCreateUser();
|
||||
$this->drupalLogin($author);
|
||||
|
|
@ -19,7 +19,7 @@ class EditorFileReferenceFilterTest extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('system', 'filter', 'editor', 'field', 'file', 'user');
|
||||
public static $modules = ['system', 'filter', 'editor', 'field', 'file', 'user'];
|
||||
|
||||
/**
|
||||
* @var \Drupal\filter\Plugin\FilterInterface[]
|
||||
|
@ -31,19 +31,19 @@ class EditorFileReferenceFilterTest extends KernelTestBase {
|
|||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installConfig(array('system'));
|
||||
$this->installConfig(['system']);
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
|
||||
$manager = $this->container->get('plugin.manager.filter');
|
||||
$bag = new FilterPluginCollection($manager, array());
|
||||
$bag = new FilterPluginCollection($manager, []);
|
||||
$this->filters = $bag->getAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the editor file reference filter.
|
||||
*/
|
||||
function testEditorFileReferenceFilter() {
|
||||
public function testEditorFileReferenceFilter() {
|
||||
$filter = $this->filters['editor_file_reference'];
|
||||
|
||||
$test = function($input) use ($filter) {
|
||||
|
@ -99,7 +99,7 @@ class EditorFileReferenceFilterTest extends KernelTestBase {
|
|||
$input = '<img src="llama.jpg" data-entity-type="file" data-entity-uuid="invalid-' . $uuid . '" />';
|
||||
$output = $test($input);
|
||||
$this->assertIdentical($input, $output->getProcessedText());
|
||||
$this->assertEqual(array(), $output->getCacheTags());
|
||||
$this->assertEqual([], $output->getCacheTags());
|
||||
|
||||
$this->pass('Two different data-entity-uuid attributes.');
|
||||
$input = '<img src="llama.jpg" data-entity-type="file" data-entity-uuid="' . $uuid . '" />';
|
||||
|
|
|
@ -23,22 +23,22 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('editor', 'editor_test', 'node', 'file');
|
||||
public static $modules = ['editor', 'editor_test', 'node', 'file'];
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('node', array('node_access'));
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
$this->installSchema('node', ['node_access']);
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
$this->installConfig(['node']);
|
||||
|
||||
// Add text formats.
|
||||
$filtered_html_format = FilterFormat::create(array(
|
||||
$filtered_html_format = FilterFormat::create([
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
'weight' => 0,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$filtered_html_format->save();
|
||||
|
||||
// Set cardinality for body field.
|
||||
|
@ -63,13 +63,13 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
* Tests the configurable text editor manager.
|
||||
*/
|
||||
public function testEditorEntityHooks() {
|
||||
$image_paths = array(
|
||||
$image_paths = [
|
||||
0 => 'core/misc/druplicon.png',
|
||||
1 => 'core/misc/tree.png',
|
||||
2 => 'core/misc/help.png',
|
||||
);
|
||||
];
|
||||
|
||||
$image_entities = array();
|
||||
$image_entities = [];
|
||||
foreach ($image_paths as $key => $image_path) {
|
||||
$image = File::create();
|
||||
$image->setFileUri($image_path);
|
||||
|
@ -77,12 +77,12 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
$image->save();
|
||||
|
||||
$file_usage = $this->container->get('file.usage');
|
||||
$this->assertIdentical(array(), $file_usage->listUsage($image), 'The image ' . $image_paths[$key] . ' has zero usages.');
|
||||
$this->assertIdentical([], $file_usage->listUsage($image), 'The image ' . $image_paths[$key] . ' has zero usages.');
|
||||
|
||||
$image_entities[] = $image;
|
||||
}
|
||||
|
||||
$body = array();
|
||||
$body = [];
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
// Don't be rude, say hello.
|
||||
$body_value = '<p>Hello, world!</p>';
|
||||
|
@ -95,10 +95,10 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
// Test handling of a non-existing UUID.
|
||||
$body_value .= '<img src="awesome-llama-' . $key . '.jpg" data-entity-type="file" data-entity-uuid="30aac704-ba2c-40fc-b609-9ed121aa90f4" />';
|
||||
|
||||
$body[] = array(
|
||||
$body[] = [
|
||||
'value' => $body_value,
|
||||
'format' => 'filtered_html',
|
||||
);
|
||||
];
|
||||
}
|
||||
|
||||
// Test editor_entity_insert(): increment.
|
||||
|
@ -111,7 +111,7 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
]);
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '1'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 1 usage.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '1']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 1 usage.');
|
||||
}
|
||||
|
||||
// Test editor_entity_update(): increment, twice, by creating new revisions.
|
||||
|
@ -121,12 +121,12 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
$node->setNewRevision(TRUE);
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '3'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '3']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
}
|
||||
|
||||
// Test hook_entity_update(): decrement, by modifying the last revision:
|
||||
// remove the data-entity-type attribute from the body field.
|
||||
$original_values = array();
|
||||
$original_values = [];
|
||||
for ($i = 0; $i < count($image_entities); $i++) {
|
||||
$original_value = $node->body[$i]->value;
|
||||
$new_value = str_replace('data-entity-type', 'data-entity-type-modified', $original_value);
|
||||
|
@ -135,7 +135,7 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '2']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
}
|
||||
|
||||
// Test editor_entity_update(): increment again by creating a new revision:
|
||||
|
@ -146,7 +146,7 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '3'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '3']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
}
|
||||
|
||||
// Test hook_entity_update(): decrement, by modifying the last revision:
|
||||
|
@ -158,7 +158,7 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '2']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
}
|
||||
|
||||
// Test hook_entity_update(): increment, by modifying the last revision:
|
||||
|
@ -168,13 +168,13 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '3'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '3']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 3 usages.');
|
||||
}
|
||||
|
||||
// Test editor_entity_revision_delete(): decrement, by deleting a revision.
|
||||
entity_revision_delete('node', $second_revision_id);
|
||||
$this->container->get('entity_type.manager')->getStorage('node')->deleteRevision($second_revision_id);
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '2']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
}
|
||||
|
||||
// Populate both the body and summary. Because this will be the same
|
||||
|
@ -185,7 +185,7 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '2']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
}
|
||||
|
||||
// Empty out the body value, but keep the summary. The number of usages
|
||||
|
@ -196,13 +196,13 @@ class EditorFileUsageTest extends EntityKernelTestBase {
|
|||
}
|
||||
$node->save();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array('editor' => array('node' => array(1 => '2'))), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
$this->assertIdentical(['editor' => ['node' => [1 => '2']]], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has 2 usages.');
|
||||
}
|
||||
|
||||
// Test editor_entity_delete().
|
||||
$node->delete();
|
||||
foreach ($image_entities as $key => $image_entity) {
|
||||
$this->assertIdentical(array(), $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has zero usages again.');
|
||||
$this->assertIdentical([], $file_usage->listUsage($image_entity), 'The image ' . $image_paths[$key] . ' has zero usages again.');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,8 @@ class EditorImageDialogTest extends EntityKernelTestBase {
|
|||
parent::setUp();
|
||||
$this->installEntitySchema('file');
|
||||
$this->installSchema('system', ['key_value_expire']);
|
||||
$this->installSchema('node', array('node_access'));
|
||||
$this->installSchema('file', array('file_usage'));
|
||||
$this->installSchema('node', ['node_access']);
|
||||
$this->installSchema('file', ['file_usage']);
|
||||
$this->installConfig(['node']);
|
||||
|
||||
// Add text formats.
|
||||
|
|
|
@ -18,7 +18,7 @@ class EditorManagerTest extends KernelTestBase {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array('system', 'user', 'filter', 'editor');
|
||||
public static $modules = ['system', 'user', 'filter', 'editor'];
|
||||
|
||||
/**
|
||||
* The manager for text editor plugins.
|
||||
|
@ -33,19 +33,19 @@ class EditorManagerTest extends KernelTestBase {
|
|||
// Install the Filter module.
|
||||
|
||||
// Add text formats.
|
||||
$filtered_html_format = FilterFormat::create(array(
|
||||
$filtered_html_format = FilterFormat::create([
|
||||
'format' => 'filtered_html',
|
||||
'name' => 'Filtered HTML',
|
||||
'weight' => 0,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$filtered_html_format->save();
|
||||
$full_html_format = FilterFormat::create(array(
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
'weight' => 1,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$full_html_format->save();
|
||||
}
|
||||
|
||||
|
@ -59,13 +59,13 @@ class EditorManagerTest extends KernelTestBase {
|
|||
// - listOptions() should return an empty list of options
|
||||
// - getAttachments() should return an empty #attachments array (and not
|
||||
// a JS settings structure that is empty)
|
||||
$this->assertIdentical(array(), $this->editorManager->listOptions(), 'When no text editor is enabled, the manager works correctly.');
|
||||
$this->assertIdentical(array(), $this->editorManager->getAttachments(array()), 'No attachments when no text editor is enabled and retrieving attachments for zero text formats.');
|
||||
$this->assertIdentical(array(), $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'No attachments when no text editor is enabled and retrieving attachments for multiple text formats.');
|
||||
$this->assertIdentical([], $this->editorManager->listOptions(), 'When no text editor is enabled, the manager works correctly.');
|
||||
$this->assertIdentical([], $this->editorManager->getAttachments([]), 'No attachments when no text editor is enabled and retrieving attachments for zero text formats.');
|
||||
$this->assertIdentical([], $this->editorManager->getAttachments(['filtered_html', 'full_html']), 'No attachments when no text editor is enabled and retrieving attachments for multiple text formats.');
|
||||
|
||||
// Enable the Text Editor Test module, which has the Unicorn Editor and
|
||||
// clear the editor manager's cache so it is picked up.
|
||||
$this->enableModules(array('editor_test'));
|
||||
$this->enableModules(['editor_test']);
|
||||
$this->editorManager = $this->container->get('plugin.manager.editor');
|
||||
$this->editorManager->clearCachedDefinitions();
|
||||
|
||||
|
@ -80,11 +80,11 @@ class EditorManagerTest extends KernelTestBase {
|
|||
'editor' => 'unicorn',
|
||||
]);
|
||||
$editor->save();
|
||||
$this->assertIdentical(array(), $this->editorManager->getAttachments(array()), 'No attachments when one text editor is enabled and retrieving attachments for zero text formats.');
|
||||
$expected = array(
|
||||
'library' => array(
|
||||
$this->assertIdentical([], $this->editorManager->getAttachments([]), 'No attachments when one text editor is enabled and retrieving attachments for zero text formats.');
|
||||
$expected = [
|
||||
'library' => [
|
||||
0 => 'editor_test/unicorn',
|
||||
),
|
||||
],
|
||||
'drupalSettings' => [
|
||||
'editor' => [
|
||||
'formats' => [
|
||||
|
@ -98,14 +98,14 @@ class EditorManagerTest extends KernelTestBase {
|
|||
],
|
||||
],
|
||||
],
|
||||
);
|
||||
$this->assertIdentical($expected, $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'Correct attachments when one text editor is enabled and retrieving attachments for multiple text formats.');
|
||||
];
|
||||
$this->assertIdentical($expected, $this->editorManager->getAttachments(['filtered_html', 'full_html']), 'Correct attachments when one text editor is enabled and retrieving attachments for multiple text formats.');
|
||||
|
||||
// Case 4: a text editor available associated, but now with its JS settings
|
||||
// being altered via hook_editor_js_settings_alter().
|
||||
\Drupal::state()->set('editor_test_js_settings_alter_enabled', TRUE);
|
||||
$expected['drupalSettings']['editor']['formats']['full_html']['editorSettings']['ponyModeEnabled'] = FALSE;
|
||||
$this->assertIdentical($expected, $this->editorManager->getAttachments(array('filtered_html', 'full_html')), 'hook_editor_js_settings_alter() works correctly.');
|
||||
$this->assertIdentical($expected, $this->editorManager->getAttachments(['filtered_html', 'full_html']), 'hook_editor_js_settings_alter() works correctly.');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = array('editor', 'editor_test');
|
||||
public static $modules = ['editor', 'editor_test'];
|
||||
|
||||
/**
|
||||
* The manager for editor plug-ins.
|
||||
|
@ -73,22 +73,22 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
$this->createFieldWithStorage(
|
||||
$this->fieldName, 'text', 1, 'Long text field',
|
||||
// Instance settings.
|
||||
array(),
|
||||
[],
|
||||
// Widget type & settings.
|
||||
'text_textarea',
|
||||
array('size' => 42),
|
||||
['size' => 42],
|
||||
// 'default' formatter type & settings.
|
||||
'text_default',
|
||||
array()
|
||||
[]
|
||||
);
|
||||
|
||||
// Create text format.
|
||||
$full_html_format = FilterFormat::create(array(
|
||||
$full_html_format = FilterFormat::create([
|
||||
'format' => 'full_html',
|
||||
'name' => 'Full HTML',
|
||||
'weight' => 1,
|
||||
'filters' => array(),
|
||||
));
|
||||
'filters' => [],
|
||||
]);
|
||||
$full_html_format->save();
|
||||
|
||||
// Associate text editor with text format.
|
||||
|
@ -99,12 +99,12 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
$editor->save();
|
||||
|
||||
// Also create a text format without an associated text editor.
|
||||
FilterFormat::create(array(
|
||||
FilterFormat::create([
|
||||
'format' => 'no_editor',
|
||||
'name' => 'No Text Editor',
|
||||
'weight' => 2,
|
||||
'filters' => array(),
|
||||
))->save();
|
||||
'filters' => [],
|
||||
])->save();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -179,15 +179,15 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
// Verify metadata.
|
||||
$items = $entity->get($this->fieldName);
|
||||
$metadata = $this->metadataGenerator->generateFieldMetadata($items, 'default');
|
||||
$expected = array(
|
||||
$expected = [
|
||||
'access' => TRUE,
|
||||
'label' => 'Long text field',
|
||||
'editor' => 'editor',
|
||||
'custom' => array(
|
||||
'custom' => [
|
||||
'format' => 'full_html',
|
||||
'formatHasTransformations' => FALSE,
|
||||
),
|
||||
);
|
||||
],
|
||||
];
|
||||
$this->assertEqual($expected, $metadata, 'The correct metadata (including custom metadata) is generated.');
|
||||
}
|
||||
|
||||
|
@ -197,9 +197,9 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
public function testAttachments() {
|
||||
$this->editorSelector = $this->container->get('quickedit.editor.selector');
|
||||
|
||||
$editors = array('editor');
|
||||
$editors = ['editor'];
|
||||
$attachments = $this->editorSelector->getEditorAttachments($editors);
|
||||
$this->assertIdentical($attachments, array('library' => array('editor/quickedit.inPlaceEditor.formattedText')), "Expected attachments for Editor module's in-place editor found.");
|
||||
$this->assertIdentical($attachments, ['library' => ['editor/quickedit.inPlaceEditor.formattedText']], "Expected attachments for Editor module's in-place editor found.");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,12 +217,12 @@ class QuickEditIntegrationTest extends QuickEditTestBase {
|
|||
$controller = new EditorController();
|
||||
$request = new Request();
|
||||
$response = $controller->getUntransformedText($entity, $this->fieldName, LanguageInterface::LANGCODE_DEFAULT, 'default');
|
||||
$expected = array(
|
||||
array(
|
||||
$expected = [
|
||||
[
|
||||
'command' => 'editorGetUntransformedText',
|
||||
'data' => 'Test',
|
||||
)
|
||||
);
|
||||
]
|
||||
];
|
||||
|
||||
$ajax_response_attachments_processor = \Drupal::service('ajax_response.attachments_processor');
|
||||
$subscriber = new AjaxResponseSubscriber($ajax_response_attachments_processor);
|
||||
|
|
75
web/core/modules/editor/tests/src/Unit/EditorBaseTest.php
Normal file
75
web/core/modules/editor/tests/src/Unit/EditorBaseTest.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\editor\Unit;
|
||||
|
||||
use Drupal\Core\Form\FormState;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
use Drupal\editor\Entity\Editor;
|
||||
use Drupal\editor\Plugin\EditorBase;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\editor\Plugin\EditorBase
|
||||
* @group editor
|
||||
*/
|
||||
class EditorBaseTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::buildConfigurationForm
|
||||
* @covers ::validateConfigurationForm
|
||||
* @covers ::submitConfigurationForm
|
||||
*/
|
||||
public function testBc() {
|
||||
$form_state = new FormState();
|
||||
$form_state->set('editor', $this->prophesize(Editor::class)->reveal());
|
||||
$editor_plugin = new BcEditor([], 'editor_plugin', []);
|
||||
|
||||
// settingsForm() is deprecated in favor of buildConfigurationForm().
|
||||
$this->assertSame(
|
||||
$editor_plugin->settingsForm([], clone $form_state, $this->prophesize(Editor::class)->reveal()),
|
||||
$editor_plugin->buildConfigurationForm([], clone $form_state)
|
||||
);
|
||||
|
||||
// settingsFormValidate() is deprecated in favor of
|
||||
// validateConfigurationForm().
|
||||
$form = [];
|
||||
$form_state_a = clone $form_state;
|
||||
$form_state_b = clone $form_state;
|
||||
$editor_plugin->settingsFormValidate($form, $form_state_a, $this->prophesize(Editor::class)->reveal());
|
||||
$editor_plugin->validateConfigurationForm($form, $form_state_b);
|
||||
$this->assertEquals($form_state_a, $form_state_b);
|
||||
|
||||
// settingsFormSubmit() is deprecated in favor of submitConfigurationForm().
|
||||
$form = [];
|
||||
$form_state_a = clone $form_state;
|
||||
$form_state_b = clone $form_state;
|
||||
$editor_plugin->settingsFormSubmit($form, $form_state_a, $this->prophesize(Editor::class)->reveal());
|
||||
$editor_plugin->submitConfigurationForm($form, $form_state_b);
|
||||
$this->assertEquals($form_state_a, $form_state_b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class BcEditor extends EditorBase {
|
||||
|
||||
public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
|
||||
return ['foo' => 'bar'];
|
||||
}
|
||||
|
||||
public function settingsFormValidate(array $form, FormStateInterface $form_state) {
|
||||
$form_state->setValue('foo', 'bar');
|
||||
}
|
||||
|
||||
public function settingsFormSubmit(array $form, FormStateInterface $form_state) {
|
||||
$form_state->setValue('bar', 'baz');
|
||||
}
|
||||
|
||||
public function getJSSettings(Editor $editor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getLibraries(Editor $editor) {
|
||||
return [];
|
||||
}
|
||||
|
||||
}
|
|
@ -90,17 +90,17 @@ class EditorConfigEntityUnitTest extends UnitTestCase {
|
|||
*/
|
||||
public function testCalculateDependencies() {
|
||||
$format_id = 'filter.format.test';
|
||||
$values = array('editor' => $this->editorId, 'format' => $format_id);
|
||||
$values = ['editor' => $this->editorId, 'format' => $format_id];
|
||||
|
||||
$plugin = $this->getMockBuilder('Drupal\editor\Plugin\EditorPluginInterface')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$plugin->expects($this->once())
|
||||
->method('getPluginDefinition')
|
||||
->will($this->returnValue(array('provider' => 'test_module')));
|
||||
->will($this->returnValue(['provider' => 'test_module']));
|
||||
$plugin->expects($this->once())
|
||||
->method('getDefaultSettings')
|
||||
->will($this->returnValue(array()));
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$this->editorPluginManager->expects($this->any())
|
||||
->method('createInstance')
|
||||
|
@ -116,14 +116,14 @@ class EditorConfigEntityUnitTest extends UnitTestCase {
|
|||
|
||||
$storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
|
||||
$storage->expects($this->once())
|
||||
->method('load')
|
||||
->with($format_id)
|
||||
->will($this->returnValue($filter_format));
|
||||
->method('load')
|
||||
->with($format_id)
|
||||
->will($this->returnValue($filter_format));
|
||||
|
||||
$this->entityManager->expects($this->once())
|
||||
->method('getStorage')
|
||||
->with('filter_format')
|
||||
->will($this->returnValue($storage));
|
||||
->method('getStorage')
|
||||
->with('filter_format')
|
||||
->will($this->returnValue($storage));
|
||||
|
||||
$dependencies = $entity->calculateDependencies()->getDependencies();
|
||||
$this->assertContains('test_module', $dependencies['module']);
|
||||
|
|
|
@ -27,17 +27,17 @@ class StandardTest extends UnitTestCase {
|
|||
->getMock();
|
||||
$this->format->expects($this->any())
|
||||
->method('getFilterTypes')
|
||||
->will($this->returnValue(array(FilterInterface::TYPE_HTML_RESTRICTOR)));
|
||||
$restrictions = array(
|
||||
'allowed' => array(
|
||||
->will($this->returnValue([FilterInterface::TYPE_HTML_RESTRICTOR]));
|
||||
$restrictions = [
|
||||
'allowed' => [
|
||||
'p' => TRUE,
|
||||
'a' => TRUE,
|
||||
'*' => array(
|
||||
'*' => [
|
||||
'style' => FALSE,
|
||||
'on*' => FALSE,
|
||||
),
|
||||
),
|
||||
);
|
||||
],
|
||||
],
|
||||
];
|
||||
$this->format->expects($this->any())
|
||||
->method('getHtmlRestrictions')
|
||||
->will($this->returnValue($restrictions));
|
||||
|
@ -49,130 +49,130 @@ class StandardTest extends UnitTestCase {
|
|||
* @see \Drupal\Tests\editor\Unit\editor\EditorXssFilter\StandardTest::testFilterXss()
|
||||
*/
|
||||
public function providerTestFilterXss() {
|
||||
$data = array();
|
||||
$data[] = array('<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>');
|
||||
$data[] = array('<p style="color:red">Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>');
|
||||
$data[] = array('<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><script>alert("evil");</script>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>alert("evil");');
|
||||
$data[] = array('<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><a href="javascript:alert(1)">test</a>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><a href="alert(1)">test</a>');
|
||||
$data = [];
|
||||
$data[] = ['<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>'];
|
||||
$data[] = ['<p style="color:red">Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>'];
|
||||
$data[] = ['<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><script>alert("evil");</script>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown>alert("evil");'];
|
||||
$data[] = ['<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><a href="javascript:alert(1)">test</a>', '<p>Hello, world!</p><unknown>Pink Fairy Armadillo</unknown><a href="alert(1)">test</a>'];
|
||||
|
||||
// All cases listed on https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
|
||||
|
||||
// No Filter Evasion.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#No_Filter_Evasion
|
||||
$data[] = array('<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>', '');
|
||||
$data[] = ['<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>', ''];
|
||||
|
||||
// Image XSS using the JavaScript directive.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Image_XSS_using_the_JavaScript_directive
|
||||
$data[] = array('<IMG SRC="javascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="javascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
|
||||
// No quotes and no semicolon.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#No_quotes_and_no_semicolon
|
||||
$data[] = array('<IMG SRC=javascript:alert(\'XSS\')>', '<IMG>');
|
||||
$data[] = ['<IMG SRC=javascript:alert(\'XSS\')>', '<IMG>'];
|
||||
|
||||
// Case insensitive XSS attack vector.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Case_insensitive_XSS_attack_vector
|
||||
$data[] = array('<IMG SRC=JaVaScRiPt:alert(\'XSS\')>', '<IMG>');
|
||||
$data[] = ['<IMG SRC=JaVaScRiPt:alert(\'XSS\')>', '<IMG>'];
|
||||
|
||||
// HTML entities.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#HTML_entities
|
||||
$data[] = array('<IMG SRC=javascript:alert("XSS")>', '<IMG>');
|
||||
$data[] = ['<IMG SRC=javascript:alert("XSS")>', '<IMG>'];
|
||||
|
||||
// Grave accent obfuscation.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Grave_accent_obfuscation
|
||||
$data[] = array('<IMG SRC=`javascript:alert("RSnake says, \'XSS\'")`>', '<IMG>');
|
||||
$data[] = ['<IMG SRC=`javascript:alert("RSnake says, \'XSS\'")`>', '<IMG>'];
|
||||
|
||||
// Malformed A tags.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Malformed_A_tags
|
||||
$data[] = array('<a onmouseover="alert(document.cookie)">xxs link</a>', '<a>xxs link</a>');
|
||||
$data[] = array('<a onmouseover=alert(document.cookie)>xxs link</a>', '<a>xxs link</a>');
|
||||
$data[] = ['<a onmouseover="alert(document.cookie)">xxs link</a>', '<a>xxs link</a>'];
|
||||
$data[] = ['<a onmouseover=alert(document.cookie)>xxs link</a>', '<a>xxs link</a>'];
|
||||
|
||||
// Malformed IMG tags.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Malformed_IMG_tags
|
||||
$data[] = array('<IMG """><SCRIPT>alert("XSS")</SCRIPT>">', '<IMG>alert("XSS")">');
|
||||
$data[] = ['<IMG """><SCRIPT>alert("XSS")</SCRIPT>">', '<IMG>alert("XSS")">'];
|
||||
|
||||
// fromCharCode.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#fromCharCode
|
||||
$data[] = array('<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>', '<IMG src="alert(String.fromCharCode(88,83,83))">');
|
||||
$data[] = ['<IMG SRC=javascript:alert(String.fromCharCode(88,83,83))>', '<IMG src="alert(String.fromCharCode(88,83,83))">'];
|
||||
|
||||
// Default SRC tag to get past filters that check SRC domain.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Default_SRC_tag_to_get_past_filters_that_check_SRC_domain
|
||||
$data[] = array('<IMG SRC=# onmouseover="alert(\'xxs\')">', '<IMG src="#">');
|
||||
$data[] = ['<IMG SRC=# onmouseover="alert(\'xxs\')">', '<IMG src="#">'];
|
||||
|
||||
// Default SRC tag by leaving it empty.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Default_SRC_tag_by_leaving_it_empty
|
||||
$data[] = array('<IMG SRC= onmouseover="alert(\'xxs\')">', '<IMG nmouseover="alert('xxs')">');
|
||||
$data[] = ['<IMG SRC= onmouseover="alert(\'xxs\')">', '<IMG nmouseover="alert('xxs')">'];
|
||||
|
||||
// Default SRC tag by leaving it out entirely.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Default_SRC_tag_by_leaving_it_out_entirely
|
||||
$data[] = array('<IMG onmouseover="alert(\'xxs\')">', '<IMG>');
|
||||
$data[] = ['<IMG onmouseover="alert(\'xxs\')">', '<IMG>'];
|
||||
|
||||
// Decimal HTML character references.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Decimal_HTML_character_references
|
||||
$data[] = array('<IMG SRC=javascript:alert('XSS')>', '<IMG src="alert('XSS')">');
|
||||
$data[] = ['<IMG SRC=javascript:alert('XSS')>', '<IMG src="alert('XSS')">'];
|
||||
|
||||
// Decimal HTML character references without trailing semicolons.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Decimal_HTML_character_references_without_trailing_semicolons
|
||||
$data[] = array('<IMG SRC=javascript:alert('XSS')>', '<IMG src="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041">');
|
||||
$data[] = ['<IMG SRC=javascript:alert('XSS')>', '<IMG src="&#0000106&#0000097&#0000118&#0000097&#0000115&#0000099&#0000114&#0000105&#0000112&#0000116&#0000058&#0000097&#0000108&#0000101&#0000114&#0000116&#0000040&#0000039&#0000088&#0000083&#0000083&#0000039&#0000041">'];
|
||||
|
||||
// Hexadecimal HTML character references without trailing semicolons.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Hexadecimal_HTML_character_references_without_trailing_semicolons
|
||||
$data[] = array('<IMG SRC=javascript:alert('XSS')>', '<IMG src="&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29">');
|
||||
$data[] = ['<IMG SRC=javascript:alert('XSS')>', '<IMG src="&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29">'];
|
||||
|
||||
// Embedded tab.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_tab
|
||||
$data[] = array('<IMG SRC="jav ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="jav ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
|
||||
// Embedded Encoded tab.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_Encoded_tab
|
||||
$data[] = array('<IMG SRC="jav	ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="jav	ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
|
||||
// Embedded newline to break up XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_newline_to_break_up_XSS
|
||||
$data[] = array('<IMG SRC="jav
ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="jav
ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
|
||||
// Embedded carriage return to break up XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Embedded_carriage_return_to_break_up_XSS
|
||||
$data[] = array('<IMG SRC="jav
ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="jav
ascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
|
||||
// Null breaks up JavaScript directive.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Null_breaks_up_JavaScript_directive
|
||||
$data[] = array("<IMG SRC=java\0script:alert(\"XSS\")>", '<IMG>');
|
||||
$data[] = ["<IMG SRC=java\0script:alert(\"XSS\")>", '<IMG>'];
|
||||
|
||||
// Spaces and meta chars before the JavaScript in images for XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Spaces_and_meta_chars_before_the_JavaScript_in_images_for_XSS
|
||||
// @fixme This dataset currently fails under 5.4 because of
|
||||
// https://www.drupal.org/node/1210798. Restore after it's fixed.
|
||||
if (version_compare(PHP_VERSION, '5.4.0', '<')) {
|
||||
$data[] = array('<IMG SRC="  javascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">');
|
||||
$data[] = ['<IMG SRC="  javascript:alert(\'XSS\');">', '<IMG src="alert('XSS');">'];
|
||||
}
|
||||
|
||||
// Non-alpha-non-digit XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Non-alpha-non-digit_XSS
|
||||
$data[] = array('<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '');
|
||||
$data[] = array('<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>', '<BODY>');
|
||||
$data[] = array('<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '');
|
||||
$data[] = ['<SCRIPT/XSS SRC="http://ha.ckers.org/xss.js"></SCRIPT>', ''];
|
||||
$data[] = ['<BODY onload!#$%&()*~+-_.,:;?@[/|\]^`=alert("XSS")>', '<BODY>'];
|
||||
$data[] = ['<SCRIPT/SRC="http://ha.ckers.org/xss.js"></SCRIPT>', ''];
|
||||
|
||||
// Extraneous open brackets.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Extraneous_open_brackets
|
||||
$data[] = array('<<SCRIPT>alert("XSS");//<</SCRIPT>', '<alert("XSS");//<');
|
||||
$data[] = ['<<SCRIPT>alert("XSS");//<</SCRIPT>', '<alert("XSS");//<'];
|
||||
|
||||
// No closing script tags.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#No_closing_script_tags
|
||||
$data[] = array('<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >', '');
|
||||
$data[] = ['<SCRIPT SRC=http://ha.ckers.org/xss.js?< B >', ''];
|
||||
|
||||
// Protocol resolution in script tags.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Protocol_resolution_in_script_tags
|
||||
$data[] = array('<SCRIPT SRC=//ha.ckers.org/.j>', '');
|
||||
$data[] = ['<SCRIPT SRC=//ha.ckers.org/.j>', ''];
|
||||
|
||||
// Half open HTML/JavaScript XSS vector.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Half_open_HTML.2FJavaScript_XSS_vector
|
||||
$data[] = array('<IMG SRC="javascript:alert(\'XSS\')"', '<IMG src="alert('XSS')">');
|
||||
$data[] = ['<IMG SRC="javascript:alert(\'XSS\')"', '<IMG src="alert('XSS')">'];
|
||||
|
||||
// Double open angle brackets.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Double_open_angle_brackets
|
||||
// @see http://ha.ckers.org/blog/20060611/hotbot-xss-vulnerability/ to
|
||||
// understand why this is a vulnerability.
|
||||
$data[] = array('<iframe src=http://ha.ckers.org/scriptlet.html <', '<iframe src="http://ha.ckers.org/scriptlet.html">');
|
||||
$data[] = ['<iframe src=http://ha.ckers.org/scriptlet.html <', '<iframe src="http://ha.ckers.org/scriptlet.html">'];
|
||||
|
||||
// Escaping JavaScript escapes.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Escaping_JavaScript_escapes
|
||||
|
@ -181,43 +181,43 @@ class StandardTest extends UnitTestCase {
|
|||
|
||||
// End title tag.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#End_title_tag
|
||||
$data[] = array('</TITLE><SCRIPT>alert("XSS");</SCRIPT>', '</TITLE>alert("XSS");');
|
||||
$data[] = ['</TITLE><SCRIPT>alert("XSS");</SCRIPT>', '</TITLE>alert("XSS");'];
|
||||
|
||||
// INPUT image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#INPUT_image
|
||||
$data[] = array('<INPUT TYPE="IMAGE" SRC="javascript:alert(\'XSS\');">', '<INPUT type="IMAGE" src="alert('XSS');">');
|
||||
$data[] = ['<INPUT TYPE="IMAGE" SRC="javascript:alert(\'XSS\');">', '<INPUT type="IMAGE" src="alert('XSS');">'];
|
||||
|
||||
// BODY image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#BODY_image
|
||||
$data[] = array('<BODY BACKGROUND="javascript:alert(\'XSS\')">', '<BODY background="alert('XSS')">');
|
||||
$data[] = ['<BODY BACKGROUND="javascript:alert(\'XSS\')">', '<BODY background="alert('XSS')">'];
|
||||
|
||||
// IMG Dynsrc.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IMG_Dynsrc
|
||||
$data[] = array('<IMG DYNSRC="javascript:alert(\'XSS\')">', '<IMG dynsrc="alert('XSS')">');
|
||||
$data[] = ['<IMG DYNSRC="javascript:alert(\'XSS\')">', '<IMG dynsrc="alert('XSS')">'];
|
||||
|
||||
// IMG lowsrc.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IMG_lowsrc
|
||||
$data[] = array('<IMG LOWSRC="javascript:alert(\'XSS\')">', '<IMG lowsrc="alert('XSS')">');
|
||||
$data[] = ['<IMG LOWSRC="javascript:alert(\'XSS\')">', '<IMG lowsrc="alert('XSS')">'];
|
||||
|
||||
// List-style-image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#List-style-image
|
||||
$data[] = array('<STYLE>li {list-style-image: url("javascript:alert(\'XSS\')");}</STYLE><UL><LI>XSS</br>', 'li {list-style-image: url("javascript:alert(\'XSS\')");}<UL><LI>XSS</br>');
|
||||
$data[] = ['<STYLE>li {list-style-image: url("javascript:alert(\'XSS\')");}</STYLE><UL><LI>XSS</br>', 'li {list-style-image: url("javascript:alert(\'XSS\')");}<UL><LI>XSS</br>'];
|
||||
|
||||
// VBscript in an image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#VBscript_in_an_image
|
||||
$data[] = array('<IMG SRC=\'vbscript:msgbox("XSS")\'>', '<IMG src=\'msgbox("XSS")\'>');
|
||||
$data[] = ['<IMG SRC=\'vbscript:msgbox("XSS")\'>', '<IMG src=\'msgbox("XSS")\'>'];
|
||||
|
||||
// Livescript (older versions of Netscape only).
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Livescript_.28older_versions_of_Netscape_only.29
|
||||
$data[] = array('<IMG SRC="livescript:[code]">', '<IMG src="[code]">');
|
||||
$data[] = ['<IMG SRC="livescript:[code]">', '<IMG src="[code]">'];
|
||||
|
||||
// BODY tag.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#BODY_tag
|
||||
$data[] = array('<BODY ONLOAD=alert(\'XSS\')>', '<BODY>');
|
||||
$data[] = ['<BODY ONLOAD=alert(\'XSS\')>', '<BODY>'];
|
||||
|
||||
// Event handlers.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Event_Handlers
|
||||
$events = array(
|
||||
$events = [
|
||||
'onAbort',
|
||||
'onActivate',
|
||||
'onAfterPrint',
|
||||
|
@ -321,71 +321,71 @@ class StandardTest extends UnitTestCase {
|
|||
'onUndo',
|
||||
'onUnload',
|
||||
'onURLFlip',
|
||||
);
|
||||
];
|
||||
foreach ($events as $event) {
|
||||
$data[] = array('<p ' . $event . '="javascript:alert(\'XSS\');">Dangerous llama!</p>', '<p>Dangerous llama!</p>');
|
||||
$data[] = ['<p ' . $event . '="javascript:alert(\'XSS\');">Dangerous llama!</p>', '<p>Dangerous llama!</p>'];
|
||||
}
|
||||
|
||||
// BGSOUND.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#BGSOUND
|
||||
$data[] = array('<BGSOUND SRC="javascript:alert(\'XSS\');">', '<BGSOUND src="alert('XSS');">');
|
||||
$data[] = ['<BGSOUND SRC="javascript:alert(\'XSS\');">', '<BGSOUND src="alert('XSS');">'];
|
||||
|
||||
// & JavaScript includes.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#.26_JavaScript_includes
|
||||
$data[] = array('<BR SIZE="&{alert(\'XSS\')}">', '<BR size="">');
|
||||
$data[] = ['<BR SIZE="&{alert(\'XSS\')}">', '<BR size="">'];
|
||||
|
||||
// STYLE sheet.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_sheet
|
||||
$data[] = array('<LINK REL="stylesheet" HREF="javascript:alert(\'XSS\');">', '');
|
||||
$data[] = ['<LINK REL="stylesheet" HREF="javascript:alert(\'XSS\');">', ''];
|
||||
|
||||
// Remote style sheet.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Remote_style_sheet
|
||||
$data[] = array('<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">', '');
|
||||
$data[] = ['<LINK REL="stylesheet" HREF="http://ha.ckers.org/xss.css">', ''];
|
||||
|
||||
// Remote style sheet part 2.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Remote_style_sheet_part_2
|
||||
$data[] = array('<STYLE>@import\'http://ha.ckers.org/xss.css\';</STYLE>', '@import\'http://ha.ckers.org/xss.css\';');
|
||||
$data[] = ['<STYLE>@import\'http://ha.ckers.org/xss.css\';</STYLE>', '@import\'http://ha.ckers.org/xss.css\';'];
|
||||
|
||||
// Remote style sheet part 3.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Remote_style_sheet_part_3
|
||||
$data[] = array('<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">', '<META http-equiv="Link">; REL=stylesheet">');
|
||||
$data[] = ['<META HTTP-EQUIV="Link" Content="<http://ha.ckers.org/xss.css>; REL=stylesheet">', '<META http-equiv="Link">; REL=stylesheet">'];
|
||||
|
||||
// Remote style sheet part 4.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Remote_style_sheet_part_4
|
||||
$data[] = array('<STYLE>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</STYLE>', 'BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}');
|
||||
$data[] = ['<STYLE>BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}</STYLE>', 'BODY{-moz-binding:url("http://ha.ckers.org/xssmoz.xml#xss")}'];
|
||||
|
||||
// STYLE tags with broken up JavaScript for XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_tags_with_broken_up_JavaScript_for_XSS
|
||||
$data[] = array('<STYLE>@im\port\'\ja\vasc\ript:alert("XSS")\';</STYLE>', '@im\port\'\ja\vasc\ript:alert("XSS")\';');
|
||||
$data[] = ['<STYLE>@im\port\'\ja\vasc\ript:alert("XSS")\';</STYLE>', '@im\port\'\ja\vasc\ript:alert("XSS")\';'];
|
||||
|
||||
// STYLE attribute using a comment to break up expression.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_attribute_using_a_comment_to_break_up_expression
|
||||
$data[] = array('<IMG STYLE="xss:expr/*XSS*/ession(alert(\'XSS\'))">', '<IMG>');
|
||||
$data[] = ['<IMG STYLE="xss:expr/*XSS*/ession(alert(\'XSS\'))">', '<IMG>'];
|
||||
|
||||
// IMG STYLE with expression.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IMG_STYLE_with_expression
|
||||
$data[] = array('exp/*<A STYLE=\'no\xss:noxss("*//*");
|
||||
xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
||||
$data[] = ['exp/*<A STYLE=\'no\xss:noxss("*//*");
|
||||
xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>'];
|
||||
|
||||
// STYLE tag (Older versions of Netscape only).
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_tag_.28Older_versions_of_Netscape_only.29
|
||||
$data[] = array('<STYLE TYPE="text/javascript">alert(\'XSS\');</STYLE>', 'alert(\'XSS\');');
|
||||
$data[] = ['<STYLE TYPE="text/javascript">alert(\'XSS\');</STYLE>', 'alert(\'XSS\');'];
|
||||
|
||||
// STYLE tag using background-image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_tag_using_background-image
|
||||
$data[] = array('<STYLE>.XSS{background-image:url("javascript:alert(\'XSS\')");}</STYLE><A CLASS=XSS></A>', '.XSS{background-image:url("javascript:alert(\'XSS\')");}<A class="XSS"></A>');
|
||||
$data[] = ['<STYLE>.XSS{background-image:url("javascript:alert(\'XSS\')");}</STYLE><A CLASS=XSS></A>', '.XSS{background-image:url("javascript:alert(\'XSS\')");}<A class="XSS"></A>'];
|
||||
|
||||
// STYLE tag using background.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#STYLE_tag_using_background
|
||||
$data[] = array('<STYLE type="text/css">BODY{background:url("javascript:alert(\'XSS\')")}</STYLE>', 'BODY{background:url("javascript:alert(\'XSS\')")}');
|
||||
$data[] = ['<STYLE type="text/css">BODY{background:url("javascript:alert(\'XSS\')")}</STYLE>', 'BODY{background:url("javascript:alert(\'XSS\')")}'];
|
||||
|
||||
// Anonymous HTML with STYLE attribute.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Anonymous_HTML_with_STYLE_attribute
|
||||
$data[] = array('<XSS STYLE="xss:expression(alert(\'XSS\'))">', '<XSS>');
|
||||
$data[] = ['<XSS STYLE="xss:expression(alert(\'XSS\'))">', '<XSS>'];
|
||||
|
||||
// Local htc file.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Local_htc_file
|
||||
$data[] = array('<XSS STYLE="behavior: url(xss.htc);">', '<XSS>');
|
||||
$data[] = ['<XSS STYLE="behavior: url(xss.htc);">', '<XSS>'];
|
||||
|
||||
// US-ASCII encoding.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#US-ASCII_encoding
|
||||
|
@ -393,77 +393,77 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
|
||||
// META.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#META
|
||||
$data[] = array('<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert(\'XSS\');">', '<META http-equiv="refresh" content="alert('XSS');">');
|
||||
$data[] = ['<META HTTP-EQUIV="refresh" CONTENT="0;url=javascript:alert(\'XSS\');">', '<META http-equiv="refresh" content="alert('XSS');">'];
|
||||
|
||||
// META using data.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#META_using_data
|
||||
$data[] = array('<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">', '<META http-equiv="refresh" content="text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">');
|
||||
$data[] = ['<META HTTP-EQUIV="refresh" CONTENT="0;url=data:text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">', '<META http-equiv="refresh" content="text/html base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">'];
|
||||
|
||||
// META with additional URL parameter
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#META
|
||||
$data[] = array('<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(\'XSS\');">', '<META http-equiv="refresh" content="//;URL=javascript:alert('XSS');">');
|
||||
$data[] = ['<META HTTP-EQUIV="refresh" CONTENT="0; URL=http://;URL=javascript:alert(\'XSS\');">', '<META http-equiv="refresh" content="//;URL=javascript:alert('XSS');">'];
|
||||
|
||||
// IFRAME.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IFRAME
|
||||
$data[] = array('<IFRAME SRC="javascript:alert(\'XSS\');"></IFRAME>', '<IFRAME src="alert('XSS');"></IFRAME>');
|
||||
$data[] = ['<IFRAME SRC="javascript:alert(\'XSS\');"></IFRAME>', '<IFRAME src="alert('XSS');"></IFRAME>'];
|
||||
|
||||
// IFRAME Event based.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IFRAME_Event_based
|
||||
$data[] = array('<IFRAME SRC=# onmouseover="alert(document.cookie)"></IFRAME>', '<IFRAME src="#"></IFRAME>');
|
||||
$data[] = ['<IFRAME SRC=# onmouseover="alert(document.cookie)"></IFRAME>', '<IFRAME src="#"></IFRAME>'];
|
||||
|
||||
// FRAME.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#FRAME
|
||||
$data[] = array('<FRAMESET><FRAME SRC="javascript:alert(\'XSS\');"></FRAMESET>', '<FRAMESET><FRAME src="alert('XSS');"></FRAMESET>');
|
||||
$data[] = ['<FRAMESET><FRAME SRC="javascript:alert(\'XSS\');"></FRAMESET>', '<FRAMESET><FRAME src="alert('XSS');"></FRAMESET>'];
|
||||
|
||||
// TABLE.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#TABLE
|
||||
$data[] = array('<TABLE BACKGROUND="javascript:alert(\'XSS\')">', '<TABLE background="alert('XSS')">');
|
||||
$data[] = ['<TABLE BACKGROUND="javascript:alert(\'XSS\')">', '<TABLE background="alert('XSS')">'];
|
||||
|
||||
// TD.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#TD
|
||||
$data[] = array('<TABLE><TD BACKGROUND="javascript:alert(\'XSS\')">', '<TABLE><TD background="alert('XSS')">');
|
||||
$data[] = ['<TABLE><TD BACKGROUND="javascript:alert(\'XSS\')">', '<TABLE><TD background="alert('XSS')">'];
|
||||
|
||||
// DIV background-image.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#DIV_background-image
|
||||
$data[] = array('<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">', '<DIV>');
|
||||
$data[] = ['<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">', '<DIV>'];
|
||||
|
||||
// DIV background-image with unicoded XSS exploit.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#DIV_background-image_with_unicoded_XSS_exploit
|
||||
$data[] = array('<DIV STYLE="background-image:\0075\0072\006C\0028\'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029\'\0029">', '<DIV>');
|
||||
$data[] = ['<DIV STYLE="background-image:\0075\0072\006C\0028\'\006a\0061\0076\0061\0073\0063\0072\0069\0070\0074\003a\0061\006c\0065\0072\0074\0028.1027\0058.1053\0053\0027\0029\'\0029">', '<DIV>'];
|
||||
|
||||
// DIV background-image plus extra characters.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#DIV_background-image_plus_extra_characters
|
||||
$data[] = array('<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">', '<DIV>');
|
||||
$data[] = ['<DIV STYLE="background-image: url(javascript:alert(\'XSS\'))">', '<DIV>'];
|
||||
|
||||
// DIV expression.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#DIV_expression
|
||||
$data[] = array('<DIV STYLE="width: expression(alert(\'XSS\'));">', '<DIV>');
|
||||
$data[] = ['<DIV STYLE="width: expression(alert(\'XSS\'));">', '<DIV>'];
|
||||
|
||||
// Downlevel-Hidden block.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Downlevel-Hidden_block
|
||||
$data[] = array('<!--[if gte IE 4]>
|
||||
$data[] = ['<!--[if gte IE 4]>
|
||||
<SCRIPT>alert(\'XSS\');</SCRIPT>
|
||||
<![endif]-->', "\n alert('XSS');\n ");
|
||||
<![endif]-->', "\n alert('XSS');\n "];
|
||||
|
||||
// BASE tag.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#BASE_tag
|
||||
$data[] = array('<BASE HREF="javascript:alert(\'XSS\');//">', '<BASE href="alert('XSS');//">');
|
||||
$data[] = ['<BASE HREF="javascript:alert(\'XSS\');//">', '<BASE href="alert('XSS');//">'];
|
||||
|
||||
// OBJECT tag.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#OBJECT_tag
|
||||
$data[] = array('<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>', '');
|
||||
$data[] = ['<OBJECT TYPE="text/x-scriptlet" DATA="http://ha.ckers.org/scriptlet.html"></OBJECT>', ''];
|
||||
|
||||
// Using an EMBED tag you can embed a Flash movie that contains XSS.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Using_an_EMBED_tag_you_can_embed_a_Flash_movie_that_contains_XSS
|
||||
$data[] = array('<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>', '');
|
||||
$data[] = ['<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>', ''];
|
||||
|
||||
// You can EMBED SVG which can contain your XSS vector.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#You_can_EMBED_SVG_which_can_contain_your_XSS_vector
|
||||
$data[] = array('<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>', '');
|
||||
$data[] = ['<EMBED SRC="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==" type="image/svg+xml" AllowScriptAccess="always"></EMBED>', ''];
|
||||
|
||||
// XML data island with CDATA obfuscation.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#XML_data_island_with_CDATA_obfuscation
|
||||
$data[] = array('<XML ID="xss"><I><B><IMG SRC="javas<!-- -->cript:alert(\'XSS\')"></B></I></XML><SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>', '<XML id="xss"><I><B><IMG>cript:alert(\'XSS\')"></B></I></XML><SPAN datasrc="#xss" datafld="B" dataformatas="HTML"></SPAN>');
|
||||
$data[] = ['<XML ID="xss"><I><B><IMG SRC="javas<!-- -->cript:alert(\'XSS\')"></B></I></XML><SPAN DATASRC="#xss" DATAFLD="B" DATAFORMATAS="HTML"></SPAN>', '<XML id="xss"><I><B><IMG>cript:alert(\'XSS\')"></B></I></XML><SPAN datasrc="#xss" datafld="B" dataformatas="HTML"></SPAN>'];
|
||||
|
||||
// Locally hosted XML with embedded JavaScript that is generated using an XML data island.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Locally_hosted_XML_with_embedded_JavaScript_that_is_generated_using_an_XML_data_island
|
||||
|
@ -472,11 +472,11 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
|
||||
// HTML+TIME in XML.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#HTML.2BTIME_in_XML
|
||||
$data[] = array('<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t:set attributeName="innerHTML" to="XSS<SCRIPT DEFER>alert("XSS")</SCRIPT>">', '<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t set attributename="innerHTML">alert("XSS")">');
|
||||
$data[] = ['<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t:set attributeName="innerHTML" to="XSS<SCRIPT DEFER>alert("XSS")</SCRIPT>">', '<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"><?import namespace="t" implementation="#default#time2"><t set attributename="innerHTML">alert("XSS")">'];
|
||||
|
||||
// Assuming you can only fit in a few characters and it filters against ".js".
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Assuming_you_can_only_fit_in_a_few_characters_and_it_filters_against_.22.js.22
|
||||
$data[] = array('<SCRIPT SRC="http://ha.ckers.org/xss.jpg"></SCRIPT>', '');
|
||||
$data[] = ['<SCRIPT SRC="http://ha.ckers.org/xss.jpg"></SCRIPT>', ''];
|
||||
|
||||
// IMG Embedded commands.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#IMG_Embedded_commands
|
||||
|
@ -485,7 +485,7 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
|
||||
// Cookie manipulation.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#Cookie_manipulation
|
||||
$data[] = array('<META HTTP-EQUIV="Set-Cookie" Content="USERID=<SCRIPT>alert(\'XSS\')</SCRIPT>">', '<META http-equiv="Set-Cookie">alert(\'XSS\')">');
|
||||
$data[] = ['<META HTTP-EQUIV="Set-Cookie" Content="USERID=<SCRIPT>alert(\'XSS\')</SCRIPT>">', '<META http-equiv="Set-Cookie">alert(\'XSS\')">'];
|
||||
|
||||
// UTF-7 encoding.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#UTF-7_encoding
|
||||
|
@ -493,13 +493,13 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
|
||||
// XSS using HTML quote encapsulation.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#XSS_using_HTML_quote_encapsulation
|
||||
$data[] = array('<SCRIPT a=">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT =">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT a=">" \'\' SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" \'\' SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT "a=\'>\'" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '\'" SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '` SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT a=">\'>" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '\'>" SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = array('<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://ha.ckers.org/xss.js"></SCRIPT>', 'document.write("<SCRI>PT SRC="http://ha.ckers.org/xss.js">');
|
||||
$data[] = ['<SCRIPT a=">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT =">" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT a=">" \'\' SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '" \'\' SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT "a=\'>\'" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '\'" SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT a=`>` SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '` SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT a=">\'>" SRC="http://ha.ckers.org/xss.js"></SCRIPT>', '\'>" SRC="http://ha.ckers.org/xss.js">'];
|
||||
$data[] = ['<SCRIPT>document.write("<SCRI");</SCRIPT>PT SRC="http://ha.ckers.org/xss.js"></SCRIPT>', 'document.write("<SCRI>PT SRC="http://ha.ckers.org/xss.js">'];
|
||||
|
||||
// URL string evasion.
|
||||
// @see https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet#URL_string_evasion
|
||||
|
@ -511,12 +511,12 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
// @see \Drupal\editor\EditorXssFilter::filterXssDataAttributes()
|
||||
|
||||
// The following two test cases verify that XSS attack vectors are filtered.
|
||||
$data[] = array('<img src="butterfly.jpg" data-caption="<script>alert();</script>" />', '<img src="butterfly.jpg" data-caption="alert();" />');
|
||||
$data[] = array('<img src="butterfly.jpg" data-caption="<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>" />', '<img src="butterfly.jpg" data-caption="" />');
|
||||
$data[] = ['<img src="butterfly.jpg" data-caption="<script>alert();</script>" />', '<img src="butterfly.jpg" data-caption="alert();" />'];
|
||||
$data[] = ['<img src="butterfly.jpg" data-caption="<EMBED SRC="http://ha.ckers.org/xss.swf" AllowScriptAccess="always"></EMBED>" />', '<img src="butterfly.jpg" data-caption="" />'];
|
||||
|
||||
// When including HTML-tags as visible content, they are double-escaped.
|
||||
// This test case ensures that we leave that content unchanged.
|
||||
$data[] = array('<img src="butterfly.jpg" data-caption="&lt;script&gt;alert();&lt;/script&gt;" />', '<img src="butterfly.jpg" data-caption="&lt;script&gt;alert();&lt;/script&gt;" />');
|
||||
$data[] = ['<img src="butterfly.jpg" data-caption="&lt;script&gt;alert();&lt;/script&gt;" />', '<img src="butterfly.jpg" data-caption="&lt;script&gt;alert();&lt;/script&gt;" />'];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
@ -573,27 +573,27 @@ xss:ex/*XSS*//*/*/pression(alert("XSS"))\'>', 'exp/*<A>');
|
|||
* - (optional) The disallowed HTML tags to be passed to \Drupal\Component\Utility\Xss::filter().
|
||||
*/
|
||||
public function providerTestBlackListMode() {
|
||||
return array(
|
||||
array(
|
||||
return [
|
||||
[
|
||||
'<unknown style="visibility:hidden">Pink Fairy Armadillo</unknown><video src="gerenuk.mp4"><script>alert(0)</script>',
|
||||
'<unknown>Pink Fairy Armadillo</unknown><video src="gerenuk.mp4">alert(0)',
|
||||
'Disallow only the script tag',
|
||||
array('script')
|
||||
),
|
||||
array(
|
||||
['script']
|
||||
],
|
||||
[
|
||||
'<unknown style="visibility:hidden">Pink Fairy Armadillo</unknown><video src="gerenuk.mp4"><script>alert(0)</script>',
|
||||
'<unknown>Pink Fairy Armadillo</unknown>alert(0)',
|
||||
'Disallow both the script and video tags',
|
||||
array('script', 'video')
|
||||
),
|
||||
['script', 'video']
|
||||
],
|
||||
// No real use case for this, but it is an edge case we must ensure works.
|
||||
array(
|
||||
[
|
||||
'<unknown style="visibility:hidden">Pink Fairy Armadillo</unknown><video src="gerenuk.mp4"><script>alert(0)</script>',
|
||||
'<unknown>Pink Fairy Armadillo</unknown><video src="gerenuk.mp4"><script>alert(0)</script>',
|
||||
'Disallow no tags',
|
||||
array()
|
||||
),
|
||||
);
|
||||
[]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue