app/assets/javascripts/angular/angular-sanitize.js in angular-rails-engine-1.2.0.2 vs app/assets/javascripts/angular/angular-sanitize.js in angular-rails-engine-1.2.3.0
- old
+ new
@@ -1,8 +1,8 @@
/**
- * @license AngularJS v1.2.0
- * (c) 2010-2012 Google, Inc. http://angularjs.org
+ * @license AngularJS v1.2.3
+ * (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
var $sanitizeMinErr = angular.$$minErr('$sanitize');
@@ -49,10 +49,12 @@
* The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
* then serialized back to properly escaped html string. This means that no unsafe input can make
* it into the returned string, however, since our parser is more strict than a typical browser
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
* browser, won't make it through the sanitizer.
+ * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
+ * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
*
* @param {string} html Html input.
* @returns {string} Sanitized html.
*
* @example
@@ -131,15 +133,28 @@
"new <b onclick=\"alert(1)\">text</b>");
});
</doc:scenario>
</doc:example>
*/
-var $sanitize = function(html) {
+function $SanitizeProvider() {
+ this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
+ return function(html) {
+ var buf = [];
+ htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
+ return !/^unsafe/.test($$sanitizeUri(uri, isImage));
+ }));
+ return buf.join('');
+ };
+ }];
+}
+
+function sanitizeText(chars) {
var buf = [];
- htmlParser(html, htmlSanitizeWriter(buf));
- return buf.join('');
-};
+ var writer = htmlSanitizeWriter(buf, angular.noop);
+ writer.chars(chars);
+ return buf.join('');
+}
// Regular Expressions for parsing tags and attributes
var START_TAG_REGEXP =
/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
@@ -148,11 +163,10 @@
BEGIN_TAG_REGEXP = /^</,
BEGING_END_TAGE_REGEXP = /^<\s*\//,
COMMENT_REGEXP = /<!--(.*?)-->/g,
DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
- URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/i,
// Match everything outside of normal chars and " (quote character)
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
// Good source of info about elements and attributes
@@ -356,12 +370,22 @@
* @param value
* @returns {string} A string with decoded entities.
*/
var hiddenPre=document.createElement("pre");
function decodeEntities(value) {
- hiddenPre.innerHTML=value.replace(/</g,"<");
- return hiddenPre.innerText || hiddenPre.textContent || '';
+ if (!value) {
+ return '';
+ }
+ // Note: IE8 does not preserve spaces at the start/end of innerHTML
+ var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
+ var parts = spaceRe.exec(value);
+ parts[0] = '';
+ if (parts[2]) {
+ hiddenPre.innerHTML=parts[2].replace(/</g,"<");
+ parts[2] = hiddenPre.innerText || hiddenPre.textContent;
+ }
+ return parts.join('');
}
/**
* Escapes all potentially dangerous characters, so that the
* resulting string can be safely inserted into attribute or
@@ -387,11 +411,11 @@
* end: function(tag) {},
* chars: function(text) {},
* comment: function(text) {}
* }
*/
-function htmlSanitizeWriter(buf){
+function htmlSanitizeWriter(buf, uriValidator){
var ignore = false;
var out = angular.bind(buf, buf.push);
return {
start: function(tag, attrs, unary){
tag = angular.lowercase(tag);
@@ -401,11 +425,13 @@
if (!ignore && validElements[tag] === true) {
out('<');
out(tag);
angular.forEach(attrs, function(value, key){
var lkey=angular.lowercase(key);
- if (validAttrs[lkey]===true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
+ var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
+ if (validAttrs[lkey] === true &&
+ (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
out(' ');
out(key);
out('="');
out(encodeEntities(value));
out('"');
@@ -433,13 +459,13 @@
};
}
// define ngSanitize module and register $sanitize service
-angular.module('ngSanitize', []).value('$sanitize', $sanitize);
+angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
-/* global htmlSanitizeWriter: false */
+/* global sanitizeText: false */
/**
* @ngdoc filter
* @name ngSanitize.filter:linky
* @function
@@ -535,43 +561,55 @@
toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
});
</doc:scenario>
</doc:example>
*/
-angular.module('ngSanitize').filter('linky', function() {
+angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
var LINKY_URL_REGEXP =
/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
MAILTO_REGEXP = /^mailto:/;
return function(text, target) {
if (!text) return text;
var match;
var raw = text;
var html = [];
- // TODO(vojta): use $sanitize instead
- var writer = htmlSanitizeWriter(html);
var url;
var i;
- var properties = {};
- if (angular.isDefined(target)) {
- properties.target = target;
- }
while ((match = raw.match(LINKY_URL_REGEXP))) {
// We can not end in these as they are sometimes found at the end of the sentence
url = match[0];
// if we did not match ftp/http/mailto then assume mailto
if (match[2] == match[3]) url = 'mailto:' + url;
i = match.index;
- writer.chars(raw.substr(0, i));
- properties.href = url;
- writer.start('a', properties);
- writer.chars(match[0].replace(MAILTO_REGEXP, ''));
- writer.end('a');
+ addText(raw.substr(0, i));
+ addLink(url, match[0].replace(MAILTO_REGEXP, ''));
raw = raw.substring(i + match[0].length);
}
- writer.chars(raw);
- return html.join('');
+ addText(raw);
+ return $sanitize(html.join(''));
+
+ function addText(text) {
+ if (!text) {
+ return;
+ }
+ html.push(sanitizeText(text));
+ }
+
+ function addLink(url, text) {
+ html.push('<a ');
+ if (angular.isDefined(target)) {
+ html.push('target="');
+ html.push(target);
+ html.push('" ');
+ }
+ html.push('href="');
+ html.push(url);
+ html.push('">');
+ addText(text);
+ html.push('</a>');
+ }
};
-});
+}]);
})(window, window.angular);