Show More
@@ -1,122 +1,126 b'' | |||||
1 | //---------------------------------------------------------------------------- |
|
1 | //---------------------------------------------------------------------------- | |
2 | // Copyright (C) 2014 The IPython Development Team |
|
2 | // Copyright (C) 2014 The IPython Development Team | |
3 | // |
|
3 | // | |
4 | // Distributed under the terms of the BSD License. The full license is in |
|
4 | // Distributed under the terms of the BSD License. The full license is in | |
5 | // the file COPYING, distributed as part of this software. |
|
5 | // the file COPYING, distributed as part of this software. | |
6 | //---------------------------------------------------------------------------- |
|
6 | //---------------------------------------------------------------------------- | |
7 |
|
7 | |||
8 | //============================================================================ |
|
8 | //============================================================================ | |
9 | // Utilities |
|
9 | // Utilities | |
10 | //============================================================================ |
|
10 | //============================================================================ | |
11 | IPython.namespace('IPython.security'); |
|
11 | IPython.namespace('IPython.security'); | |
12 |
|
12 | |||
13 | IPython.security = (function (IPython) { |
|
13 | IPython.security = (function (IPython) { | |
14 | "use strict"; |
|
14 | "use strict"; | |
15 |
|
15 | |||
16 | var utils = IPython.utils; |
|
16 | var utils = IPython.utils; | |
17 |
|
17 | |||
18 | var noop = function (x) { return x; }; |
|
18 | var noop = function (x) { return x; }; | |
19 |
|
19 | |||
20 | var cmp_tree = function (a, b) { |
|
20 | var cmp_tree = function (a, b) { | |
21 | // compare two HTML trees |
|
21 | // compare two HTML trees | |
22 | // only checks the tag structure is preserved, |
|
22 | // only checks the tag structure is preserved, | |
23 | // not any attributes or contents |
|
23 | // not any attributes or contents | |
24 | if (a.length !== b.length) { |
|
24 | if (a.length !== b.length) { | |
25 | return false; |
|
25 | return false; | |
26 | } |
|
26 | } | |
27 |
|
27 | |||
28 | for (var i = a.length - 1; i >= 0; i--) { |
|
28 | for (var i = a.length - 1; i >= 0; i--) { | |
29 | if ((a[i].tagName || '').toLowerCase() != (b[i].tagName || '').toLowerCase()) { |
|
29 | if ((a[i].tagName || '').toLowerCase() != (b[i].tagName || '').toLowerCase()) { | |
30 | return false; |
|
30 | return false; | |
31 | } |
|
31 | } | |
32 | } |
|
32 | } | |
33 | var ac = a.children(); |
|
33 | var ac = a.children(); | |
34 | var bc = b.children(); |
|
34 | var bc = b.children(); | |
35 | if (ac.length === 0 && bc.length === 0) { |
|
35 | if (ac.length === 0 && bc.length === 0) { | |
36 | return true; |
|
36 | return true; | |
37 | } |
|
37 | } | |
38 | return cmp_tree(ac, bc); |
|
38 | return cmp_tree(ac, bc); | |
39 | }; |
|
39 | }; | |
40 |
|
40 | |||
41 | var caja; |
|
41 | var caja; | |
42 | if (window && window.html) { |
|
42 | if (window && window.html) { | |
43 | caja = window.html; |
|
43 | caja = window.html; | |
44 | caja.html4 = window.html4; |
|
44 | caja.html4 = window.html4; | |
45 | } |
|
45 | } | |
46 |
|
46 | |||
47 | var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) { |
|
47 | var sanitizeAttribs = function (tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger) { | |
48 | // wrap sanitizeAttribs into trusting data-attributes |
|
48 | // wrap sanitizeAttribs into trusting data-attributes | |
49 | var ATTRIBS = caja.html4.ATTRIBS; |
|
49 | var ATTRIBS = caja.html4.ATTRIBS; | |
50 | for (var i = 0; i < attribs.length; i += 2) { |
|
50 | for (var i = 0; i < attribs.length; i += 2) { | |
51 | var attribName = attribs[i]; |
|
51 | var attribName = attribs[i]; | |
52 | if (attribName.substr(0,5) == 'data-') { |
|
52 | if (attribName.substr(0,5) == 'data-') { | |
53 | var attribKey = '*::' + attribName; |
|
53 | var attribKey = '*::' + attribName; | |
54 | if (!ATTRIBS.hasOwnProperty(attribKey)) { |
|
54 | if (!ATTRIBS.hasOwnProperty(attribKey)) { | |
55 | ATTRIBS[attribKey] = 0; |
|
55 | ATTRIBS[attribKey] = 0; | |
56 | } |
|
56 | } | |
57 | } |
|
57 | } | |
58 | } |
|
58 | } | |
59 | return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger); |
|
59 | return caja.sanitizeAttribs(tagName, attribs, opt_naiveUriRewriter, opt_nmTokenPolicy, opt_logger); | |
60 | }; |
|
60 | }; | |
61 |
|
61 | |||
62 | var sanitize = function (html, log) { |
|
62 | var sanitize = function (html, log) { | |
63 | // sanitize HTML |
|
63 | // sanitize HTML | |
64 | // returns a struct of |
|
64 | // returns a struct of | |
65 | // { |
|
65 | // { | |
66 | // src: original_html, |
|
66 | // src: original_html, | |
67 | // sanitized: the_sanitized_html, |
|
67 | // sanitized: the_sanitized_html, | |
68 |
// safe: bool // false if the sanitizer |
|
68 | // _maybe_safe: bool // false if the sanitizer definitely made changes. | |
|
69 | // This is an incomplete indication, | |||
|
70 | // only used to indicate whether further verification is necessary. | |||
69 | // } |
|
71 | // } | |
70 | var result = { |
|
72 | var result = { | |
71 | src : html, |
|
73 | src : html, | |
72 | safe : true |
|
74 | _maybe_safe : true | |
73 | }; |
|
75 | }; | |
74 | var record_messages = function (msg, opts) { |
|
76 | var record_messages = function (msg, opts) { | |
75 | console.log("HTML Sanitizer", msg, opts); |
|
77 | console.log("HTML Sanitizer", msg, opts); | |
76 | result.safe = false; |
|
78 | result._maybe_safe = false; | |
77 | }; |
|
79 | }; | |
78 |
|
80 | |||
79 | var html4 = caja.html4; |
|
81 | var html4 = caja.html4; | |
80 | var policy = function (tagName, attribs) { |
|
82 | var policy = function (tagName, attribs) { | |
81 | if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) { |
|
83 | if (!(html4.ELEMENTS[tagName] & html4.eflags.UNSAFE)) { | |
82 | return { |
|
84 | return { | |
83 | 'attribs': sanitizeAttribs(tagName, attribs, |
|
85 | 'attribs': sanitizeAttribs(tagName, attribs, | |
84 | noop, noop, record_messages) |
|
86 | noop, noop, record_messages) | |
85 | }; |
|
87 | }; | |
86 | } else { |
|
88 | } else { | |
87 | record_messages(tagName + " removed", { |
|
89 | record_messages(tagName + " removed", { | |
88 | change: "removed", |
|
90 | change: "removed", | |
89 | tagName: tagName |
|
91 | tagName: tagName | |
90 | }); |
|
92 | }); | |
91 | } |
|
93 | } | |
92 | }; |
|
94 | }; | |
93 |
|
95 | |||
94 | result.sanitized = caja.sanitizeWithPolicy(html, policy); |
|
96 | result.sanitized = caja.sanitizeWithPolicy(html, policy); | |
95 | return result; |
|
97 | return result; | |
96 | }; |
|
98 | }; | |
97 |
|
99 | |||
98 | var sanitize_html = function (html) { |
|
100 | var sanitize_html = function (html) { | |
99 | // shorthand for str-to-str conversion, dropping the struct |
|
101 | // shorthand for str-to-str conversion, dropping the struct | |
100 | return sanitize(html).sanitized; |
|
102 | return sanitize(html).sanitized; | |
101 | }; |
|
103 | }; | |
102 |
|
104 | |||
103 | var is_safe = function (html) { |
|
105 | var is_safe = function (html) { | |
104 | // just return bool for whether an HTML string is safe |
|
106 | // just return bool for whether an HTML string is safe | |
105 | var result = sanitize(html); |
|
107 | var result = sanitize(html); | |
106 |
|
108 | |||
107 | // caja can strip whole elements without logging, |
|
109 | // caja can strip whole elements without logging, | |
108 | // so double-check that node structure didn't change |
|
110 | // so double-check that node structure didn't change | |
109 | if (result.safe) { |
|
111 | if (result._maybe_safe) { | |
110 | result.safe = cmp_tree($(result.sanitized), $(html)); |
|
112 | result.safe = cmp_tree($(result.sanitized), $(html)); | |
|
113 | } else { | |||
|
114 | result.safe = false; | |||
111 | } |
|
115 | } | |
112 | return result.safe; |
|
116 | return result.safe; | |
113 | }; |
|
117 | }; | |
114 |
|
118 | |||
115 | return { |
|
119 | return { | |
116 | is_safe: is_safe, |
|
120 | is_safe: is_safe, | |
117 | sanitize: sanitize, |
|
121 | sanitize: sanitize, | |
118 | sanitize_html: sanitize_html |
|
122 | sanitize_html: sanitize_html | |
119 | }; |
|
123 | }; | |
120 |
|
124 | |||
121 | }(IPython)); |
|
125 | }(IPython)); | |
122 |
|
126 |
General Comments 0
You need to be logged in to leave comments.
Login now