Skip to content
Permalink
Browse files

Merge branch 't/10080' into major

  • Loading branch information...
Reinmar committed Feb 15, 2013
2 parents c7cf983 + dfe9426 commit 5aff1eaf4b021f90cc266fc95a1ad60e859bcd0f
Showing with 96 additions and 28 deletions.
  1. +84 −21 core/filter.js
  2. +6 −1 core/tools.js
  3. +3 −3 plugins/image/plugin.js
  4. +2 −2 plugins/link/plugin.js
  5. +1 −1 plugins/smiley/plugin.js
@@ -8,7 +8,8 @@

var DTD = CKEDITOR.dtd,
copy = CKEDITOR.tools.copy,
trim = CKEDITOR.tools.trim;
trim = CKEDITOR.tools.trim,
TEST_VALUE = 'cke-test';

/**
* @class
@@ -331,7 +332,7 @@
},

/**
* Add array of content transformations groups. One group
* Add an array of content transformations groups. One group
* may contain many transformations rules, but only the first
* matching rule in a group is executed.
*
@@ -414,23 +415,40 @@
},

/**
* Checks whether content defined in test argument is allowed
* Check whether content defined in test argument is allowed
* by this filter.
*
* Unless `strictCheck` is set to `true` this method checks
* if all parts of the `test` (styles, attributes and classes)
* are accepted by the filter, not whether element with
* these properties only would be accepted.
*
* For example:
*
* // Rule: 'img[!src,alt]'
* filter.check( 'img[alt]' ); // -> true
* filter.check( 'img[alt]', true, true ); // -> false
*
* Second check returned false because of `src` is required.
*
* @param {String/CKEDITOR.style} test
* @param {Boolean} [applyTransformations=true] Whether to use registered transformations.
* @param {Boolean} [strictCheck] Whether fitler should check if element with exactly
* these properties is allowed.
* @returns {Boolean} Returns `true` if content is allowed.
*/
check: function( test, applyTransformations ) {
check: function( test, applyTransformations, strictCheck ) {
if ( this.disabled )
return true;

var element, result;
var element, result, cacheKey;

if ( typeof test == 'string' ) {
cacheKey = test + '<' + ( applyTransformations === false ? '0' : '1' ) + ( strictCheck ? '1' : '0' ) + '>';

// Check if result of this check hasn't been already cached.
if ( test in this._.cachedChecks )
return this._.cachedChecks[ test ];
if ( cacheKey in this._.cachedChecks )
return this._.cachedChecks[ cacheKey ];

// Create test element from string.
element = mockElementFromString( test );
@@ -440,11 +458,23 @@

// Make a deep copy.
var clone = CKEDITOR.tools.clone( element ),
toBeRemoved = [];
toBeRemoved = [],
transformations, i;

// Apply transformations to original element.
// Transformations will be applied to clone by the filter function.
if ( applyTransformations !== false && ( transformations = this._.transformations[ element.name ] ) ) {
for ( i = 0; i < transformations.length; ++i )
applyTransformationsGroup( this, element, transformations[ i ] );

// Transformations could modify styles or classes, so they need to be copied
// to attributes object.
updateAttributes( element );
}

// Filter clone of mocked element.
// Do not run transformations.
getFilterFunction( this )( clone, this._.rules, applyTransformations === false ? false : this._.transformations, toBeRemoved );
getFilterFunction( this )( clone, this._.rules, applyTransformations === false ? false : this._.transformations, toBeRemoved, false, !strictCheck );

// Element has been marked for removal.
if ( toBeRemoved.length > 0 )
@@ -457,13 +487,19 @@

// Cache result of this test - we can build cache only for string tests.
if ( typeof test == 'string' )
this._.cachedChecks[ test ] = result;
this._.cachedChecks[ cacheKey ] = result;

return result;
}
};

function applyRule( rule, element, status, isSpecific ) {
// Apply ACR to an element
// @param rule
// @param element
// @param status Object containing status of element's filtering.
// @param {Boolean} isSpecific True if this is specific element's rule, false if generic.
// @param {Boolean} skipRequired If true don't check if element has all required properties.
function applyRule( rule, element, status, isSpecific, skipRequired ) {
var name = element.name;

// This generic rule doesn't apply to this element - skip it.
@@ -478,7 +514,7 @@

// If element doesn't have all required styles/attrs/classes
// this rule doesn't match it.
if ( !hasAllRequired( rule, element ) )
if ( !skipRequired && !hasAllRequired( rule, element ) )
return;

// If this rule doesn't validate properties only mark element as valid.
@@ -593,7 +629,13 @@
protectElementsNamesRegexp = /^(object|embed|param)$/;

// Return and cache created function.
return that._.filterFunction = function( element, optimizedRules, transformations, toBeRemoved, toHtml ) {
// @param {CKEDITOR.htmlParser.element}
// @param optimizedRules Rules to be used.
// @param [transformations] Transformations to be applied.
// @param {Array} toBeRemoved Array into which elements rejected by the filter will be pushed.
// @param {Boolean} [toHtml] Set to true if filter used together with htmlDP#toHtml
// @param {Boolean} [skipRequired] Whether element's required properties shouldn't be verified.
return that._.filterFunction = function( element, optimizedRules, transformations, toBeRemoved, toHtml, skipRequired ) {
var name = element.name,
i, l, trans;

@@ -644,12 +686,12 @@

if ( rules ) {
for ( i = 0, l = rules.length; i < l; ++i )
applyRule( rules[ i ], element, status, true );
applyRule( rules[ i ], element, status, true, skipRequired );
}

if ( genericRules ) {
for ( i = 0, l = genericRules.length; i < l; ++i )
applyRule( genericRules[ i ], element, status, false );
applyRule( genericRules[ i ], element, status, false, skipRequired );
}

// Finally, if after running all filter rules it still hasn't been allowed - remove it.
@@ -725,26 +767,27 @@
// to check if tested style is allowed.
function mockElementFromStyle( style ) {
var styleDef = style.getDefinition(),
styles = styleDef.styles || null,
styles = styleDef.styles,
attrs = styleDef.attributes || {};

if ( styles ) {
styles = copy( styles );
attrs.style = CKEDITOR.tools.writeCssText( styles );
}
attrs.style = CKEDITOR.tools.writeCssText( styles, true );
} else
styles = {};

var el = {
name: styleDef.element,
attributes: attrs,
classes: attrs[ 'class' ] ? attrs[ 'class' ].split( /\s+/ ) : null,
classes: attrs[ 'class' ] ? attrs[ 'class' ].split( /\s+/ ) : [],
styles: styles
};

return el;
}

// Mock hash based on string.
// 'a,b,c' => { a: 'test', b: 'test', c: 'test' }
// 'a,b,c' => { a: 'cke-test', b: 'cke-test', c: 'cke-test' }
// Used to mock styles and attributes objects.
function mockHash( str ) {
// It may be a null or empty string.
@@ -755,7 +798,7 @@
obj = {}

while ( keys.length )
obj[ keys.shift() ] = 'test';
obj[ keys.shift() ] = TEST_VALUE;

return obj;
}
@@ -912,6 +955,23 @@
element.classes = element.attributes[ 'class' ] ? element.attributes[ 'class' ].split( /\s+/ ) : [];
}

// Copy element's styles and classes back to attributes array.
function updateAttributes( element ) {
var attrs = element.attributes,
stylesArr = [],
name, styles;

// Will be recreated later if any of styles/classes exists.
delete attrs.style;
delete attrs[ 'class' ];

if ( ( styles = CKEDITOR.tools.writeCssText( element.styles, true ) ) )
attrs.style = styles;

if ( element.classes.length )
attrs[ 'class' ] = element.classes.sort().join( ' ' );
}

// Update element object based on status of filtering.
function updateElement( element, status ) {
var validAttrs = status.validAttributes,
@@ -1310,6 +1370,9 @@

if ( match )
element.attributes[ attrName ] = match[ 1 ];
// Pass the TEST_VALUE used by filter#check when mocking element.
else if ( value == TEST_VALUE )
element.attributes[ attrName ] = TEST_VALUE;
}

delete element.styles[ styleName ];
@@ -873,17 +873,22 @@
* var styleObj = CKEDITOR.tools.parseCssText( 'color: red; border: none' );
* console.log( styleObj.color ); // -> 'red'
* CKEDITOR.tools.writeCssText( styleObj ); // -> 'color:red; border:none'
* CKEDITOR.tools.writeCssText( styleObj, true ); // -> 'border:none; color:red'
*
* @param {Object} styles The object contaning style properties.
* @param {Boolean} [sort] Whether to sort CSS properties.
* @returns {String} The serialized style text.
*/
writeCssText: function( styles ) {
writeCssText: function( styles, sort ) {
var name,
stylesArr = [];

for ( name in styles )
stylesArr.push( name + ':' + styles[ name ] );

if ( sort )
stylesArr.sort();

return stylesArr.join( '; ' );
},

@@ -19,13 +19,13 @@
// Register the dialog.
CKEDITOR.dialog.add( pluginName, this.path + 'dialogs/image.js' );

var allowed = 'img[alt,src]{border-style,border-width,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}',
var allowed = 'img[alt,!src]{border-style,border-width,height,margin,margin-bottom,margin-left,margin-right,margin-top,width}',
required = 'img[alt,src]';

if ( CKEDITOR.dialog.isTabEnabled( editor, pluginName, 'advanced' ) )
allowed += ';img[dir,id,lang,longdesc,title]{*}(*)';
allowed = 'img[alt,dir,id,lang,longdesc,!src,title]{*}(*)';
if ( CKEDITOR.dialog.isTabEnabled( editor, pluginName, 'link' ) )
allowed += ';a[href]';
allowed += ';a[!href]';

// Register the command.
editor.addCommand( pluginName, new CKEDITOR.dialogCommand( pluginName, {
@@ -52,9 +52,9 @@ CKEDITOR.plugins.add( 'link', {
required = 'a[href]';

if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'advanced' ) )
allowed += ';a[accesskey,charset,dir,id,lang,name,rel,tabindex,title,type]{*}(*)';
allowed = allowed.replace( ']', ',accesskey,charset,dir,id,lang,name,rel,tabindex,title,type]{*}(*)' );
if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'target' ) )
allowed += ';a[target,onclick]';
allowed = allowed.replace( ']', ',target,onclick]' );

// Add the link and unlink buttons.
editor.addCommand( 'link', new CKEDITOR.dialogCommand( 'link', {
@@ -10,7 +10,7 @@ CKEDITOR.plugins.add( 'smiley', {
init: function( editor ) {
editor.config.smiley_path = editor.config.smiley_path || ( this.path + 'images/' );
editor.addCommand( 'smiley', new CKEDITOR.dialogCommand( 'smiley', {
allowedContent: 'img[alt,height,src,title,width]',
allowedContent: 'img[alt,height,!src,title,width]',
requiredContent: 'img'
} ) );
editor.ui.addButton && editor.ui.addButton( 'Smiley', {

0 comments on commit 5aff1ea

Please sign in to comment.
You can’t perform that action at this time.