1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package com.xpn.xwiki.internal.store.hibernate.query; |
21 |
|
|
22 |
|
import java.util.HashMap; |
23 |
|
import java.util.HashSet; |
24 |
|
import java.util.List; |
25 |
|
import java.util.Map; |
26 |
|
import java.util.Set; |
27 |
|
import java.util.regex.Pattern; |
28 |
|
|
29 |
|
import org.apache.commons.lang3.StringUtils; |
30 |
|
|
31 |
|
import net.sf.jsqlparser.JSQLParserException; |
32 |
|
import net.sf.jsqlparser.expression.Expression; |
33 |
|
import net.sf.jsqlparser.expression.Function; |
34 |
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil; |
35 |
|
import net.sf.jsqlparser.schema.Column; |
36 |
|
import net.sf.jsqlparser.schema.Table; |
37 |
|
import net.sf.jsqlparser.statement.Statement; |
38 |
|
import net.sf.jsqlparser.statement.select.FromItem; |
39 |
|
import net.sf.jsqlparser.statement.select.Join; |
40 |
|
import net.sf.jsqlparser.statement.select.PlainSelect; |
41 |
|
import net.sf.jsqlparser.statement.select.Select; |
42 |
|
import net.sf.jsqlparser.statement.select.SelectBody; |
43 |
|
import net.sf.jsqlparser.statement.select.SelectExpressionItem; |
44 |
|
import net.sf.jsqlparser.statement.select.SelectItem; |
45 |
|
|
46 |
|
|
47 |
|
|
48 |
|
|
49 |
|
@version |
50 |
|
@since |
51 |
|
|
|
|
| 93.5% |
Uncovered Elements: 7 (108) |
Complexity: 26 |
Complexity Density: 0.37 |
|
52 |
|
public final class HqlQueryUtils |
53 |
|
{ |
54 |
|
private static final String DOCUMENT_FIELD_FULLNAME = "fullName"; |
55 |
|
|
56 |
|
private static final String DOCUMENT_FIELD_NAME = "name"; |
57 |
|
|
58 |
|
private static final String DOCUMENT_FIELD_SPACE = "space"; |
59 |
|
|
60 |
|
private static final String DOCUMENT_FIELD_LANGUAGE = "language"; |
61 |
|
|
62 |
|
private static final String DOCUMENT_FIELD_DEFAULTLANGUAGE = "defaultLanguage"; |
63 |
|
|
64 |
|
private static final String DOCUMENT_FIELD_TRANSLATION = "translation"; |
65 |
|
|
66 |
|
private static final String DOCUMENT_FIELD_HIDDEN = "hidden"; |
67 |
|
|
68 |
|
private static final String SPACE_FIELD_REFERENCE = "reference"; |
69 |
|
|
70 |
|
private static final String SPACE_FIELD_NAME = DOCUMENT_FIELD_NAME; |
71 |
|
|
72 |
|
private static final String SPACE_FIELD_PARENT = "parent"; |
73 |
|
|
74 |
|
private static final String SPACE_FIELD_HIDDEN = DOCUMENT_FIELD_HIDDEN; |
75 |
|
|
76 |
|
private static final String FROM_REPLACEMENT = "$1"; |
77 |
|
|
78 |
|
private static final Pattern FROM_DOC = Pattern.compile("com\\.xpn\\.xwiki\\.doc\\.([^ ]+)"); |
79 |
|
|
80 |
|
private static final Pattern FROM_OBJECT = Pattern.compile("com\\.xpn\\.xwiki\\.objects\\.([^ ]+)"); |
81 |
|
|
82 |
|
private static final Pattern FROM_RCS = Pattern.compile("com\\.xpn\\.xwiki\\.doc\\.rcs\\.([^ ]+)"); |
83 |
|
|
84 |
|
private static final Pattern FROM_VERSION = Pattern.compile("com\\.xpn\\.xwiki\\.store\\.migration\\.([^ ]+)"); |
85 |
|
|
86 |
|
private static final Map<String, Set<String>> ALLOWED_FIELDS; |
87 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (16) |
Complexity: 1 |
Complexity Density: 0.06 |
|
88 |
5 |
static {... |
89 |
5 |
ALLOWED_FIELDS = new HashMap<>(); |
90 |
|
|
91 |
5 |
Set<String> allowedDocFields = new HashSet<>(); |
92 |
5 |
ALLOWED_FIELDS.put("XWikiDocument", allowedDocFields); |
93 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_FULLNAME); |
94 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_NAME); |
95 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_SPACE); |
96 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_LANGUAGE); |
97 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_DEFAULTLANGUAGE); |
98 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_TRANSLATION); |
99 |
5 |
allowedDocFields.add(DOCUMENT_FIELD_HIDDEN); |
100 |
|
|
101 |
5 |
Set<String> allowedSpaceFields = new HashSet<>(); |
102 |
5 |
ALLOWED_FIELDS.put("XWikiSpace", allowedSpaceFields); |
103 |
5 |
allowedSpaceFields.add(SPACE_FIELD_REFERENCE); |
104 |
5 |
allowedSpaceFields.add(SPACE_FIELD_NAME); |
105 |
5 |
allowedSpaceFields.add(SPACE_FIELD_PARENT); |
106 |
5 |
allowedSpaceFields.add(SPACE_FIELD_HIDDEN); |
107 |
|
} |
108 |
|
|
|
|
| - |
Uncovered Elements: 0 (0) |
Complexity: 1 |
Complexity Density: - |
|
109 |
0 |
private HqlQueryUtils()... |
110 |
|
{ |
111 |
|
|
112 |
|
} |
113 |
|
|
114 |
|
|
115 |
|
@param |
116 |
|
@return |
117 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
118 |
27 |
public static boolean isShortFormStatement(String statement)... |
119 |
|
{ |
120 |
27 |
return StringUtils.startsWithAny(statement.trim().toLowerCase(), ",", "from", "where", "order"); |
121 |
|
} |
122 |
|
|
123 |
|
|
124 |
|
@param |
125 |
|
@return |
126 |
|
|
|
|
| 92.3% |
Uncovered Elements: 2 (26) |
Complexity: 5 |
Complexity Density: 0.25 |
|
127 |
15 |
public static boolean isSafe(String statementString)... |
128 |
|
{ |
129 |
15 |
Statement statement; |
130 |
15 |
try { |
131 |
|
|
132 |
|
|
133 |
|
|
134 |
15 |
String cleanedStatement = statementString; |
135 |
15 |
cleanedStatement = FROM_DOC.matcher(cleanedStatement).replaceAll(FROM_REPLACEMENT); |
136 |
15 |
cleanedStatement = FROM_OBJECT.matcher(cleanedStatement).replaceAll(FROM_REPLACEMENT); |
137 |
15 |
cleanedStatement = FROM_RCS.matcher(cleanedStatement).replaceAll(FROM_REPLACEMENT); |
138 |
15 |
cleanedStatement = FROM_VERSION.matcher(cleanedStatement).replaceAll(FROM_REPLACEMENT); |
139 |
|
|
140 |
15 |
statement = CCJSqlParserUtil.parse(cleanedStatement); |
141 |
|
|
142 |
15 |
if (statement instanceof Select) { |
143 |
13 |
Select select = (Select) statement; |
144 |
|
|
145 |
13 |
SelectBody selectBody = select.getSelectBody(); |
146 |
|
|
147 |
13 |
if (selectBody instanceof PlainSelect) { |
148 |
13 |
PlainSelect plainSelect = (PlainSelect) selectBody; |
149 |
|
|
150 |
13 |
Map<String, String> tables = getTables(plainSelect); |
151 |
|
|
152 |
13 |
for (SelectItem selectItem : plainSelect.getSelectItems()) { |
153 |
16 |
if (!isSelectItemAllowed(selectItem, tables)) { |
154 |
6 |
return false; |
155 |
|
} |
156 |
|
} |
157 |
|
|
158 |
7 |
return true; |
159 |
|
} |
160 |
|
} |
161 |
|
} catch (JSQLParserException e) { |
162 |
|
|
163 |
0 |
e.printStackTrace(); |
164 |
|
} |
165 |
|
|
166 |
2 |
return false; |
167 |
|
} |
168 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (9) |
Complexity: 2 |
Complexity Density: 0.29 |
|
169 |
13 |
private static Map<String, String> getTables(PlainSelect plainSelect)... |
170 |
|
{ |
171 |
13 |
Map<String, String> tables = new HashMap<>(); |
172 |
|
|
173 |
|
|
174 |
13 |
addFromItem(plainSelect.getFromItem(), tables); |
175 |
|
|
176 |
|
|
177 |
13 |
List<Join> joins = plainSelect.getJoins(); |
178 |
13 |
if (joins != null) { |
179 |
5 |
for (Join join : joins) { |
180 |
7 |
addFromItem(join.getRightItem(), tables); |
181 |
|
} |
182 |
|
} |
183 |
|
|
184 |
13 |
return tables; |
185 |
|
} |
186 |
|
|
|
|
| 85.7% |
Uncovered Elements: 1 (7) |
Complexity: 3 |
Complexity Density: 1 |
|
187 |
20 |
private static void addFromItem(FromItem item, Map<String, String> tables)... |
188 |
|
{ |
189 |
20 |
if (item instanceof Table) { |
190 |
20 |
String tableName = ((Table) item).getName(); |
191 |
20 |
tables.put(item.getAlias() != null ? item.getAlias().getName() : tableName, tableName); |
192 |
|
} |
193 |
|
} |
194 |
|
|
195 |
|
|
196 |
|
@param@link |
197 |
|
@return@link |
198 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
199 |
16 |
private static boolean isSelectItemAllowed(SelectItem selectItem, Map<String, String> tables)... |
200 |
|
{ |
201 |
16 |
if (selectItem instanceof SelectExpressionItem) { |
202 |
14 |
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; |
203 |
|
|
204 |
14 |
return isSelectExpressionAllowed(selectExpressionItem.getExpression(), tables); |
205 |
|
} |
206 |
|
|
207 |
|
|
208 |
|
|
209 |
2 |
return false; |
210 |
|
} |
211 |
|
|
|
|
| 87% |
Uncovered Elements: 3 (23) |
Complexity: 6 |
Complexity Density: 0.46 |
|
212 |
16 |
private static boolean isSelectExpressionAllowed(Expression expression, Map<String, String> tables)... |
213 |
|
{ |
214 |
16 |
if (expression instanceof Column) { |
215 |
12 |
Column column = (Column) expression; |
216 |
|
|
217 |
12 |
if (isColumnAllowed(column, tables)) { |
218 |
9 |
return true; |
219 |
|
} |
220 |
4 |
} else if (expression instanceof Function) { |
221 |
4 |
Function function = (Function) expression; |
222 |
|
|
223 |
4 |
if (function.isAllColumns()) { |
224 |
|
|
225 |
|
|
226 |
2 |
return function.getName().equals("count") && tables.size() == 1 |
227 |
|
&& isTableAllowed(tables.values().iterator().next()); |
228 |
|
} else { |
229 |
|
|
230 |
2 |
for (Expression parameter : function.getParameters().getExpressions()) { |
231 |
2 |
if (!isSelectExpressionAllowed(parameter, tables)) { |
232 |
0 |
return false; |
233 |
|
} |
234 |
|
} |
235 |
|
|
236 |
2 |
return true; |
237 |
|
} |
238 |
|
} |
239 |
|
|
240 |
3 |
return false; |
241 |
|
} |
242 |
|
|
243 |
|
|
244 |
|
@param@link |
245 |
|
@return@link |
246 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
247 |
12 |
private static boolean isColumnAllowed(Column column, Map<String, String> tables)... |
248 |
|
{ |
249 |
12 |
Set<String> fields = ALLOWED_FIELDS.get(getTableName(column.getTable(), tables)); |
250 |
12 |
return fields != null && fields.contains(column.getColumnName()); |
251 |
|
} |
252 |
|
|
253 |
|
|
254 |
|
@param |
255 |
|
@return |
256 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
257 |
2 |
private static boolean isTableAllowed(String tableName)... |
258 |
|
{ |
259 |
2 |
return ALLOWED_FIELDS.containsKey(tableName); |
260 |
|
} |
261 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (6) |
Complexity: 3 |
Complexity Density: 0.75 |
|
262 |
12 |
private static String getTableName(Table table, Map<String, String> tables)... |
263 |
|
{ |
264 |
12 |
String tableName = tables.values().iterator().next(); |
265 |
|
|
266 |
12 |
if (table != null && StringUtils.isNotEmpty(table.getFullyQualifiedName())) { |
267 |
9 |
tableName = tables.get(table.getFullyQualifiedName()); |
268 |
|
} |
269 |
|
|
270 |
12 |
return tableName; |
271 |
|
} |
272 |
|
} |