-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathHTML.qll
More file actions
203 lines (172 loc) · 4.84 KB
/
HTML.qll
File metadata and controls
203 lines (172 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/** Provides classes for working with HTML documents. */
overlay[local]
module;
import go
module HTML {
/**
* An HTML element.
*
* Example:
*
* ```
* <a href="semmle.com">Semmle</a>
* ```
*/
class Element extends Locatable, @xmlelement {
Element() { exists(HtmlFile f | xmlElements(this, _, _, _, f)) }
/**
* Gets the name of this HTML element.
*
* For example, the name of `<br>` is `br`.
*/
string getName() { xmlElements(this, result, _, _, _) }
/**
* Gets the parent element of this element, if any.
*/
Element getParent() { xmlElements(this, _, result, _, _) }
/**
* Holds if this is a toplevel element, that is, if it does not have a parent element.
*/
predicate isTopLevel() { not exists(this.getParent()) }
/**
* Gets the root HTML document element in which this element is contained.
*/
DocumentElement getDocument() { result = this.getRoot() }
/**
* Gets the root element in which this element is contained.
*/
Element getRoot() {
if this.isTopLevel() then result = this else result = this.getParent().getRoot()
}
/**
* Gets the `i`th child element (0-based) of this element.
*/
Element getChild(int i) { xmlElements(result, _, this, i, _) }
/**
* Gets a child element of this element.
*/
Element getChild() { result = this.getChild(_) }
/**
* Gets the `i`th attribute (0-based) of this element.
*/
Attribute getAttribute(int i) { xmlAttrs(result, this, _, _, i, _) }
/**
* Gets an attribute of this element.
*/
Attribute getAnAttribute() { result = this.getAttribute(_) }
/**
* Gets an attribute of this element that has the given name.
*/
Attribute getAttributeByName(string name) {
result = this.getAnAttribute() and
result.getName() = name
}
/**
* Gets the text node associated with this element.
*/
TextNode getTextNode() { result.getParent() = this }
override string toString() { result = "<" + this.getName() + ">...</>" }
}
/**
* An attribute of an HTML element.
*
* Examples:
*
* ```
* <a
* href ="semmle.com" <!-- an attribute -->
* target=_blank <!-- also an attribute -->
* >Semmle</a>
* ```
*/
class Attribute extends Locatable, @xmlattribute {
Attribute() { xmlAttrs(this, _, _, _, _, any(HtmlFile f)) }
/**
* Gets the element to which this attribute belongs.
*/
Element getElement() { xmlAttrs(this, result, _, _, _, _) }
/**
* Gets the root element in which the element to which this attribute
* belongs is contained.
*/
Element getRoot() { result = this.getElement().getRoot() }
/**
* Gets the name of this attribute.
*/
string getName() { xmlAttrs(this, _, result, _, _, _) }
/**
* Gets the value of this attribute.
*
* For attributes without an explicitly specified value, the
* result is the empty string.
*/
string getValue() { xmlAttrs(this, _, _, result, _, _) }
override string toString() { result = this.getName() + "=" + this.getValue() }
}
/**
* An HTML `<html>` element.
*
* Example:
*
* ```
* <html>
* <body>
* This is a test.
* </body>
* </html>
* ```
*/
class DocumentElement extends Element {
DocumentElement() { this.getName() = "html" }
}
/**
* An HTML text node.
*
* Example:
*
* ```
* <div>
* This text is represented as a text node.
* </div>
* ```
*/
class TextNode extends Locatable, @xmlcharacters {
TextNode() { exists(HtmlFile f | xmlChars(this, _, _, _, _, f)) }
override string toString() { result = this.getText() }
/**
* Gets the content of this text node.
*
* Note that entity expansion has been performed already.
*/
string getText() { xmlChars(this, result, _, _, _, _) }
/**
* Gets the parent this text.
*/
Element getParent() { xmlChars(this, _, result, _, _, _) }
/**
* Gets the child index number of this text node.
*/
int getIndex() { xmlChars(this, _, _, result, _, _) }
/**
* Holds if this text node is inside a `CDATA` tag.
*/
predicate isCData() { xmlChars(this, _, _, _, 1, _) }
}
/**
* An HTML comment.
*
* Example:
*
* ```
* <!-- this is a comment -->
* ```
*/
class CommentNode extends Locatable, @xmlcomment {
CommentNode() { exists(HtmlFile f | xmlComments(this, _, _, f)) }
/** Gets the element in which this comment occurs. */
Element getParent() { xmlComments(this, _, result, _) }
/** Gets the text of this comment, not including delimiters. */
string getText() { result = this.toString().regexpCapture("(?s)<!--(.*)-->", 1) }
override string toString() { xmlComments(this, result, _, _) }
}
}