Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
refactor($compile): move img[srcset] sanitizing to helper method
  • Loading branch information
jbedard committed Aug 2, 2018
commit 88a12f8623d53579f8a21ac48d02ae1834fa7acb
98 changes: 53 additions & 45 deletions src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,57 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}


function sanitizeSrcset(value) {
if (!value) {
return value;
}
if (!isString(value)) {
throw $compileMinErr('srcset', 'Can\'t pass trusted values to `$set(\'srcset\', value)`: "{0}"', value.toString());
}

// Such values are a bit too complex to handle automatically inside $sce.
// Instead, we sanitize each of the URIs individually, which works, even dynamically.

// It's not possible to work around this using `$sce.trustAsMediaUrl`.
// If you want to programmatically set explicitly trusted unsafe URLs, you should use
// `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
// `ng-bind-html` directive.

var result = '';

// first check if there are spaces because it's not the same pattern
var trimmedSrcset = trim(value);
// ( 999x ,| 999w ,| ,|, )
var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;

// split srcset into tuple of uri and descriptor except for the last item
var rawUris = trimmedSrcset.split(pattern);

// for each tuples
var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
for (var i = 0; i < nbrUrisWith2parts; i++) {
var innerIdx = i * 2;
// sanitize the uri
result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
// add the descriptor
result += ' ' + trim(rawUris[innerIdx + 1]);
}

// split the last item into uri and descriptor
var lastTuple = trim(rawUris[i * 2]).split(/\s/);

// sanitize the last uri
result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));

// and add the last descriptor if any
if (lastTuple.length === 2) {
result += (' ' + trim(lastTuple[1]));
}
return result;
}


function Attributes(element, attributesToCopy) {
if (attributesToCopy) {
var keys = Object.keys(attributesToCopy);
Expand Down Expand Up @@ -1767,51 +1818,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeName = nodeName_(this.$$element);

// Sanitize img[srcset] values.
if (nodeName === 'img' && key === 'srcset' && value) {
if (!isString(value)) {
throw $compileMinErr('srcset', 'Can\'t pass trusted values to `$set(\'srcset\', value)`: "{0}"', value.toString());
}

// Such values are a bit too complex to handle automatically inside $sce.
// Instead, we sanitize each of the URIs individually, which works, even dynamically.

// It's not possible to work around this using `$sce.trustAsMediaUrl`.
// If you want to programmatically set explicitly trusted unsafe URLs, you should use
// `$sce.trustAsHtml` on the whole `img` tag and inject it into the DOM using the
// `ng-bind-html` directive.

var result = '';

// first check if there are spaces because it's not the same pattern
var trimmedSrcset = trim(value);
// ( 999x ,| 999w ,| ,|, )
var srcPattern = /(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/;
var pattern = /\s/.test(trimmedSrcset) ? srcPattern : /(,)/;

// split srcset into tuple of uri and descriptor except for the last item
var rawUris = trimmedSrcset.split(pattern);

// for each tuples
var nbrUrisWith2parts = Math.floor(rawUris.length / 2);
for (var i = 0; i < nbrUrisWith2parts; i++) {
var innerIdx = i * 2;
// sanitize the uri
result += $sce.getTrustedMediaUrl(trim(rawUris[innerIdx]));
// add the descriptor
result += ' ' + trim(rawUris[innerIdx + 1]);
}

// split the last item into uri and descriptor
var lastTuple = trim(rawUris[i * 2]).split(/\s/);

// sanitize the last uri
result += $sce.getTrustedMediaUrl(trim(lastTuple[0]));

// and add the last descriptor if any
if (lastTuple.length === 2) {
result += (' ' + trim(lastTuple[1]));
}
this[key] = value = result;
if (nodeName === 'img' && key === 'srcset') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't sanitize source[srcset] as advertized by the comment above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that I originally changed this to also include source for consistency with Angular + ng-prop, but this was revert to avoid breaking changes. But I forgot to revert the comment, so I'll be addressing this comment by reverting the comment back to how it is in master...

this[key] = value = sanitizeSrcset(value, '$set(\'srcset\', value)');
}

if (writeAttr !== false) {
Expand Down