angularjs-rails 1.5.8 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +6 -1
- data/lib/angularjs-rails/engine.rb +1 -1
- data/lib/angularjs-rails/version.rb +1 -1
- data/vendor/assets/javascripts/angular-animate.js +426 -293
- data/vendor/assets/javascripts/angular-aria.js +64 -43
- data/vendor/assets/javascripts/angular-cookies.js +24 -93
- data/vendor/assets/javascripts/angular-loader.js +190 -36
- data/vendor/assets/javascripts/angular-message-format.js +72 -84
- data/vendor/assets/javascripts/angular-messages.js +158 -68
- data/vendor/assets/javascripts/angular-mocks.js +1033 -402
- data/vendor/assets/javascripts/angular-parse-ext.js +14 -10
- data/vendor/assets/javascripts/angular-resource.js +317 -269
- data/vendor/assets/javascripts/angular-route.js +329 -132
- data/vendor/assets/javascripts/angular-sanitize.js +268 -93
- data/vendor/assets/javascripts/angular-touch.js +46 -413
- data/vendor/assets/javascripts/angular.js +9213 -4485
- metadata +2 -3
- data/vendor/assets/javascripts/angular-scenario.js +0 -44134
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
|
-
* @license AngularJS v1.
|
3
|
-
* (c) 2010-
|
2
|
+
* @license AngularJS v1.8.0
|
3
|
+
* (c) 2010-2020 Google, Inc. http://angularjs.org
|
4
4
|
* License: MIT
|
5
5
|
*/
|
6
6
|
(function(window, angular) {'use strict';
|
@@ -20,9 +20,11 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize');
|
|
20
20
|
var bind;
|
21
21
|
var extend;
|
22
22
|
var forEach;
|
23
|
+
var isArray;
|
23
24
|
var isDefined;
|
24
25
|
var lowercase;
|
25
26
|
var noop;
|
27
|
+
var nodeContains;
|
26
28
|
var htmlParser;
|
27
29
|
var htmlSanitizeWriter;
|
28
30
|
|
@@ -31,13 +33,8 @@ var htmlSanitizeWriter;
|
|
31
33
|
* @name ngSanitize
|
32
34
|
* @description
|
33
35
|
*
|
34
|
-
* # ngSanitize
|
35
|
-
*
|
36
36
|
* The `ngSanitize` module provides functionality to sanitize HTML.
|
37
37
|
*
|
38
|
-
*
|
39
|
-
* <div doc-module-components="ngSanitize"></div>
|
40
|
-
*
|
41
38
|
* See {@link ngSanitize.$sanitize `$sanitize`} for usage.
|
42
39
|
*/
|
43
40
|
|
@@ -50,12 +47,11 @@ var htmlSanitizeWriter;
|
|
50
47
|
* Sanitizes an html string by stripping all potentially dangerous tokens.
|
51
48
|
*
|
52
49
|
* The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
|
53
|
-
* then serialized back to properly escaped
|
50
|
+
* then serialized back to a properly escaped HTML string. This means that no unsafe input can make
|
54
51
|
* it into the returned string.
|
55
52
|
*
|
56
53
|
* The whitelist for URL sanitization of attribute values is configured using the functions
|
57
|
-
* `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link
|
58
|
-
* `$compileProvider`}.
|
54
|
+
* `aHrefSanitizationWhitelist` and `imgSrcSanitizationWhitelist` of {@link $compileProvider}.
|
59
55
|
*
|
60
56
|
* The input may also contain SVG markup if this is enabled via {@link $sanitizeProvider}.
|
61
57
|
*
|
@@ -63,7 +59,7 @@ var htmlSanitizeWriter;
|
|
63
59
|
* @returns {string} Sanitized HTML.
|
64
60
|
*
|
65
61
|
* @example
|
66
|
-
<example module="sanitizeExample" deps="angular-sanitize.js">
|
62
|
+
<example module="sanitizeExample" deps="angular-sanitize.js" name="sanitize-service">
|
67
63
|
<file name="index.html">
|
68
64
|
<script>
|
69
65
|
angular.module('sanitizeExample', ['ngSanitize'])
|
@@ -112,19 +108,19 @@ var htmlSanitizeWriter;
|
|
112
108
|
</file>
|
113
109
|
<file name="protractor.js" type="protractor">
|
114
110
|
it('should sanitize the html snippet by default', function() {
|
115
|
-
expect(element(by.css('#bind-html-with-sanitize div')).
|
111
|
+
expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
|
116
112
|
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
|
117
113
|
});
|
118
114
|
|
119
115
|
it('should inline raw snippet if bound to a trusted value', function() {
|
120
|
-
expect(element(by.css('#bind-html-with-trust div')).
|
116
|
+
expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).
|
121
117
|
toBe("<p style=\"color:blue\">an html\n" +
|
122
118
|
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
123
119
|
"snippet</p>");
|
124
120
|
});
|
125
121
|
|
126
122
|
it('should escape snippet without any filter', function() {
|
127
|
-
expect(element(by.css('#bind-default div')).
|
123
|
+
expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).
|
128
124
|
toBe("<p style=\"color:blue\">an html\n" +
|
129
125
|
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
130
126
|
"snippet</p>");
|
@@ -133,11 +129,11 @@ var htmlSanitizeWriter;
|
|
133
129
|
it('should update', function() {
|
134
130
|
element(by.model('snippet')).clear();
|
135
131
|
element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
|
136
|
-
expect(element(by.css('#bind-html-with-sanitize div')).
|
132
|
+
expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
|
137
133
|
toBe('new <b>text</b>');
|
138
|
-
expect(element(by.css('#bind-html-with-trust div')).
|
134
|
+
expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).toBe(
|
139
135
|
'new <b onclick="alert(1)">text</b>');
|
140
|
-
expect(element(by.css('#bind-default div')).
|
136
|
+
expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).toBe(
|
141
137
|
"new <b onclick=\"alert(1)\">text</b>");
|
142
138
|
});
|
143
139
|
</file>
|
@@ -148,14 +144,17 @@ var htmlSanitizeWriter;
|
|
148
144
|
/**
|
149
145
|
* @ngdoc provider
|
150
146
|
* @name $sanitizeProvider
|
147
|
+
* @this
|
151
148
|
*
|
152
149
|
* @description
|
153
150
|
* Creates and configures {@link $sanitize} instance.
|
154
151
|
*/
|
155
152
|
function $SanitizeProvider() {
|
153
|
+
var hasBeenInstantiated = false;
|
156
154
|
var svgEnabled = false;
|
157
155
|
|
158
156
|
this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
|
157
|
+
hasBeenInstantiated = true;
|
159
158
|
if (svgEnabled) {
|
160
159
|
extend(validElements, svgElements);
|
161
160
|
}
|
@@ -196,7 +195,7 @@ function $SanitizeProvider() {
|
|
196
195
|
* </div>
|
197
196
|
*
|
198
197
|
* @param {boolean=} flag Enable or disable SVG support in the sanitizer.
|
199
|
-
* @returns {boolean
|
198
|
+
* @returns {boolean|$sanitizeProvider} Returns the currently configured value if called
|
200
199
|
* without an argument or self for chaining otherwise.
|
201
200
|
*/
|
202
201
|
this.enableSvg = function(enableSvg) {
|
@@ -208,6 +207,105 @@ function $SanitizeProvider() {
|
|
208
207
|
}
|
209
208
|
};
|
210
209
|
|
210
|
+
|
211
|
+
/**
|
212
|
+
* @ngdoc method
|
213
|
+
* @name $sanitizeProvider#addValidElements
|
214
|
+
* @kind function
|
215
|
+
*
|
216
|
+
* @description
|
217
|
+
* Extends the built-in lists of valid HTML/SVG elements, i.e. elements that are considered safe
|
218
|
+
* and are not stripped off during sanitization. You can extend the following lists of elements:
|
219
|
+
*
|
220
|
+
* - `htmlElements`: A list of elements (tag names) to extend the current list of safe HTML
|
221
|
+
* elements. HTML elements considered safe will not be removed during sanitization. All other
|
222
|
+
* elements will be stripped off.
|
223
|
+
*
|
224
|
+
* - `htmlVoidElements`: This is similar to `htmlElements`, but marks the elements as
|
225
|
+
* "void elements" (similar to HTML
|
226
|
+
* [void elements](https://rawgit.com/w3c/html/html5.1-2/single-page.html#void-elements)). These
|
227
|
+
* elements have no end tag and cannot have content.
|
228
|
+
*
|
229
|
+
* - `svgElements`: This is similar to `htmlElements`, but for SVG elements. This list is only
|
230
|
+
* taken into account if SVG is {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for
|
231
|
+
* `$sanitize`.
|
232
|
+
*
|
233
|
+
* <div class="alert alert-info">
|
234
|
+
* This method must be called during the {@link angular.Module#config config} phase. Once the
|
235
|
+
* `$sanitize` service has been instantiated, this method has no effect.
|
236
|
+
* </div>
|
237
|
+
*
|
238
|
+
* <div class="alert alert-warning">
|
239
|
+
* Keep in mind that extending the built-in lists of elements may expose your app to XSS or
|
240
|
+
* other vulnerabilities. Be very mindful of the elements you add.
|
241
|
+
* </div>
|
242
|
+
*
|
243
|
+
* @param {Array<String>|Object} elements - A list of valid HTML elements or an object with one or
|
244
|
+
* more of the following properties:
|
245
|
+
* - **htmlElements** - `{Array<String>}` - A list of elements to extend the current list of
|
246
|
+
* HTML elements.
|
247
|
+
* - **htmlVoidElements** - `{Array<String>}` - A list of elements to extend the current list of
|
248
|
+
* void HTML elements; i.e. elements that do not have an end tag.
|
249
|
+
* - **svgElements** - `{Array<String>}` - A list of elements to extend the current list of SVG
|
250
|
+
* elements. The list of SVG elements is only taken into account if SVG is
|
251
|
+
* {@link ngSanitize.$sanitizeProvider#enableSvg enabled} for `$sanitize`.
|
252
|
+
*
|
253
|
+
* Passing an array (`[...]`) is equivalent to passing `{htmlElements: [...]}`.
|
254
|
+
*
|
255
|
+
* @return {$sanitizeProvider} Returns self for chaining.
|
256
|
+
*/
|
257
|
+
this.addValidElements = function(elements) {
|
258
|
+
if (!hasBeenInstantiated) {
|
259
|
+
if (isArray(elements)) {
|
260
|
+
elements = {htmlElements: elements};
|
261
|
+
}
|
262
|
+
|
263
|
+
addElementsTo(svgElements, elements.svgElements);
|
264
|
+
addElementsTo(voidElements, elements.htmlVoidElements);
|
265
|
+
addElementsTo(validElements, elements.htmlVoidElements);
|
266
|
+
addElementsTo(validElements, elements.htmlElements);
|
267
|
+
}
|
268
|
+
|
269
|
+
return this;
|
270
|
+
};
|
271
|
+
|
272
|
+
|
273
|
+
/**
|
274
|
+
* @ngdoc method
|
275
|
+
* @name $sanitizeProvider#addValidAttrs
|
276
|
+
* @kind function
|
277
|
+
*
|
278
|
+
* @description
|
279
|
+
* Extends the built-in list of valid attributes, i.e. attributes that are considered safe and are
|
280
|
+
* not stripped off during sanitization.
|
281
|
+
*
|
282
|
+
* **Note**:
|
283
|
+
* The new attributes will not be treated as URI attributes, which means their values will not be
|
284
|
+
* sanitized as URIs using `$compileProvider`'s
|
285
|
+
* {@link ng.$compileProvider#aHrefSanitizationWhitelist aHrefSanitizationWhitelist} and
|
286
|
+
* {@link ng.$compileProvider#imgSrcSanitizationWhitelist imgSrcSanitizationWhitelist}.
|
287
|
+
*
|
288
|
+
* <div class="alert alert-info">
|
289
|
+
* This method must be called during the {@link angular.Module#config config} phase. Once the
|
290
|
+
* `$sanitize` service has been instantiated, this method has no effect.
|
291
|
+
* </div>
|
292
|
+
*
|
293
|
+
* <div class="alert alert-warning">
|
294
|
+
* Keep in mind that extending the built-in list of attributes may expose your app to XSS or
|
295
|
+
* other vulnerabilities. Be very mindful of the attributes you add.
|
296
|
+
* </div>
|
297
|
+
*
|
298
|
+
* @param {Array<String>} attrs - A list of valid attributes.
|
299
|
+
*
|
300
|
+
* @returns {$sanitizeProvider} Returns self for chaining.
|
301
|
+
*/
|
302
|
+
this.addValidAttrs = function(attrs) {
|
303
|
+
if (!hasBeenInstantiated) {
|
304
|
+
extend(validAttrs, arrayToMap(attrs, true));
|
305
|
+
}
|
306
|
+
return this;
|
307
|
+
};
|
308
|
+
|
211
309
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
212
310
|
// Private stuff
|
213
311
|
//////////////////////////////////////////////////////////////////////////////////////////////////
|
@@ -215,17 +313,23 @@ function $SanitizeProvider() {
|
|
215
313
|
bind = angular.bind;
|
216
314
|
extend = angular.extend;
|
217
315
|
forEach = angular.forEach;
|
316
|
+
isArray = angular.isArray;
|
218
317
|
isDefined = angular.isDefined;
|
219
|
-
lowercase = angular
|
318
|
+
lowercase = angular.$$lowercase;
|
220
319
|
noop = angular.noop;
|
221
320
|
|
222
321
|
htmlParser = htmlParserImpl;
|
223
322
|
htmlSanitizeWriter = htmlSanitizeWriterImpl;
|
224
323
|
|
324
|
+
nodeContains = window.Node.prototype.contains || /** @this */ function(arg) {
|
325
|
+
// eslint-disable-next-line no-bitwise
|
326
|
+
return !!(this.compareDocumentPosition(arg) & 16);
|
327
|
+
};
|
328
|
+
|
225
329
|
// Regular Expressions for parsing tags and attributes
|
226
330
|
var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
|
227
331
|
// Match everything outside of normal chars and " (quote character)
|
228
|
-
NON_ALPHANUMERIC_REGEXP = /([
|
332
|
+
NON_ALPHANUMERIC_REGEXP = /([^#-~ |!])/g;
|
229
333
|
|
230
334
|
|
231
335
|
// Good source of info about elements and attributes
|
@@ -234,36 +338,36 @@ function $SanitizeProvider() {
|
|
234
338
|
|
235
339
|
// Safe Void Elements - HTML5
|
236
340
|
// http://dev.w3.org/html5/spec/Overview.html#void-elements
|
237
|
-
var voidElements =
|
341
|
+
var voidElements = stringToMap('area,br,col,hr,img,wbr');
|
238
342
|
|
239
343
|
// Elements that you can, intentionally, leave open (and which close themselves)
|
240
344
|
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
|
241
|
-
var optionalEndTagBlockElements =
|
242
|
-
optionalEndTagInlineElements =
|
345
|
+
var optionalEndTagBlockElements = stringToMap('colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr'),
|
346
|
+
optionalEndTagInlineElements = stringToMap('rp,rt'),
|
243
347
|
optionalEndTagElements = extend({},
|
244
348
|
optionalEndTagInlineElements,
|
245
349
|
optionalEndTagBlockElements);
|
246
350
|
|
247
351
|
// Safe Block Elements - HTML5
|
248
|
-
var blockElements = extend({}, optionalEndTagBlockElements,
|
249
|
-
|
250
|
-
|
352
|
+
var blockElements = extend({}, optionalEndTagBlockElements, stringToMap('address,article,' +
|
353
|
+
'aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,' +
|
354
|
+
'h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,section,table,ul'));
|
251
355
|
|
252
356
|
// Inline Elements - HTML5
|
253
|
-
var inlineElements = extend({}, optionalEndTagInlineElements,
|
254
|
-
|
255
|
-
|
357
|
+
var inlineElements = extend({}, optionalEndTagInlineElements, stringToMap('a,abbr,acronym,b,' +
|
358
|
+
'bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,' +
|
359
|
+
'samp,small,span,strike,strong,sub,sup,time,tt,u,var'));
|
256
360
|
|
257
361
|
// SVG Elements
|
258
362
|
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
|
259
363
|
// Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
|
260
364
|
// They can potentially allow for arbitrary javascript to be executed. See #11290
|
261
|
-
var svgElements =
|
262
|
-
|
263
|
-
|
365
|
+
var svgElements = stringToMap('circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,' +
|
366
|
+
'hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,' +
|
367
|
+
'radialGradient,rect,stop,svg,switch,text,title,tspan');
|
264
368
|
|
265
369
|
// Blocked Elements (will be stripped)
|
266
|
-
var blockedElements =
|
370
|
+
var blockedElements = stringToMap('script,style');
|
267
371
|
|
268
372
|
var validElements = extend({},
|
269
373
|
voidElements,
|
@@ -272,9 +376,9 @@ function $SanitizeProvider() {
|
|
272
376
|
optionalEndTagElements);
|
273
377
|
|
274
378
|
//Attributes that have href and hence need to be sanitized
|
275
|
-
var uriAttrs =
|
379
|
+
var uriAttrs = stringToMap('background,cite,href,longdesc,src,xlink:href,xml:base');
|
276
380
|
|
277
|
-
var htmlAttrs =
|
381
|
+
var htmlAttrs = stringToMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
|
278
382
|
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
|
279
383
|
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
|
280
384
|
'scope,scrolling,shape,size,span,start,summary,tabindex,target,title,type,' +
|
@@ -282,7 +386,7 @@ function $SanitizeProvider() {
|
|
282
386
|
|
283
387
|
// SVG attributes (without "id" and "name" attributes)
|
284
388
|
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
|
285
|
-
var svgAttrs =
|
389
|
+
var svgAttrs = stringToMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
|
286
390
|
'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
|
287
391
|
'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
|
288
392
|
'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
|
@@ -303,35 +407,96 @@ function $SanitizeProvider() {
|
|
303
407
|
svgAttrs,
|
304
408
|
htmlAttrs);
|
305
409
|
|
306
|
-
function
|
307
|
-
|
410
|
+
function stringToMap(str, lowercaseKeys) {
|
411
|
+
return arrayToMap(str.split(','), lowercaseKeys);
|
412
|
+
}
|
413
|
+
|
414
|
+
function arrayToMap(items, lowercaseKeys) {
|
415
|
+
var obj = {}, i;
|
308
416
|
for (i = 0; i < items.length; i++) {
|
309
417
|
obj[lowercaseKeys ? lowercase(items[i]) : items[i]] = true;
|
310
418
|
}
|
311
419
|
return obj;
|
312
420
|
}
|
313
421
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
422
|
+
function addElementsTo(elementsMap, newElements) {
|
423
|
+
if (newElements && newElements.length) {
|
424
|
+
extend(elementsMap, arrayToMap(newElements));
|
425
|
+
}
|
426
|
+
}
|
427
|
+
|
428
|
+
/**
|
429
|
+
* Create an inert document that contains the dirty HTML that needs sanitizing
|
430
|
+
* Depending upon browser support we use one of three strategies for doing this.
|
431
|
+
* Support: Safari 10.x -> XHR strategy
|
432
|
+
* Support: Firefox -> DomParser strategy
|
433
|
+
*/
|
434
|
+
var getInertBodyElement /* function(html: string): HTMLBodyElement */ = (function(window, document) {
|
435
|
+
var inertDocument;
|
436
|
+
if (document && document.implementation) {
|
437
|
+
inertDocument = document.implementation.createHTMLDocument('inert');
|
319
438
|
} else {
|
320
|
-
throw $sanitizeMinErr('noinert',
|
439
|
+
throw $sanitizeMinErr('noinert', 'Can\'t create an inert html document');
|
321
440
|
}
|
322
|
-
var
|
323
|
-
var bodyElements = docElement.getElementsByTagName('body');
|
441
|
+
var inertBodyElement = (inertDocument.documentElement || inertDocument.getDocumentElement()).querySelector('body');
|
324
442
|
|
325
|
-
//
|
326
|
-
|
327
|
-
|
443
|
+
// Check for the Safari 10.1 bug - which allows JS to run inside the SVG G element
|
444
|
+
inertBodyElement.innerHTML = '<svg><g onload="this.parentNode.remove()"></g></svg>';
|
445
|
+
if (!inertBodyElement.querySelector('svg')) {
|
446
|
+
return getInertBodyElement_XHR;
|
328
447
|
} else {
|
329
|
-
|
330
|
-
inertBodyElement =
|
331
|
-
|
332
|
-
|
448
|
+
// Check for the Firefox bug - which prevents the inner img JS from being sanitized
|
449
|
+
inertBodyElement.innerHTML = '<svg><p><style><img src="</style><img src=x onerror=alert(1)//">';
|
450
|
+
if (inertBodyElement.querySelector('svg img')) {
|
451
|
+
return getInertBodyElement_DOMParser;
|
452
|
+
} else {
|
453
|
+
return getInertBodyElement_InertDocument;
|
454
|
+
}
|
455
|
+
}
|
456
|
+
|
457
|
+
function getInertBodyElement_XHR(html) {
|
458
|
+
// We add this dummy element to ensure that the rest of the content is parsed as expected
|
459
|
+
// e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the `<head>` tag.
|
460
|
+
html = '<remove></remove>' + html;
|
461
|
+
try {
|
462
|
+
html = encodeURI(html);
|
463
|
+
} catch (e) {
|
464
|
+
return undefined;
|
465
|
+
}
|
466
|
+
var xhr = new window.XMLHttpRequest();
|
467
|
+
xhr.responseType = 'document';
|
468
|
+
xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false);
|
469
|
+
xhr.send(null);
|
470
|
+
var body = xhr.response.body;
|
471
|
+
body.firstChild.remove();
|
472
|
+
return body;
|
473
|
+
}
|
474
|
+
|
475
|
+
function getInertBodyElement_DOMParser(html) {
|
476
|
+
// We add this dummy element to ensure that the rest of the content is parsed as expected
|
477
|
+
// e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the `<head>` tag.
|
478
|
+
html = '<remove></remove>' + html;
|
479
|
+
try {
|
480
|
+
var body = new window.DOMParser().parseFromString(html, 'text/html').body;
|
481
|
+
body.firstChild.remove();
|
482
|
+
return body;
|
483
|
+
} catch (e) {
|
484
|
+
return undefined;
|
485
|
+
}
|
486
|
+
}
|
487
|
+
|
488
|
+
function getInertBodyElement_InertDocument(html) {
|
489
|
+
inertBodyElement.innerHTML = html;
|
490
|
+
|
491
|
+
// Support: IE 9-11 only
|
492
|
+
// strip custom-namespaced attributes on IE<=11
|
493
|
+
if (document.documentMode) {
|
494
|
+
stripCustomNsAttrs(inertBodyElement);
|
495
|
+
}
|
496
|
+
|
497
|
+
return inertBodyElement;
|
333
498
|
}
|
334
|
-
})(window);
|
499
|
+
})(window, window.document);
|
335
500
|
|
336
501
|
/**
|
337
502
|
* @example
|
@@ -351,22 +516,21 @@ function $SanitizeProvider() {
|
|
351
516
|
} else if (typeof html !== 'string') {
|
352
517
|
html = '' + html;
|
353
518
|
}
|
354
|
-
|
519
|
+
|
520
|
+
var inertBodyElement = getInertBodyElement(html);
|
521
|
+
if (!inertBodyElement) return '';
|
355
522
|
|
356
523
|
//mXSS protection
|
357
524
|
var mXSSAttempts = 5;
|
358
525
|
do {
|
359
526
|
if (mXSSAttempts === 0) {
|
360
|
-
throw $sanitizeMinErr('uinput',
|
527
|
+
throw $sanitizeMinErr('uinput', 'Failed to sanitize html because the input is unstable');
|
361
528
|
}
|
362
529
|
mXSSAttempts--;
|
363
530
|
|
364
|
-
//
|
365
|
-
|
366
|
-
|
367
|
-
}
|
368
|
-
html = inertBodyElement.innerHTML; //trigger mXSS
|
369
|
-
inertBodyElement.innerHTML = html;
|
531
|
+
// trigger mXSS if it is going to happen by reading and writing the innerHTML
|
532
|
+
html = inertBodyElement.innerHTML;
|
533
|
+
inertBodyElement = getInertBodyElement(html);
|
370
534
|
} while (html !== inertBodyElement.innerHTML);
|
371
535
|
|
372
536
|
var node = inertBodyElement.firstChild;
|
@@ -382,16 +546,16 @@ function $SanitizeProvider() {
|
|
382
546
|
|
383
547
|
var nextNode;
|
384
548
|
if (!(nextNode = node.firstChild)) {
|
385
|
-
|
549
|
+
if (node.nodeType === 1) {
|
386
550
|
handler.end(node.nodeName.toLowerCase());
|
387
551
|
}
|
388
|
-
nextNode = node
|
552
|
+
nextNode = getNonDescendant('nextSibling', node);
|
389
553
|
if (!nextNode) {
|
390
554
|
while (nextNode == null) {
|
391
|
-
node = node
|
555
|
+
node = getNonDescendant('parentNode', node);
|
392
556
|
if (node === inertBodyElement) break;
|
393
|
-
nextNode = node
|
394
|
-
|
557
|
+
nextNode = getNonDescendant('nextSibling', node);
|
558
|
+
if (node.nodeType === 1) {
|
395
559
|
handler.end(node.nodeName.toLowerCase());
|
396
560
|
}
|
397
561
|
}
|
@@ -400,7 +564,7 @@ function $SanitizeProvider() {
|
|
400
564
|
node = nextNode;
|
401
565
|
}
|
402
566
|
|
403
|
-
while (node = inertBodyElement.firstChild) {
|
567
|
+
while ((node = inertBodyElement.firstChild)) {
|
404
568
|
inertBodyElement.removeChild(node);
|
405
569
|
}
|
406
570
|
}
|
@@ -481,6 +645,7 @@ function $SanitizeProvider() {
|
|
481
645
|
out(tag);
|
482
646
|
out('>');
|
483
647
|
}
|
648
|
+
// eslint-disable-next-line eqeqeq
|
484
649
|
if (tag == ignoreCurrentElement) {
|
485
650
|
ignoreCurrentElement = false;
|
486
651
|
}
|
@@ -502,28 +667,36 @@ function $SanitizeProvider() {
|
|
502
667
|
* @param node Root element to process
|
503
668
|
*/
|
504
669
|
function stripCustomNsAttrs(node) {
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
var
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
670
|
+
while (node) {
|
671
|
+
if (node.nodeType === window.Node.ELEMENT_NODE) {
|
672
|
+
var attrs = node.attributes;
|
673
|
+
for (var i = 0, l = attrs.length; i < l; i++) {
|
674
|
+
var attrNode = attrs[i];
|
675
|
+
var attrName = attrNode.name.toLowerCase();
|
676
|
+
if (attrName === 'xmlns:ns1' || attrName.lastIndexOf('ns1:', 0) === 0) {
|
677
|
+
node.removeAttributeNode(attrNode);
|
678
|
+
i--;
|
679
|
+
l--;
|
680
|
+
}
|
514
681
|
}
|
515
682
|
}
|
516
|
-
}
|
517
683
|
|
518
|
-
|
519
|
-
|
520
|
-
|
684
|
+
var nextNode = node.firstChild;
|
685
|
+
if (nextNode) {
|
686
|
+
stripCustomNsAttrs(nextNode);
|
687
|
+
}
|
688
|
+
|
689
|
+
node = getNonDescendant('nextSibling', node);
|
521
690
|
}
|
691
|
+
}
|
522
692
|
|
523
|
-
|
524
|
-
if
|
525
|
-
|
693
|
+
function getNonDescendant(propName, node) {
|
694
|
+
// An element is clobbered if its `propName` property points to one of its descendants
|
695
|
+
var nextNode = node[propName];
|
696
|
+
if (nextNode && nodeContains.call(node, nextNode)) {
|
697
|
+
throw $sanitizeMinErr('elclob', 'Failed to sanitize html because the element is clobbered: {0}', node.outerHTML || node.outerText);
|
526
698
|
}
|
699
|
+
return nextNode;
|
527
700
|
}
|
528
701
|
}
|
529
702
|
|
@@ -536,7 +709,9 @@ function sanitizeText(chars) {
|
|
536
709
|
|
537
710
|
|
538
711
|
// define ngSanitize module and register $sanitize service
|
539
|
-
angular.module('ngSanitize', [])
|
712
|
+
angular.module('ngSanitize', [])
|
713
|
+
.provider('$sanitize', $SanitizeProvider)
|
714
|
+
.info({ angularVersion: '1.8.0' });
|
540
715
|
|
541
716
|
/**
|
542
717
|
* @ngdoc filter
|
@@ -544,13 +719,13 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
544
719
|
* @kind function
|
545
720
|
*
|
546
721
|
* @description
|
547
|
-
* Finds links in text input and turns them into html links. Supports `http/https/ftp/mailto` and
|
722
|
+
* Finds links in text input and turns them into html links. Supports `http/https/ftp/sftp/mailto` and
|
548
723
|
* plain email address links.
|
549
724
|
*
|
550
725
|
* Requires the {@link ngSanitize `ngSanitize`} module to be installed.
|
551
726
|
*
|
552
727
|
* @param {string} text Input text.
|
553
|
-
* @param {string} target Window (`_blank|_self|_parent|_top`) or named frame to open links in.
|
728
|
+
* @param {string} [target] Window (`_blank|_self|_parent|_top`) or named frame to open links in.
|
554
729
|
* @param {object|function(url)} [attributes] Add custom attributes to the link element.
|
555
730
|
*
|
556
731
|
* Can be one of:
|
@@ -568,7 +743,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
568
743
|
<span ng-bind-html="linky_expression | linky"></span>
|
569
744
|
*
|
570
745
|
* @example
|
571
|
-
<example module="linkyExample" deps="angular-sanitize.js">
|
746
|
+
<example module="linkyExample" deps="angular-sanitize.js" name="linky-filter">
|
572
747
|
<file name="index.html">
|
573
748
|
<div ng-controller="ExampleController">
|
574
749
|
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
@@ -616,10 +791,10 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
616
791
|
angular.module('linkyExample', ['ngSanitize'])
|
617
792
|
.controller('ExampleController', ['$scope', function($scope) {
|
618
793
|
$scope.snippet =
|
619
|
-
'Pretty text with some links:\n'+
|
620
|
-
'http://angularjs.org/,\n'+
|
621
|
-
'mailto:us@somewhere.org,\n'+
|
622
|
-
'another@somewhere.org,\n'+
|
794
|
+
'Pretty text with some links:\n' +
|
795
|
+
'http://angularjs.org/,\n' +
|
796
|
+
'mailto:us@somewhere.org,\n' +
|
797
|
+
'another@somewhere.org,\n' +
|
623
798
|
'and one more: ftp://127.0.0.1/.';
|
624
799
|
$scope.snippetWithSingleURL = 'http://angularjs.org/';
|
625
800
|
}]);
|
@@ -667,7 +842,7 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
667
842
|
*/
|
668
843
|
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
|
669
844
|
var LINKY_URL_REGEXP =
|
670
|
-
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
|
845
|
+
/((s?ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
|
671
846
|
MAILTO_REGEXP = /^mailto:/i;
|
672
847
|
|
673
848
|
var linkyMinErr = angular.$$minErr('linky');
|