Skip to content

Commit

Permalink
Escape HTML on detail dialogs with unsafe flag
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 24, 2018
1 parent 1e11586 commit 10e793b
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 28 deletions.
10 changes: 5 additions & 5 deletions src/JBrowse/Model/VCFFeature.js
Expand Up @@ -11,8 +11,8 @@ function (Util) {
this._id = args.id;
this.data = this.dataFromVariant(this.variant);
},
get(field) {

get(field) {
return this._get(field) || this._get(field.toLowerCase())
},

Expand Down Expand Up @@ -100,7 +100,7 @@ function (Util) {
start: start,
end: end,
seq_id: variant.CHROM,
description: Util.escapeHTML( description ),
description: description,
type: SO_term,
reference_allele: ref
};
Expand Down Expand Up @@ -131,7 +131,7 @@ function (Util) {
meta: {
description: 'VCF ALT field, list of alternate non-reference alleles called on at least one of the samples'
},
values: alt.map( Util.escapeHTML )
values: alt
};
}

Expand Down Expand Up @@ -253,7 +253,7 @@ function (Util) {

_getSOAndDescByExamination: function (ref, alt) {
if (ref.length == 1 && alt.length == 1) {
// use SNV because SO definition of SNP says abundance must be at
// use SNV because SO definition of SNP says abundance must be at
// least 1% in population, and can't be sure we meet that
return [
'SNV',
Expand Down
3 changes: 3 additions & 0 deletions src/JBrowse/Util.js
Expand Up @@ -38,6 +38,9 @@ Util = {
},

escapeHTML: function( str ) {
if(str === null || str === undefined) {
return str
}
return str.toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
},

Expand Down
26 changes: 14 additions & 12 deletions src/JBrowse/View/DetailsMixin.js
Expand Up @@ -31,7 +31,7 @@ var Grid = declare([DGrid,DGridDijitRegistry]);

return declare( null, {

renderDetailField: function( parentElement, title, val, f, class_, externalFieldMeta = {} ) {
renderDetailField: function( parentElement, title, val, f, class_, externalFieldMeta = {}, unsafe = false) {
if( val === null || val === undefined )
return '';

Expand All @@ -44,7 +44,7 @@ return declare( null, {

class_ = class_ || title.replace(/\W/g,'_').toLowerCase();

var formatted_title=title;
var formatted_title = title;
// if this object has a config value 'fmtDetailField_Foo' function, apply it to field title
if(( fieldSpecificFormatter = this.config['fmtDetailField_'+title] ) && f) {
formatted_title= fieldSpecificFormatter(title,f);
Expand Down Expand Up @@ -91,15 +91,15 @@ return declare( null, {
+ class_
}, fieldContainer );

var count = this.renderDetailValue( valueContainer, title, val, f, class_);
var count = this.renderDetailValue( valueContainer, title, val, f, class_, unsafe);
if( typeof count == 'number' && count > 4 ) {
query( 'h2', fieldContainer )[0].innerHTML = formatted_title + ' ('+count+')';
}

return fieldContainer;
},

renderDetailValue: function( parent, title, val, f, class_ ) {
renderDetailValue: function( parent, title, val, f, class_, unsafe = false) {
var thisB = this;

if( !lang.isArray(val) && val && val.values )
Expand All @@ -114,13 +114,15 @@ return declare( null, {

// if this object has a config value 'fmtDetailValue_Foo' function, apply it to val
if(( fieldSpecificFormatter = this.config['fmtDetailValue_'+title] ) && f) {
val= fieldSpecificFormatter( val,f );
unsafe = true
val = fieldSpecificFormatter( val,f );
if(!val) val='';
if(val.length==1) val=val[0]; // avoid recursion when an array of length 1 is returned
if(val.length == 1) val = val[0]; // avoid recursion when an array of length 1 is returned
}
else if(( fieldSpecificFormatter = this.config['fmtMetaValue_'+title] ) && !f) {
val=fieldSpecificFormatter( val );
if(val.length==1) val=val[0];
unsafe = true
val = fieldSpecificFormatter( val );
if(val.length == 1) val = val[0];
}

var valType = typeof val;
Expand All @@ -140,12 +142,12 @@ return declare( null, {
className: 'value_container '+class_,
style: { width: '100%' },
}, parent );
this.renderDetailValue( itemContainer, title, v, f, class_ );
this.renderDetailValue( itemContainer, title, v, f, class_, unsafe );
return itemContainer
})
} else {
vals = array.map( val, function(v) {
return this.renderDetailValue( parent, title, v, f, class_ );
return this.renderDetailValue( parent, title, v, f, class_, unsafe );
}, this );
}
if( vals.length > 1 )
Expand Down Expand Up @@ -200,13 +202,13 @@ return declare( null, {
}
else {
array.forEach( keys, function( k ) {
return this.renderDetailField( parent, k, val[k], f, class_ );
return this.renderDetailField( parent, k, val[k], f, class_, {}, unsafe );
}, this );
return keys.length;
}
}

domConstruct.create('div', { className: 'value '+class_, innerHTML: val }, parent );
domConstruct.create('div', { className: 'value '+class_, innerHTML: unsafe ? val : Util.escapeHTML(val) }, parent );
return 1;
},

Expand Down
2 changes: 1 addition & 1 deletion src/JBrowse/View/FeatureGlyph/Box.js
Expand Up @@ -327,7 +327,7 @@ return declare([ FeatureGlyph, FeatureLabelMixin], {
if (clearTop) context.clearRect(labelLeft,clearTop,fLabelRecord.w,fLabelRecord.h)

context.fillText(
Util.unescapeHTML(fLabelRecord.text),
fLabelRecord.text,
labelLeft,
labelTop
)
Expand Down
6 changes: 3 additions & 3 deletions src/JBrowse/View/Track/Wiggle/XYPlot.js
Expand Up @@ -208,11 +208,11 @@ var XYPlot = declare( [WiggleBase, YScaleMixin],
thisB._fillRectMod( context, 0, varTop, canvas.width, varHeight );
context.font = '12px sans-serif';
if( plusminus > 0 ) {
context.fillText( Util.unescapeHTML( '+'+label ), 2, varTop );
context.fillText( Util.unescapeHTML( '-'+label ), 2, varTop+varHeight );
context.fillText( '+'+label, 2, varTop );
context.fillText( '-'+label, 2, varTop+varHeight );
}
else {
context.fillText( Util.unescapeHTML( label ), 2, varTop );
context.fillText( label, 2, varTop );
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/JBrowse/View/Track/_AlignmentsMixin.js
Expand Up @@ -31,9 +31,9 @@ return declare([ MismatchesMixin, NamedFeatureFiltersMixin ], {
className: 'detail feature-detail feature-detail-'+track.name.replace(/\s+/g,'_').toLowerCase(),
innerHTML: ''
});
var fmt = dojo.hitch( this, function( name, value, feature ) {
var fmt = dojo.hitch( this, function( name, value, feature, unsafe ) {
name = Util.ucFirst( name.replace(/_/g,' ') );
return this.renderDetailField(container, name, value, feature);
return this.renderDetailField(container, name, value, feature, null, {}, unsafe);
});
fmt( 'Name', f.get('name'), f );
fmt( 'Type', f.get('type'), f );
Expand All @@ -50,7 +50,7 @@ return declare([ MismatchesMixin, NamedFeatureFiltersMixin ], {


if( f.get('seq') ) {
fmt('Sequence and Quality', this._renderSeqQual( f ), f );
fmt('Sequence and Quality', this._renderSeqQual( f ), f, true );
}

var renameTags = { length_on_ref: 'seq_length_on_ref' };
Expand Down
2 changes: 1 addition & 1 deletion src/JBrowse/View/Track/_FeatureDetailMixin.js
Expand Up @@ -97,7 +97,7 @@ return declare( FeatureDescriptionMixin, {
var fmt = dojo.hitch( this, 'renderDetailField', coreDetails );
coreDetails.innerHTML += '<h2 class="sectiontitle">Primary Data</h2>';

fmt( 'Name', this.getFeatureLabel( f ),f );
fmt( 'Name', this.getFeatureLabel( f ), f );
fmt( 'Type', f.get('type'),f );
fmt( 'Score', f.get('score'),f );
fmt( 'Description', this.getFeatureDescription( f ),f );
Expand Down
6 changes: 3 additions & 3 deletions tests/js_tests/spec/VCF.spec.js
Expand Up @@ -62,7 +62,7 @@ describe('VCF store', function() {
);
runs(function() {
expect(features.length).toEqual( 7 );
expect(features[2].get('alternative_alleles').values).toEqual([ "TC", "&lt;*&gt;" ]);
expect(features[2].get('alternative_alleles').values).toEqual([ "TC", "<*>" ]);
});


Expand Down Expand Up @@ -122,7 +122,7 @@ describe('VCF store', function() {
);
runs(function() {
expect(features.length).toEqual( 37 );
expect(features[0].get('alternative_alleles').values).toEqual([ '&lt;NON_REF&gt;' ]);
expect(features[0].get('alternative_alleles').values).toEqual([ '<NON_REF>' ]);
});
});

Expand Down Expand Up @@ -191,7 +191,7 @@ describe('VCF store', function() {
start: 1206810422,
end: 1206810423,
seq_id: '1',
description: 'SNV T -&gt; A',
description: 'SNV T -> A',
type: 'SNV',
reference_allele: 'T',
score: 25,
Expand Down

0 comments on commit 10e793b

Please sign in to comment.