1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.shiro.util;
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 public class AntPathMatcher implements PatternMatcher {
61
62
63
64
65
66
67 public static final String DEFAULT_PATH_SEPARATOR = "/";
68
69 private String pathSeparator = DEFAULT_PATH_SEPARATOR;
70
71
72
73
74
75
76 public void setPathSeparator(String pathSeparator) {
77 this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
78 }
79
80
81 public boolean isPattern(String path) {
82 return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
83 }
84
85 public boolean matches(String pattern, String source) {
86 return match(pattern, source);
87 }
88
89 public boolean match(String pattern, String path) {
90 return doMatch(pattern, path, true);
91 }
92
93 public boolean matchStart(String pattern, String path) {
94 return doMatch(pattern, path, false);
95 }
96
97
98
99
100
101
102
103
104
105
106
107
108 protected boolean doMatch(String pattern, String path, boolean fullMatch) {
109 if (path.startsWith(this.pathSeparator) != pattern.startsWith(this.pathSeparator)) {
110 return false;
111 }
112
113 String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
114 String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
115
116 int pattIdxStart = 0;
117 int pattIdxEnd = pattDirs.length - 1;
118 int pathIdxStart = 0;
119 int pathIdxEnd = pathDirs.length - 1;
120
121
122 while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
123 String patDir = pattDirs[pattIdxStart];
124 if ("**".equals(patDir)) {
125 break;
126 }
127 if (!matchStrings(patDir, pathDirs[pathIdxStart])) {
128 return false;
129 }
130 pattIdxStart++;
131 pathIdxStart++;
132 }
133
134 if (pathIdxStart > pathIdxEnd) {
135
136 if (pattIdxStart > pattIdxEnd) {
137 return (pattern.endsWith(this.pathSeparator) ?
138 path.endsWith(this.pathSeparator) : !path.endsWith(this.pathSeparator));
139 }
140 if (!fullMatch) {
141 return true;
142 }
143 if (pattIdxStart == pattIdxEnd && pattDirs[pattIdxStart].equals("*") &&
144 path.endsWith(this.pathSeparator)) {
145 return true;
146 }
147 for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
148 if (!pattDirs[i].equals("**")) {
149 return false;
150 }
151 }
152 return true;
153 } else if (pattIdxStart > pattIdxEnd) {
154
155 return false;
156 } else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
157
158 return true;
159 }
160
161
162 while (pattIdxStart <= pattIdxEnd && pathIdxStart <= pathIdxEnd) {
163 String patDir = pattDirs[pattIdxEnd];
164 if (patDir.equals("**")) {
165 break;
166 }
167 if (!matchStrings(patDir, pathDirs[pathIdxEnd])) {
168 return false;
169 }
170 pattIdxEnd--;
171 pathIdxEnd--;
172 }
173 if (pathIdxStart > pathIdxEnd) {
174
175 for (int i = pattIdxStart; i <= pattIdxEnd; i++) {
176 if (!pattDirs[i].equals("**")) {
177 return false;
178 }
179 }
180 return true;
181 }
182
183 while (pattIdxStart != pattIdxEnd && pathIdxStart <= pathIdxEnd) {
184 int patIdxTmp = -1;
185 for (int i = pattIdxStart + 1; i <= pattIdxEnd; i++) {
186 if (pattDirs[i].equals("**")) {
187 patIdxTmp = i;
188 break;
189 }
190 }
191 if (patIdxTmp == pattIdxStart + 1) {
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245 private boolean matchStrings(String pattern, String str) {
246 char[] patArr = pattern.toCharArray();
247 char[] strArr = str.toCharArray();
248 int patIdxStart = 0;
249 int patIdxEnd = patArr.length - 1;
250 int strIdxStart = 0;
251 int strIdxEnd = strArr.length - 1;
252 char ch;
253
254 boolean containsStar = false;
255 for (char aPatArr : patArr) {
256 if (aPatArr == '*') {
257 containsStar = true;
258 break;
259 }
260 }
261
262 if (!containsStar) {
263
264 if (patIdxEnd != strIdxEnd) {
265 return false;
266 }
267 for (int i = 0; i <= patIdxEnd; i++) {
268 ch = patArr[i];
269 if (ch != '?') {
270 if (ch != strArr[i]) {
271 return false;
272 }
273 }
274 }
275 return true;
276 }
277
278
279 if (patIdxEnd == 0) {
280 return true;
281 }
282
283
284 while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
285 if (ch != '?') {
286 if (ch != strArr[strIdxStart]) {
287 return false;
288 }
289 }
290 patIdxStart++;
291 strIdxStart++;
292 }
293 if (strIdxStart > strIdxEnd) {
294
295
296 for (int i = patIdxStart; i <= patIdxEnd; i++) {
297 if (patArr[i] != '*') {
298 return false;
299 }
300 }
301 return true;
302 }
303
304
305 while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
306 if (ch != '?') {
307 if (ch != strArr[strIdxEnd]) {
308 return false;
309 }
310 }
311 patIdxEnd--;
312 strIdxEnd--;
313 }
314 if (strIdxStart > strIdxEnd) {
315
316
317 for (int i = patIdxStart; i <= patIdxEnd; i++) {
318 if (patArr[i] != '*') {
319 return false;
320 }
321 }
322 return true;
323 }
324
325
326
327 while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
328 int patIdxTmp = -1;
329 for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
330 if (patArr[i] == '*') {
331 patIdxTmp = i;
332 break;
333 }
334 }
335 if (patIdxTmp == patIdxStart + 1) {
336
337 patIdxStart++;
338 continue;
339 }
340
341
342 int patLength = (patIdxTmp - patIdxStart - 1);
343 int strLength = (strIdxEnd - strIdxStart + 1);
344 int foundIdx = -1;
345 strLoop:
346 for (int i = 0; i <= strLength - patLength; i++) {
347 for (int j = 0; j < patLength; j++) {
348 ch = patArr[patIdxStart + j + 1];
349 if (ch != '?') {
350 if (ch != strArr[strIdxStart + i + j]) {
351 continue strLoop;
352 }
353 }
354 }
355
356 foundIdx = strIdxStart + i;
357 break;
358 }
359
360 if (foundIdx == -1) {
361 return false;
362 }
363
364 patIdxStart = patIdxTmp;
365 strIdxStart = foundIdx + patLength;
366 }
367
368
369
370 for (int i = patIdxStart; i <= patIdxEnd; i++) {
371 if (patArr[i] != '*') {
372 return false;
373 }
374 }
375
376 return true;
377 }
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395 public String extractPathWithinPattern(String pattern, String path) {
396 String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
397 String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
398
399 StringBuilder buffer = new StringBuilder();
400
401
402 int puts = 0;
403 for (int i = 0; i < patternParts.length; i++) {
404 String patternPart = patternParts[i];
405 if ((patternPart.indexOf('*') > -1 || patternPart.indexOf('?') > -1) && pathParts.length >= i + 1) {
406 if (puts > 0 || (i == 0 && !pattern.startsWith(this.pathSeparator))) {
407 buffer.append(this.pathSeparator);
408 }
409 buffer.append(pathParts[i]);
410 puts++;
411 }
412 }
413
414
415 for (int i = patternParts.length; i < pathParts.length; i++) {
416 if (puts > 0 || i > 0) {
417 buffer.append(this.pathSeparator);
418 }
419 buffer.append(pathParts[i]);
420 }
421
422 return buffer.toString();
423 }
424
425 }