Changeset a30779 in indico
- Timestamp:
- 10/08/10 15:55:20 (3 years ago)
- Branches:
- master, burotel, hello-world-walkthrough, ipv6, new-webex, v0.97-series, v0.98-series, v0.98.2, v0.98.3, v0.98b1, v0.98b2, v0.99, b8c30da8ebdbdcbd675a873997cc3e95f567de49, 36509dd327b5670bb394f5ec070c14653b4c9c19
- Children:
- a9e8ac
- Parents:
- 203b37
- git-author:
- Leszek Syroka <leszek.marek.syroka@…> (06/04/10 15:39:42)
- git-committer:
- Jose Benito <jose.benito.gonzalez@…> (10/08/10 15:55:20)
- Location:
- indico
- Files:
-
- 6 edited
- 1 moved
-
MaKaC/common/security.py (modified) (2 diffs)
-
MaKaC/webinterface/common/tools.py (modified) (4 diffs)
-
MaKaC/webinterface/tpls/js/vars.js.tpl (modified) (2 diffs)
-
htdocs/js/indico/Common/Loader.js (modified) (1 diff)
-
htdocs/js/indico/Common/htmlparser.js (moved) (moved from indico/htdocs/js/indico/Legacy/htmlparser.js) (7 diffs)
-
htdocs/js/indico/Legacy/Dialogs.js (modified) (2 diffs)
-
htdocs/js/indico/Legacy/Loader.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
indico/MaKaC/common/security.py
rbdd862 ra30779 23 23 24 24 from MaKaC.errors import MaKaCError, htmlScriptError, htmlForbiddenTag 25 from MaKaC.webinterface.common.tools import scriptDetection,escape_html, restrictedHTML25 from MaKaC.webinterface.common.tools import escape_html, restrictedHTML 26 26 27 27 """ … … 72 72 params[param][i] = escape_html(item) 73 73 74 ## elif level == 1: 75 ## #level 1 or default 76 ## #raise error if script or style detected 77 ## ret = None 78 ## for param in params.keys(): 79 ## if isinstance(params[param], str): 80 ## ret = scriptDetection(params[param]) 81 ## if not restrictedHTML(params[param], level): 82 ## raise htmlForbiddenTag(params[param]) 83 ## elif isinstance(params[param], list): 84 ## for item in params[param]: 85 ## if isinstance(item, str): 86 ## ret = scriptDetection(item) 87 ## if ret: 88 ## raise htmlScriptError(item) 89 ## if not restrictedHTML(item, level): 90 ## raise htmlForbiddenTag(item) 91 ## if ret: 92 ## raise htmlScriptError(params[param]) 93 ## 94 ## elif level == 2: 95 ## #raise error if script but style accepted 96 ## ret = None 97 ## for param in params.keys(): 98 ## if isinstance(params[param], str): 99 ## ret = scriptDetection(params[param], allowStyle=True) 100 ## if ret: 101 ## raise htmlScriptError(params[param]) 102 ## ret = restrictedHTML(params[param], level) 103 ## if not ret: 104 ## raise htmlForbiddenTag(params[param]) 105 ## elif isinstance(params[param], list): 106 ## for item in params[param]: 107 ## if isinstance(item, str): 108 ## ret = scriptDetection(item, allowStyle=True) 109 ## if ret: 110 ## raise htmlScriptError(item) 111 ## ret = restrictedHTML(item, level) 112 ## if not ret: 113 ## raise htmlForbiddenTag(item) 114 74 115 # raise error if form or iframe tags are used 75 116 elif level == 1: 76 117 #level 1 or default 77 118 #raise error if script or style detected 78 ret = None79 119 for param in params.keys(): 80 120 if isinstance(params[param], str): 81 ret = scriptDetection(params[param]) 82 if not restrictedHTML(params[param]): 121 if not restrictedHTML(params[param], level): 83 122 raise htmlForbiddenTag(params[param]) 84 123 elif isinstance(params[param], list): 85 124 for item in params[param]: 86 125 if isinstance(item, str): 87 ret = scriptDetection(item) 88 if ret: 89 raise htmlScriptError(item) 90 if not restrictedHTML(item): 126 if not restrictedHTML(item, level): 91 127 raise htmlForbiddenTag(item) 92 if ret:93 raise htmlScriptError(params[param])94 128 95 129 elif level == 2: 96 130 #raise error if script but style accepted 97 ret = None98 131 for param in params.keys(): 99 132 if isinstance(params[param], str): 100 ret = scriptDetection(params[param], allowStyle=True) 101 if ret: 102 raise htmlScriptError(params[param]) 103 ret = restrictedHTML(params[param]) 104 if not ret: 133 if not restrictedHTML(params[param], level): 105 134 raise htmlForbiddenTag(params[param]) 106 135 elif isinstance(params[param], list): 107 136 for item in params[param]: 108 137 if isinstance(item, str): 109 ret = scriptDetection(item, allowStyle=True) 110 if ret: 111 raise htmlScriptError(item) 112 ret = restrictedHTML(item) 113 if not ret: 138 if not restrictedHTML(params[param], level): 114 139 raise htmlForbiddenTag(item) 115 140 -
indico/MaKaC/webinterface/common/tools.py
rb25817 ra30779 19 19 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 20 20 from MaKaC.common.logger import Logger 21 from HTMLParser import HTMLParser, HTMLParseError 22 from xml.sax.saxutils import unescape 21 23 22 24 import re 23 24 25 25 26 26 allowedTags = ["a","abbr","acronym","address","area", … … 38 38 "p","pre", 39 39 "q", 40 "s","samp","small","span","strike","strong","s tyle","sub","sup",40 "s","samp","small","span","strike","strong","sub","sup", 41 41 "table","tbody","td","tfoot","th","thead","tr","tt", 42 42 "u","ul", 43 43 "var"] 44 44 45 notAllowedTags = [ "applet", 46 "base", "basefont", "button", 47 "form", "frame", "frameset", 48 "head", 49 "iframe", "input", "isindex", 50 "label", "link", 51 "meta", 52 "noframe", "noscript", 53 "object", "optgroup", "option" 54 "param", 55 "script", "select", 56 "textarea", 57 "title", "embed"] 58 45 allowedAttrs = ["align", "abbr", "alt", 46 "border", "bgcolor", 47 "class", "cellpadding", "color", "char", "charoff", "cite", "clear", "colspan", "compact", 48 "dir", "disabled", "face", 49 "href", "height", "headers","hreflang","hspace", 50 "id", "ismap", 51 "lang", 52 "name", "noshade", "nowrap", 53 "rel", "rev", "rowspan", "rules", 54 "size", "scope", "shape", "span","start", "summary", 55 "title", "tabindex", "type", 56 "valign", "value", "vspace", 57 "width"] 58 59 allowedCssProperties = [ "background-color", "border-top-color", "border-top-style", "border-top-width", 60 "border-top", "border-right-color", "border-right-style", "border-right-width", 61 "border-right", "border-bottom-color", "border-bottom-style", "border-bottom-width", 62 "border-bottom", "border-left-color", "border-left-style", "border-left-width", 63 "border-left", "border-color", "border-style", "border-width", "border", "bottom", 64 "border-collapse", "border-spacing", 65 "color", "clear", "clip", "caption-side", 66 "display", "direction", 67 "empty-cells", 68 "float","font-size","font-family","font-style","font","font-variant","font-weight", 69 "font-size-adjust", "font-stretch", 70 "height", 71 "left", "list-style-type", "list-style-position", "line-height", "letter-spacing", 72 "marker-offset","margin","margin-left","margin-right","margin-top","margin-bottom","max-height", 73 "min-height","max-width", "min-width", "marks", 74 "overflow", "outline-color", "outline-style", "outline-width", "outline", "orphans", 75 "position", "padding-top", "padding-right", "padding-bottom", "padding-left", "padding", 76 "page", "page-break-after", "page-break-before", "page-break-inside", 77 "quotes", 78 "right", 79 "size", 80 "text-align", "top", "table-layout", "text-decoration", "text-indent", "text-shadow", 81 "text-transform", 82 "unicode-bidi", 83 "visibility", "vertical-align", 84 "width", "widows", "white-space", "word-spacing", "word-wrap", 85 "z-index"] 86 87 allowedCssKeywords = ['auto', 'aqua', 88 'black', 'block', 'blue', 'bold', 'both', 'bolder', 'bottom', 'brown', 89 'center', 'collapse', 90 'dashed', 'dotted', 91 'fuchsia', 92 'gray', 'green', 93 '!important', 'italic', 'inherit', 94 'left', 'lime', 'large', 'larger', 'length', 'lighter', 95 'maroon', 'medium', 'middle', 96 'none', 'navy', 'normal', 'nowrap', 97 'olive', 'oblique', 98 'pointer', 'purple', 99 'red', 'right', 100 'small', 'smaller', 'solid', 'silver', 101 'teal', 'top', 'transparent', 102 'underline', 103 'white', 104 'x-small', 'xx-small', 'x-large', 'xx-large', 105 'yellow'] 106 107 allowedProtocols = [ 'afs', 'aim', 108 'callto', 109 'feed', 'ftp', 110 'http', 'https', 111 'irc', 112 'mailto', 113 'news', 114 'gopher', 115 'nntp', 116 'rsync', 'rtsp', 117 'ssh', 'sftp', 118 'tag', 'telnet', 119 'urn', 120 'webcal', 121 'xmpp' ] 122 123 urlProperties = ['action', 124 'cite', 125 'href', 126 'longdesc', 127 'src', 128 'xlink:href', 'xml:base'] 129 ## 130 ##notAllowedTags = [ "applet", 131 ## "base", "basefont", "button", 132 ## "embed", 133 ## "form", "frame", "frameset", 134 ## "head", 135 ## "iframe", "input", "isindex", 136 ## "label", "link", 137 ## "meta", 138 ## "noframe", "noscript", 139 ## "object", "optgroup", "option" 140 ## "param", 141 ## "script", "select", 142 ## "textarea", 143 ## "title"] 144 ## 59 145 60 146 # Generate the regular expression objects to found the not allowed tags 61 147 tagSearch = re.compile("< *[^<^>^ ]+",re.IGNORECASE|re.DOTALL) 62 148 63 scriptStr = "\s*(s|s|S)"\64 "\s*(c|c|C)"\65 "\s*(r|r|R)"\66 "\s*(i|i|I)"\67 "\s*(p|p|P)"\68 "\s*(t|p|T)"69 script = re.compile("< *%s"%scriptStr,re.IGNORECASE|re.DOTALL)70 71 iframeStr = "\s*(i|i|I)"\72 "\s*(f|f|F)"\73 "\s*(r|r|R)"\74 "\s*(a|a|A)"\75 "\s*(m|m|M)"\76 "\s*(e|e|E)"77 iframe = re.compile("< *%s"%iframeStr,re.IGNORECASE|re.DOTALL)78 79 formStr = "\s*(f|f|F)"\80 "\s*(o|o|O)"\81 "\s*(r|r|R)"\82 "\s*(m|m|M)"83 form = re.compile("< *%s"%formStr,re.IGNORECASE|re.DOTALL)84 85 onList = ["onblur","onchange","onclick","ondblclick","onerror","onfocus",86 "onkeydown","onkeypress","onkeyup","onload","onmousedown","onmousemove",87 "onmouseout","onmouseover","onmouseup","onreset","onresize","onselect",88 "onsubmit","onunload"]89 90 on = re.compile("<[^>]*(%s)"%"|".join(onList), re.IGNORECASE|re.DOTALL)91 92 style = re.compile("<[^>]*style")93 94 def scriptDetection(txt, allowStyle=False):95 #search for "<script> tag96 if script.findall(txt):97 return True98 #search for javascript event manager99 if on.findall(txt):100 return True101 if not allowStyle:102 #search for style103 if style.findall(txt):104 return True105 return False149 ##scriptStr = "\s*(s|s|S)"\ 150 ## "\s*(c|c|C)"\ 151 ## "\s*(r|r|R)"\ 152 ## "\s*(i|i|I)"\ 153 ## "\s*(p|p|P)"\ 154 ## "\s*(t|p|T)" 155 ##script = re.compile("< *%s"%scriptStr,re.IGNORECASE|re.DOTALL) 156 ## 157 ##iframeStr = "\s*(i|i|I)"\ 158 ## "\s*(f|f|F)"\ 159 ## "\s*(r|r|R)"\ 160 ## "\s*(a|a|A)"\ 161 ## "\s*(m|m|M)"\ 162 ## "\s*(e|e|E)" 163 ##iframe = re.compile("< *%s"%iframeStr,re.IGNORECASE|re.DOTALL) 164 ## 165 ##formStr = "\s*(f|f|F)"\ 166 ## "\s*(o|o|O)"\ 167 ## "\s*(r|r|R)"\ 168 ## "\s*(m|m|M)" 169 ##form = re.compile("< *%s"%formStr,re.IGNORECASE|re.DOTALL) 170 ## 171 ##onList = ["onblur","onchange","onclick","ondblclick","onerror","onfocus", 172 ## "onkeydown","onkeypress","onkeyup","onload","onmousedown","onmousemove", 173 ## "onmouseout","onmouseover","onmouseup","onreset","onresize","onselect", 174 ## "onsubmit","onunload"] 175 ## 176 ##on = re.compile("<[^>]*(%s)"%"|".join(onList), re.IGNORECASE|re.DOTALL) 177 ## 178 ##style = re.compile("<[^>]*style") 179 180 ##def scriptDetection(txt, allowStyle=False): 181 ## #search for "<script> tag 182 ## if script.findall(txt): 183 ## return True 184 ## #search for javascript event manager 185 ## if on.findall(txt): 186 ## return True 187 ## if not allowStyle: 188 ## #search for style 189 ## if style.findall(txt): 190 ## return True 191 ## return False 106 192 107 193 ##def restrictedHTML(txt): … … 112 198 ## return True 113 199 114 def restrictedHTML(txt):115 #use a black list116 notFound = True117 for tag in tagSearch.findall(txt):118 tag = tag[1:].strip()119 if tag:120 if tag[0] == "/":121 tag = tag[1:].strip()122 if tag:123 if tag.lower() in notAllowedTags:124 notFound = False125 return notFound200 ##def restrictedHTML(txt): 201 ## #use a black list 202 ## notFound = True 203 ## for tag in tagSearch.findall(txt): 204 ## tag = tag[1:].strip() 205 ## if tag: 206 ## if tag[0] == "/": 207 ## tag = tag[1:].strip() 208 ## if tag: 209 ## if tag.lower() in notAllowedTags: 210 ## notFound = False 211 ## return notFound 126 212 127 213 ##def restrictedHTML(txt): … … 135 221 ## return True 136 222 223 224 class HarmfulHTMLException: 225 226 def __init__(self, msg, pos = 0): 227 self.msg = 'Potentially harmful HTML: "%s" found at %s' % (msg, pos) 228 229 class RestrictedHTMLParser( HTMLParser ): 230 231 _defaultSanitizationLevel = 1 232 233 def __init__( self, sanitizationLevel = _defaultSanitizationLevel): 234 HTMLParser.__init__(self) 235 if sanitizationLevel not in range(0,3): 236 sanitizationLevel = self._defaultSanitizationLevel 237 self._sanitizationLevel = sanitizationLevel 238 239 def getSanitizationLevel(self): 240 return self._sanitizationLevel 241 242 def setSanitizationLevel(self, sanitizationLevel): 243 if sanitizationLevel not in range(0,3): 244 sanitizationLevel = self._defaultSanitizationLevel 245 self._sanitizationLevel = sanitizationLevel 246 247 def handle_inlineStyle(self, style): 248 # disallow urls 249 style = re.compile('url\s*\(\s*[^\s)]+?\s*\)\s*').sub(' ', style) 250 # gauntlet 251 if not re.match("""^([\-:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$""", style): raise HarmfulHTMLException(style, self.getpos()) 252 if not re.match("^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$", style): raise HarmfulHTMLException(style, self.getpos()) 253 for prop, value in re.findall("([-\w]+)\s*:\s*([^:;]*)", style): 254 if not value: continue 255 if prop.lower() in allowedCssProperties or \ 256 prop.split('-')[0].lower() in ['background', 'border', 'margin', 'padding']: 257 for keyword in value.split(): 258 if not keyword.lower() in allowedCssKeywords and \ 259 not re.match("^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\-?\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$", keyword): 260 raise HarmfulHTMLException(style, self.getpos()) 261 else: 262 raise HarmfulHTMLException(style, self.getpos()) 263 264 def handle_starttag(self, tag, attrs): 265 if tag not in allowedTags: 266 raise HarmfulHTMLException( tag, self.getpos() ) 267 for attr in attrs: 268 if self.getSanitizationLevel() >= 2 and attr[0] == 'style': 269 self.handle_inlineStyle(attr[1]) 270 elif attr[0] not in allowedAttrs: 271 raise HarmfulHTMLException(attr[0], self.getpos()) 272 elif attr[0] in urlProperties: 273 val_unescaped = re.sub("[`\000-\040\177-\240\s]+", '', unescape(attr[1])).lower() 274 #remove replacement characters from unescaped characters 275 val_unescaped = val_unescaped.replace(u"\ufffd", "") 276 if (re.match("^[a-z0-9][-+.a-z0-9]*:", val_unescaped) and 277 (val_unescaped.split(':')[0] not in 278 allowedProtocols)): 279 raise HarmfulHTMLException(val_unescaped.split(':')[0], self.getpos()) 280 281 282 def restrictedHTML(txt, sanitizationLevel): 283 try: 284 parser = RestrictedHTMLParser(sanitizationLevel) 285 parser.feed(txt) 286 parser.close() 287 except (HarmfulHTMLException, HTMLParseError): 288 return False 289 return True 137 290 138 291 def hasTags(s): -
indico/MaKaC/webinterface/tpls/js/vars.js.tpl
r6b4ff5 ra30779 4 4 <% from MaKaC.rb_location import Location %> 5 5 <% import simplejson %> 6 <% import MaKaC.webinterface.common.tools as securityTools %> 6 7 <%! 7 8 config = Config.getInstance() … … 141 142 Locations: <%= jsonEncode(locationList) %> 142 143 }, 144 145 Security:{ 146 allowedTags: "<%= ",".join(securityTools.allowedTags) %>", 147 allowedAttributes: "<%= ",".join(securityTools.allowedAttrs) %>", 148 allowedCssKeywords: "<%= ",".join(securityTools.allowedCssKeywords) %>", 149 allowedCssProperties: "<%= ",".join(securityTools.allowedCssProperties) %>", 150 allowedProtocols: "<%= ",".join(securityTools.allowedProtocols) %>", 151 urlProperties: "<%= ",".join(securityTools.urlProperties) %>", 152 sanitizationLevel: <%= Config.getInstance().getSanitizationLevel() %> 153 }, 154 143 155 Settings: { 144 156 ExtAuthenticators: <%= extAuths %>, -
indico/htdocs/js/indico/Common/Loader.js
r3cc6b6 ra30779 1 1 include(ScriptRoot + "indico/Common/TimezoneSelector.js"); 2 2 include(ScriptRoot + "indico/Common/IntelligentSearchBox.js"); 3 include(ScriptRoot + "indico/Common/htmlparser.js"); -
indico/htdocs/js/indico/Common/htmlparser.js
r203b37 ra30779 14 14 * 15 15 * // or to escape harmful html and scripts 16 * escapeHarmfulHTML(htmlString, params);16 * escapeHarmfulHTML(htmlString, sanitizationLevel, params); 17 17 * 18 18 * // or to get an XML string: … … 100 100 }); 101 101 102 if ( self.handler.start ) 103 self.handler.start( tagName, attrs, unary ); 102 self.handler.start( tagName, attrs, unary ); 104 103 } 105 104 }; … … 255 254 }); 256 255 257 //Regular Expressions for parsing properties and values258 var whitespaces = /\s*/;259 var propertyName = /[\w-]+/;260 var propertyPattern = new RegExp( whitespaces.source + propertyName.source + whitespaces.source + /:/.source );261 262 var valueElementName = /#?[\w\/\:\.]+%?/;263 var valueElementEnding = /(((\(?\)\s*;)|[)(,;\s]))?/;264 const valueElement = new RegExp(whitespaces.source + valueElementName.source + whitespaces.source + valueElementEnding.source);265 266 var singleValue = /\s*(\w+%?)\s*/267 var multipleValues = /((\s*[\w]+\s*%?,?)+)/;268 var link = /(\s*\w+:\/\/[\w\/\.]+\s*)/;269 var color = /(\s*#(\w){6}\s*)/;270 var valuePatternName = new RegExp(color.source + "|(" + singleValue.source + "(\\s*\\((" + multipleValues.source + "|" + link.source +")\\)\\s*)?)");271 var valuePatternLoop = new RegExp("(" + whitespaces.source + valuePatternName.source + whitespaces.source + ")+");272 var valuePattern = new RegExp(valuePatternLoop.source + /;?/.source);273 274 256 //Default parameters 275 257 276 258 //Properties which can appear in a CSS 277 var propertyWhitelist = makeMap("background-color,border-top-color,border-top-style,border-top-width," + 278 "border-top,border-right-color,border-right-style,border-right-width," + 279 "border-right,border-bottom-color,border-bottom-style,border-bottom-width," + 280 "border-bottom,border-left-color,border-left-style,border-left-width," + 281 "border-left,border-color,border-style,border-width,border,bottom," + 282 "border-collapse,border-spacing," + 283 "color,clear,clip,caption-side," + 284 "display,direction," + 285 "empty-cells," + 286 "float,font-size,font-family,font-style,font,font-variant,font-weight," + 287 "font-size-adjust,font-stretch," + 288 "height," + 289 "left,list-style-type,list-style-position,line-height,letter-spacing," + 290 "marker-offset,margin,margin-left,margin-rigth,margin-top,margin-bottom,max-height," + 291 "min-height,max-width,min-width,marks," + 292 "overflow,outline-color,outline-style,outline-width,outline,orphans," + 293 "position,padding-top,padding-right,padding-bottom,padding-left,padding," + 294 "page,page-break-after,page-break-before,page-break-inside," + 295 "quotes," + 296 "right," + 297 "size," + 298 "text-align,top,table-layout,text-decoration,text-indent,text-shadow," + 299 "text-transform," + 300 "unicode-bidi," + 301 "visibility,vertical-align," + 302 "width,widows,white-space,word-spacing,word-wrap," + 303 "z-index"); 304 305 //Values which cannot appear in a CSS 306 var valueBlacklist = makeMap(""); 259 var propertyWhitelist = makeMap( Indico.Security.allowedCssProperties ); 260 261 //Keywords which can appear in a CSS 262 var keywordWhitelist = makeMap( Indico.Security.allowedCssKeywords ); 307 263 308 264 type("inlineCSSParser",[], 309 265 { 310 266 parse: function(){ 311 312 267 var result = ""; 313 var property;314 var values;315 268 var security = 0; 316 269 317 while (this.css.replace(/\s+/g,"")){ 318 319 property = this.getProperty(); 320 values = this.getValues(); 321 322 if(this.propertyWhitelist[property]) 323 { 324 result += property + ":"; 325 for(var i = 0; i < values.length; ++i) 326 if(!this.valueBlacklist[values[i]]) 327 result += " " + values[i]; 328 else 329 security = 1; 330 } 331 else 332 security = 1; 270 // disallow urls 271 this.css = this.css.replace(/url\s*\(\s*[^\s)]+?\s*\)\s*/, ' ') 272 // gauntlet 273 if (!(/^([\-:,;#%.\sa-zA-Z0-9!]|\w-\w|'[\s\w]+'|"[\s\w]+"|\([\d,\s]+\))*$/).test(this.css)) 274 throw "Parse Error: " + this.css; 275 if (!(/^\s*([-\w]+\s*:[^:;]*(;\s*|$))*$/).test(this.css)) 276 throw "Parse Error: " + this.css; 277 278 parts = this.css.split(/;/g); 279 for( i in parts){ 280 if( parts[i].replace(/\s/g,'') != ""){ 281 property = parts[i].split(/:/g)[0].replace(/\s/g,''); 282 values = parts[i].split(/:/g)[1].split(/\s/g); 283 value = "" 284 for( j in values){ 285 if( values[j].replace(/\s/g,'')) 286 if((/^(#[0-9a-f]+|rgb\(\d+%?,\d*%?,?\d*%?\)?|\-?\d{0,2}\.?\d{0,2}(cm|em|ex|in|mm|pc|pt|px|%|,|\))?)$/).test(values[j].replace(/\s/g,'')) || 287 this.keywordWhitelist[values[j].replace(/\s/g,'')]) 288 value += " " + values[j].replace(/\s/g,'') 289 else 290 security = 1; 291 } 292 if (this.propertyWhitelist[property] && value){ 293 result += property + ':' + value + ';'; 294 } 295 else{ 296 security = 1; 297 } 298 } 333 299 } 300 334 301 return [result, security]; 335 },336 337 getProperty: function(){338 var property = this.css.match(this.propertyPattern);339 if(property){340 this.css = this.css.substring(property[0].length);341 return property[0].substring(0, property[0].length - 1).replace(/\s+/g,"");342 302 } 343 throw "Parse Error: " + this.css; 344 }, 345 346 getValues: function(){ 347 var values = this.css.match(this.valuePattern); 348 var valuesTable = []; 349 var tmp; 350 if(values) { 351 this.css = this.css.substring(values[0].length); 352 while(values[0] != ""){ 353 tmp = values[0].match(this.valueElement); 354 values[0] = values[0].substring(tmp[0].length); 355 valuesTable.push(tmp[0].replace(/\s+/g,"")); 356 } 357 return valuesTable; 358 359 } 360 throw "Parse Error: " + this.css; 361 } 303 362 304 }, 363 305 /**Cleans text from not proper css properties and values. … … 365 307 * @param (dictionary) params Parser parameters. If not set defaults are used. Take a look at the beginning of the type. 366 308 * params.propertyWhitelist - accepted list of properties. 367 * params. valueBlacklist - list of forbidden values.309 * params.keywordWhitelistt - list of allowed css keywords. 368 310 * @returns (tuple(string, security)) First element of the tuple is parsed text. Second one indicates which actions was done during parsing: 369 311 * 0 - removing removing not necessary whitespace or empty values. … … 372 314 function(css, params){ 373 315 this.css = css; 374 375 // Regular Expressions for parsing properties and values376 this.propertyPattern = propertyPattern;377 378 this.valueElement = valueElement;379 380 this.valuePattern = valuePattern;381 382 //Properties which can appear in a CSS383 316 this.propertyWhitelist = params && params.propertyWhitelist ? params.propertyWhitelist : propertyWhitelist; 384 //Values which cannot appear in a CSS 385 this.valueBlacklist = params && params.valueBlacklist ? params.valueBlacklist : valueBlacklist; 317 this.keywordWhitelist = params && params.keywordWhitelist ? params.keywordWhitelist : keywordWhitelist; 386 318 }); 387 319 388 320 389 var defaultTagWhitelist = makeMap( "a,abbr,acronym,address,area," + 390 "b,bdo,big,blockquote,br," + 391 "caption,center,cite,code,col,colgroup," + 392 "dd,del,dir,div,dfn,dl,dt," + 393 "em," + 394 "fieldset,font," + 395 "h1,h2,h3,h4,h5,h6,hr," + 396 "i,img,ins," + 397 "kbd," + 398 "legend,li," + 399 "map,menu," + 400 "ol," + 401 "p,pre," + 402 "q," + 403 "s,samp,small,span,strike,strong,sub,sup," + 404 "table,tbody,td,tfoot,th,thead,tr,tt," + 405 "u,ul," + 406 "var"); 407 408 var defaultAttribWhitelist = makeMap("align,abbr,alt," + 409 "border,bgcolor," + 410 "class,cellpadding,color,char,charoff,cite,clear,colspan,compact," + 411 "dir,disabled,face," + 412 "href,height,headers,hreflang,hspace," + 413 "id,ismap," + 414 "lang," + 415 "name,noshade,nowrap," + 416 "rel,rev,rowspan,rules," + 417 "size,scope,shape,span,start,summary," + 418 "title,tabindex,type," + 419 "valign,value,vspace," + 420 "width"); 321 var defaultTagWhitelist = makeMap( Indico.Security.allowedTags ); 322 323 var defaultAttribWhitelist = makeMap( Indico.Security.allowedAttributes ); 324 325 var defaultAllowedProtocols = makeMap( Indico.Security.allowedProtocols ); 326 327 var urlProperties = makeMap( Indico.Security.urlProperties ) 421 328 422 329 /**Cleans text from scripts, styles and potentialy harmful html. 423 330 * @param (String) html Text to be parsed. 331 * @param sanitizationLevel Current indico sanitization level. If 0 or 3 text is not parsed at all. If 1 inline css script are deleted. If 2 text is parsed normally. 424 332 * @param (dictionary) params Parser parameters. For further description see 'params' in HTMLParser and inlineCSSParser types. 425 333 * params.tagWhitelist String containing tags to be accepted by parser in lowercase separated by coma(without whitespace). If not defined defualts is used. 426 334 * params.attribWhitelist String containing attributes to be accepted by parser in lowercase separated by coma(without whitespace). If not defined defualts is used. 335 * params.allowedProtocols String contains allowed protocols. 427 336 * params.strict If true while parsing style fails exception is thrown. False by default. 428 337 * @returns (tuple(string, security)) First element of the tuple is parsed text. Second one indicates which actions was done during parsing: … … 431 340 * 2 - removing scripts, objects, applets, embed etc. 432 341 **/ 433 function escapeHarmfulHTML( html, params ) { 434 435 var self = this; 436 var strict = params && params.strict || false; 437 438 //Result string 439 var results = ""; 440 441 //Tags which can occur in the string. Other tags are omitted. 442 var tagWhitelist = params && params.tagWhitelist ? params.tagWhitelist : defaultTagWhitelist; 443 444 //Attributes allowed. 445 var attribWhitelist = params && params.attribWhitelist ? params.attribWhitelist : defaultAttribWhitelist; 446 447 var security = 0; 448 449 parser = new HTMLParser(html, { 450 start: function( tag, attrs, unary ) { 451 if( tagWhitelist[tag] ) { 452 results += "<" + tag; 453 454 for ( var i = 0; i < attrs.length; i++ ) 455 if(attribWhitelist[ attrs[i].name ] || unary && attrs[i].name == '/') { 456 if(attrs[i].name == "style") { 342 function escapeHarmfulHTML( html, sanitizationLevel, params ) { 343 344 sanitizationLevel = sanitizationLevel == undefined ? Indico.Security.sanitizationLevel : sanitizationLevel; 345 346 if( sanitizationLevel == 1 || sanitizationLevel == 2 ) 347 { 348 var self = this; 349 var strict = params && params.strict || false; 350 351 //Result string 352 var results = ""; 353 354 //Tags which can occur in the string. Other tags are omitted. 355 var tagWhitelist = params && params.tagWhitelist ? params.tagWhitelist : defaultTagWhitelist; 356 357 //Attributes allowed. 358 var attribWhitelist = params && params.attribWhitelist ? params.attribWhitelist : defaultAttribWhitelist; 359 360 //Protocols allowed 361 var allowedProtocols = params && params.allowedProtocols ? params.allowedProtocols : defaultAllowedProtocols; 362 363 var security = 0; 364 365 parser = new HTMLParser(html, { 366 start: function( tag, attrs, unary ) { 367 if( tagWhitelist[tag] ) { 368 results += "<" + tag; 369 370 for ( var i = 0; i < attrs.length; i++ ) 371 if(attrs[i].name == "style" && sanitizationLevel == 2) { 457 372 try{ 458 373 var cssParser = new inlineCSSParser(attrs[i].escaped, params); … … 461 376 catch(error){ 462 377 if(typeof error == "string" && error.indexOf("Parse Error") != -1 && !strict) 463 var tuple = ["", -1];378 var tuple = ["",1]; 464 379 else 465 380 throw error; 466 381 } 467 attrs[i].escaped = tuple[0]; 382 if(tuple[0] != '') 383 results += " " + attrs[i].name + '="' + tuple[0] + '"'; 468 384 security = max(security, tuple[1]); 469 385 } 470 if(attrs[i].escaped) 471 results += " " + attrs[i].name + '="' + attrs[i].escaped + '"'; 472 } 473 else 474 security = max(security, 1); 475 476 results += (unary ? "/" : "") + ">"; 386 else if(attribWhitelist[ attrs[i].name ] || unary && attrs[i].name == '/') { 387 if(urlProperties[attrs[i].name]){ 388 attrs[i].escaped = attrs[i].escaped.replace(/[`\000-\040\177-\240\s]+/g, ''); 389 attrs[i].escaped = attrs[i].escaped.replace(/\ufffd/g, "") 390 if (/^[a-z0-9][-+.a-z0-9]*:/.test(attrs[i].escaped) && !allowedProtocols[attrs[i].escaped.split(':')[0]]) { 391 security = 1; 392 continue; 393 } 394 } 395 if( attrs[i].escaped != '') 396 results += " " + attrs[i].name + '="' + attrs[i].escaped + '"'; 397 } 398 else 399 security = max(security, 1); 400 401 results += (unary ? "/" : "") + ">"; 402 } 403 else 404 security = max(1, security); 405 }, 406 end: function( tag ) { 407 if(tagWhitelist[tag]) 408 results += "</" + tag + ">"; 409 else 410 security = max(1, security); 411 }, 412 chars: function( text ) { 413 results += text; 414 }, 415 comment: function( text ) { 416 // results += "<!--" + text + "-->"; 417 }, 418 escape: function(text, tag) { 419 security = max(2, security); 477 420 } 478 else 479 security = max(1, security); 480 }, 481 end: function( tag ) { 482 if(tagWhitelist[tag]) 483 results += "</" + tag + ">"; 484 else 485 security = max(1, security); 486 }, 487 chars: function( text ) { 488 results += text; 489 }, 490 comment: function( text ) { 491 // results += "<!--" + text + "-->"; 492 }, 493 escape: function(text, tag) { 494 security = max(2, security); 421 }, params); 422 423 parser.parse(); 424 425 return [results, security]; 495 426 } 496 }, params); 497 498 parser.parse(); 499 500 return [results, security]; 427 else 428 return [html,0]; 501 429 }; 502 430 -
indico/htdocs/js/indico/Legacy/Dialogs.js
r203b37 ra30779 663 663 } 664 664 665 var popup = new ConfirmPopup( "Warning!", Html.div({style: {width:pixels(300), textAlign:'justify'}},"Your minutes contains some potentially harmful " + security + ", which cannot be stored in the database. Clean the text manually or use the automatic Indico cleaner."), cleaningFunction);665 var popup = new ConfirmPopup($T("Warning!"), Html.div({style: {width:pixels(300), textAlign:'justify'}},$T("Your minutes contains some potentially harmful " + security + ", which cannot be stored in the database. Clean the text manually or use the automatic Indico cleaner.")), cleaningFunction); 666 666 popup.draw = function(){ 667 667 var self = this; … … 691 691 if(typeof error == "string" && error.indexOf("Parse Error") != -1){ 692 692 closeMinutes = false; 693 var popup = new WarningPopup( "Warning!", "Format of your minutes is invalid. Please check the syntax.");693 var popup = new WarningPopup($T("Warning!"), $T("Format of your minutes is invalid. Please check the syntax.")); 694 694 popup.open(); 695 695 } -
indico/htdocs/js/indico/Legacy/Loader.js
r1113bb ra30779 2 2 include(ScriptRoot + "indico/Legacy/Dialogs.js"); 3 3 include(ScriptRoot + "indico/Legacy/Util.js"); 4 include(ScriptRoot + "indico/Legacy/htmlparser.js");5
Note: See TracChangeset
for help on using the changeset viewer.
