diff options
Diffstat (limited to 'test/ngSanitize/sanitizeSpec.js')
| -rw-r--r-- | test/ngSanitize/sanitizeSpec.js | 286 | 
1 files changed, 286 insertions, 0 deletions
| diff --git a/test/ngSanitize/sanitizeSpec.js b/test/ngSanitize/sanitizeSpec.js new file mode 100644 index 00000000..b4fd8a2a --- /dev/null +++ b/test/ngSanitize/sanitizeSpec.js @@ -0,0 +1,286 @@ +'use strict'; + +describe('HTML', function() { + +  var expectHTML; + +  beforeEach(module('ngSanitize')); + +  beforeEach(inject(function($sanitize) { +    expectHTML = function(html){ +      return expect($sanitize(html)); +    }; +  })); + +  describe('htmlParser', function() { +    if (angular.isUndefined(window.htmlParser)) return; + +    var handler, start, text; +    beforeEach(function() { +      handler = { +          start: function(tag, attrs, unary){ +            start = { +                tag: tag, +                attrs: attrs, +                unary: unary +            }; +            // Since different browsers handle newlines differenttly we trim +            // so that it is easier to write tests. +            angular.forEach(attrs, function(value, key) { +              attrs[key] = value.replace(/^\s*/, '').replace(/\s*$/, '') +            }); +          }, +          chars: function(text_){ +            text = text_; +          }, +          end:function(tag) { +            expect(tag).toEqual(start.tag); +          } +      }; +    }); + +    it('should parse basic format', function() { +      htmlParser('<tag attr="value">text</tag>', handler); +      expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); +      expect(text).toEqual('text'); +    }); + +    it('should parse newlines in tags', function() { +      htmlParser('<\ntag\n attr="value"\n>text<\n/\ntag\n>', handler); +      expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); +      expect(text).toEqual('text'); +    }); + +    it('should parse newlines in attributes', function() { +      htmlParser('<tag attr="\nvalue\n">text</tag>', handler); +      expect(start).toEqual({tag:'tag', attrs:{attr:'value'}, unary:false}); +      expect(text).toEqual('text'); +    }); + +    it('should parse namespace', function() { +      htmlParser('<ns:t-a-g ns:a-t-t-r="\nvalue\n">text</ns:t-a-g>', handler); +      expect(start).toEqual({tag:'ns:t-a-g', attrs:{'ns:a-t-t-r':'value'}, unary:false}); +      expect(text).toEqual('text'); +    }); + +    it('should parse empty value attribute of node', function() { +      htmlParser('<OPTION selected value="">abc</OPTION>', handler); +      expect(start).toEqual({tag:'option', attrs:{selected:'', value:''}, unary:false}); +      expect(text).toEqual('abc'); +    }); +  }); + +  // THESE TESTS ARE EXECUTED WITH COMPILED ANGULAR +  it('should echo html', function() { +    expectHTML('hello<b class="1\'23" align=\'""\'>world</b>.'). +       toEqual('hello<b class="1\'23" align="""">world</b>.'); +  }); + +  it('should remove script', function() { +    expectHTML('a<SCRIPT>evil< / scrIpt >c.').toEqual('ac.'); +  }); + +  it('should remove nested script', function() { +    expectHTML('a< SCRIPT >A< SCRIPT >evil< / scrIpt >B< / scrIpt >c.').toEqual('ac.'); +  }); + +  it('should remove attrs', function() { +    expectHTML('a<div style="abc">b</div>c').toEqual('a<div>b</div>c'); +  }); + +  it('should remove style', function() { +    expectHTML('a<STyle>evil</stYle>c.').toEqual('ac.'); +  }); + +  it('should remove script and style', function() { +    expectHTML('a<STyle>evil<script></script></stYle>c.').toEqual('ac.'); +  }); + +  it('should remove double nested script', function() { +    expectHTML('a<SCRIPT>ev<script>evil</sCript>il</scrIpt>c.').toEqual('ac.'); +  }); + +  it('should remove unknown  names', function() { +    expectHTML('a<xxx><B>b</B></xxx>c').toEqual('a<b>b</b>c'); +  }); + +  it('should remove unsafe value', function() { +    expectHTML('<a href="javascript:alert()">').toEqual('<a></a>'); +  }); + +  it('should handle self closed elements', function() { +    expectHTML('a<hr/>c').toEqual('a<hr/>c'); +  }); + +  it('should handle namespace', function() { +    expectHTML('a<my:hr/><my:div>b</my:div>c').toEqual('abc'); +  }); + +  it('should handle entities', function() { +    var everything = '<div rel="!@#$%^&*()_+-={}[]:";\'<>?,./`~ ħ">' + +    '!@#$%^&*()_+-={}[]:";\'<>?,./`~ ħ</div>'; +    expectHTML(everything).toEqual(everything); +  }); + +  it('should handle improper html', function() { +    expectHTML('< div rel="</div>" alt=abc dir=\'"\' >text< /div>'). +      toEqual('<div rel="</div>" alt="abc" dir=""">text</div>'); +  }); + +  it('should handle improper html2', function() { +    expectHTML('< div rel="</div>" / >'). +      toEqual('<div rel="</div>"/>'); +  }); + +  it('should ignore back slash as escape', function() { +    expectHTML('<img alt="xxx\\" title="><script>....">'). +      toEqual('<img alt="xxx\\" title="><script>...."/>'); +  }); + +  it('should ignore object attributes', function() { +    expectHTML('<a constructor="hola">:)</a>'). +      toEqual('<a>:)</a>'); +    expectHTML('<constructor constructor="hola">:)</constructor>'). +      toEqual(''); +  }); + +  describe('htmlSanitizerWriter', function() { +    if (angular.isUndefined(window.htmlSanitizeWriter)) return; + +    var writer, html; +    beforeEach(function() { +      html = ''; +      writer = htmlSanitizeWriter({push:function(text){html+=text;}}); +    }); + +    it('should write basic HTML', function() { +      writer.chars('before'); +      writer.start('div', {rel:'123'}, false); +      writer.chars('in'); +      writer.end('div'); +      writer.chars('after'); + +      expect(html).toEqual('before<div rel="123">in</div>after'); +    }); + +    it('should escape text nodes', function() { +      writer.chars('a<div>&</div>c'); +      expect(html).toEqual('a<div>&</div>c'); +    }); + +    it('should escape IE script', function() { +      writer.chars('&<>{}'); +      expect(html).toEqual('&<>{}'); +    }); + +    it('should escape attributes', function() { +      writer.start('div', {rel:'!@#$%^&*()_+-={}[]:";\'<>?,./`~ \n\0\r\u0127'}); +      expect(html).toEqual('<div rel="!@#$%^&*()_+-={}[]:";\'<>?,./`~ 
�
ħ">'); +    }); + +    it('should ignore missformed elements', function() { +      writer.start('d>i&v', {}); +      expect(html).toEqual(''); +    }); + +    it('should ignore unknown attributes', function() { +      writer.start('div', {unknown:""}); +      expect(html).toEqual('<div>'); +    }); + +    describe('explicitly dissallow', function() { +      it('should not allow attributes', function() { +        writer.start('div', {id:'a', name:'a', style:'a'}); +        expect(html).toEqual('<div>'); +      }); + +      it('should not allow tags', function() { +        function tag(name) { +          writer.start(name, {}); +          writer.end(name); +        } +        tag('frameset'); +        tag('frame'); +        tag('form'); +        tag('param'); +        tag('object'); +        tag('embed'); +        tag('textarea'); +        tag('input'); +        tag('button'); +        tag('option'); +        tag('select'); +        tag('script'); +        tag('style'); +        tag('link'); +        tag('base'); +        tag('basefont'); +        expect(html).toEqual(''); +      }); +    }); + +    describe('isUri', function() { + +      function isUri(value) { +        return value.match(URI_REGEXP); +      } + +      it('should be URI', function() { +        expect(isUri('http://abc')).toBeTruthy(); +        expect(isUri('https://abc')).toBeTruthy(); +        expect(isUri('ftp://abc')).toBeTruthy(); +        expect(isUri('mailto:me@example.com')).toBeTruthy(); +        expect(isUri('#anchor')).toBeTruthy(); +      }); + +      it('should not be UIR', function() { +        expect(isUri('')).toBeFalsy(); +        expect(isUri('javascript:alert')).toBeFalsy(); +      }); +    }); + +    describe('javascript URL attribute', function() { +      beforeEach(function() { +        this.addMatchers({ +          toBeValidUrl: function() { +            return URI_REGEXP.exec(this.actual); +          } +        }); +      }); + +      it('should ignore javascript:', function() { +        expect('JavaScript:abc').not.toBeValidUrl(); +        expect(' \n Java\n Script:abc').not.toBeValidUrl(); +        expect('http://JavaScript/my.js').toBeValidUrl(); +      }); + +      it('should ignore dec encoded javascript:', function() { +        expect('javascript:').not.toBeValidUrl(); +        expect('javascript:').not.toBeValidUrl(); +        expect('j avascript:').not.toBeValidUrl(); +      }); + +      it('should ignore decimal with leading 0 encodede javascript:', function() { +        expect('javascript:').not.toBeValidUrl(); +        expect('j avascript:').not.toBeValidUrl(); +        expect('j avascript:').not.toBeValidUrl(); +      }); + +      it('should ignore hex encoded javascript:', function() { +        expect('javascript:').not.toBeValidUrl(); +        expect('javascript:').not.toBeValidUrl(); +        expect('j avascript:').not.toBeValidUrl(); +      }); + +      it('should ignore hex encoded whitespace javascript:', function() { +        expect('jav	ascript:alert("A");').not.toBeValidUrl(); +        expect('jav
ascript:alert("B");').not.toBeValidUrl(); +        expect('jav
 ascript:alert("C");').not.toBeValidUrl(); +        expect('jav\u0000ascript:alert("D");').not.toBeValidUrl(); +        expect('java\u0000\u0000script:alert("D");').not.toBeValidUrl(); +        expect('  java\u0000\u0000script:alert("D");').not.toBeValidUrl(); +      }); +    }); + +  }); +}); | 
