source: azure_iot_hub/trunk/curl-7.57.0/lib/curl_fnmatch.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.1 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23#include "curl_setup.h"
24
25#include <curl/curl.h>
26
27#include "curl_fnmatch.h"
28#include "curl_memory.h"
29
30/* The last #include file should be: */
31#include "memdebug.h"
32
33#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
34#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
35
36#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
37
38#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
39#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
40#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
41#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
42#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
43#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
44#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
45#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
46#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
47#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
48
49typedef enum {
50 CURLFNM_LOOP_DEFAULT = 0,
51 CURLFNM_LOOP_BACKSLASH
52} loop_state;
53
54typedef enum {
55 CURLFNM_SCHS_DEFAULT = 0,
56 CURLFNM_SCHS_MAYRANGE,
57 CURLFNM_SCHS_MAYRANGE2,
58 CURLFNM_SCHS_RIGHTBR,
59 CURLFNM_SCHS_RIGHTBRLEFTBR
60} setcharset_state;
61
62typedef enum {
63 CURLFNM_PKW_INIT = 0,
64 CURLFNM_PKW_DDOT
65} parsekey_state;
66
67#define SETCHARSET_OK 1
68#define SETCHARSET_FAIL 0
69
70static int parsekeyword(unsigned char **pattern, unsigned char *charset)
71{
72 parsekey_state state = CURLFNM_PKW_INIT;
73#define KEYLEN 10
74 char keyword[KEYLEN] = { 0 };
75 int found = FALSE;
76 int i;
77 unsigned char *p = *pattern;
78 for(i = 0; !found; i++) {
79 char c = *p++;
80 if(i >= KEYLEN)
81 return SETCHARSET_FAIL;
82 switch(state) {
83 case CURLFNM_PKW_INIT:
84 if(ISALPHA(c) && ISLOWER(c))
85 keyword[i] = c;
86 else if(c == ':')
87 state = CURLFNM_PKW_DDOT;
88 else
89 return 0;
90 break;
91 case CURLFNM_PKW_DDOT:
92 if(c == ']')
93 found = TRUE;
94 else
95 return SETCHARSET_FAIL;
96 }
97 }
98#undef KEYLEN
99
100 *pattern = p; /* move caller's pattern pointer */
101 if(strcmp(keyword, "digit") == 0)
102 charset[CURLFNM_DIGIT] = 1;
103 else if(strcmp(keyword, "alnum") == 0)
104 charset[CURLFNM_ALNUM] = 1;
105 else if(strcmp(keyword, "alpha") == 0)
106 charset[CURLFNM_ALPHA] = 1;
107 else if(strcmp(keyword, "xdigit") == 0)
108 charset[CURLFNM_XDIGIT] = 1;
109 else if(strcmp(keyword, "print") == 0)
110 charset[CURLFNM_PRINT] = 1;
111 else if(strcmp(keyword, "graph") == 0)
112 charset[CURLFNM_GRAPH] = 1;
113 else if(strcmp(keyword, "space") == 0)
114 charset[CURLFNM_SPACE] = 1;
115 else if(strcmp(keyword, "blank") == 0)
116 charset[CURLFNM_BLANK] = 1;
117 else if(strcmp(keyword, "upper") == 0)
118 charset[CURLFNM_UPPER] = 1;
119 else if(strcmp(keyword, "lower") == 0)
120 charset[CURLFNM_LOWER] = 1;
121 else
122 return SETCHARSET_FAIL;
123 return SETCHARSET_OK;
124}
125
126/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
127static int setcharset(unsigned char **p, unsigned char *charset)
128{
129 setcharset_state state = CURLFNM_SCHS_DEFAULT;
130 unsigned char rangestart = 0;
131 unsigned char lastchar = 0;
132 bool something_found = FALSE;
133 unsigned char c;
134 for(;;) {
135 c = **p;
136 if(!c)
137 return SETCHARSET_FAIL;
138
139 switch(state) {
140 case CURLFNM_SCHS_DEFAULT:
141 if(ISALNUM(c)) { /* ASCII value */
142 rangestart = c;
143 charset[c] = 1;
144 (*p)++;
145 state = CURLFNM_SCHS_MAYRANGE;
146 something_found = TRUE;
147 }
148 else if(c == ']') {
149 if(something_found)
150 return SETCHARSET_OK;
151 something_found = TRUE;
152 state = CURLFNM_SCHS_RIGHTBR;
153 charset[c] = 1;
154 (*p)++;
155 }
156 else if(c == '[') {
157 char c2 = *((*p) + 1);
158 if(c2 == ':') { /* there has to be a keyword */
159 (*p) += 2;
160 if(parsekeyword(p, charset)) {
161 state = CURLFNM_SCHS_DEFAULT;
162 }
163 else
164 return SETCHARSET_FAIL;
165 }
166 else {
167 charset[c] = 1;
168 (*p)++;
169 }
170 something_found = TRUE;
171 }
172 else if(c == '?' || c == '*') {
173 something_found = TRUE;
174 charset[c] = 1;
175 (*p)++;
176 }
177 else if(c == '^' || c == '!') {
178 if(!something_found) {
179 if(charset[CURLFNM_NEGATE]) {
180 charset[c] = 1;
181 something_found = TRUE;
182 }
183 else
184 charset[CURLFNM_NEGATE] = 1; /* negate charset */
185 }
186 else
187 charset[c] = 1;
188 (*p)++;
189 }
190 else if(c == '\\') {
191 c = *(++(*p));
192 if(ISPRINT((c))) {
193 something_found = TRUE;
194 state = CURLFNM_SCHS_MAYRANGE;
195 charset[c] = 1;
196 rangestart = c;
197 (*p)++;
198 }
199 else
200 return SETCHARSET_FAIL;
201 }
202 else {
203 charset[c] = 1;
204 (*p)++;
205 something_found = TRUE;
206 }
207 break;
208 case CURLFNM_SCHS_MAYRANGE:
209 if(c == '-') {
210 charset[c] = 1;
211 (*p)++;
212 lastchar = '-';
213 state = CURLFNM_SCHS_MAYRANGE2;
214 }
215 else if(c == '[') {
216 state = CURLFNM_SCHS_DEFAULT;
217 }
218 else if(ISALNUM(c)) {
219 charset[c] = 1;
220 (*p)++;
221 }
222 else if(c == '\\') {
223 c = *(++(*p));
224 if(ISPRINT(c)) {
225 charset[c] = 1;
226 (*p)++;
227 }
228 else
229 return SETCHARSET_FAIL;
230 }
231 else if(c == ']') {
232 return SETCHARSET_OK;
233 }
234 else
235 return SETCHARSET_FAIL;
236 break;
237 case CURLFNM_SCHS_MAYRANGE2:
238 if(c == ']') {
239 return SETCHARSET_OK;
240 }
241 else if(c == '\\') {
242 c = *(++(*p));
243 if(ISPRINT(c)) {
244 charset[c] = 1;
245 state = CURLFNM_SCHS_DEFAULT;
246 (*p)++;
247 }
248 else
249 return SETCHARSET_FAIL;
250 }
251 else if(c >= rangestart) {
252 if((ISLOWER(c) && ISLOWER(rangestart)) ||
253 (ISDIGIT(c) && ISDIGIT(rangestart)) ||
254 (ISUPPER(c) && ISUPPER(rangestart))) {
255 charset[lastchar] = 0;
256 rangestart++;
257 while(rangestart++ <= c)
258 charset[rangestart-1] = 1;
259 (*p)++;
260 state = CURLFNM_SCHS_DEFAULT;
261 }
262 else
263 return SETCHARSET_FAIL;
264 }
265 else
266 return SETCHARSET_FAIL;
267 break;
268 case CURLFNM_SCHS_RIGHTBR:
269 if(c == '[') {
270 state = CURLFNM_SCHS_RIGHTBRLEFTBR;
271 charset[c] = 1;
272 (*p)++;
273 }
274 else if(c == ']') {
275 return SETCHARSET_OK;
276 }
277 else if(ISPRINT(c)) {
278 charset[c] = 1;
279 (*p)++;
280 state = CURLFNM_SCHS_DEFAULT;
281 }
282 else
283 /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
284 * nonsense warning 'statement not reached' at end of the fnc when
285 * compiling on Solaris */
286 goto fail;
287 break;
288 case CURLFNM_SCHS_RIGHTBRLEFTBR:
289 if(c == ']') {
290 return SETCHARSET_OK;
291 }
292 else {
293 state = CURLFNM_SCHS_DEFAULT;
294 charset[c] = 1;
295 (*p)++;
296 }
297 break;
298 }
299 }
300fail:
301 return SETCHARSET_FAIL;
302}
303
304static int loop(const unsigned char *pattern, const unsigned char *string)
305{
306 loop_state state = CURLFNM_LOOP_DEFAULT;
307 unsigned char *p = (unsigned char *)pattern;
308 unsigned char *s = (unsigned char *)string;
309 unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
310 int rc = 0;
311
312 for(;;) {
313 switch(state) {
314 case CURLFNM_LOOP_DEFAULT:
315 if(*p == '*') {
316 while(*(p + 1) == '*') /* eliminate multiple stars */
317 p++;
318 if(*s == '\0' && *(p + 1) == '\0')
319 return CURL_FNMATCH_MATCH;
320 rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
321 if(rc == CURL_FNMATCH_MATCH)
322 return CURL_FNMATCH_MATCH;
323 if(*s) /* let the star eat up one character */
324 s++;
325 else
326 return CURL_FNMATCH_NOMATCH;
327 }
328 else if(*p == '?') {
329 if(ISPRINT(*s)) {
330 s++;
331 p++;
332 }
333 else if(*s == '\0')
334 return CURL_FNMATCH_NOMATCH;
335 else
336 return CURL_FNMATCH_FAIL; /* cannot deal with other character */
337 }
338 else if(*p == '\0') {
339 if(*s == '\0')
340 return CURL_FNMATCH_MATCH;
341 return CURL_FNMATCH_NOMATCH;
342 }
343 else if(*p == '\\') {
344 state = CURLFNM_LOOP_BACKSLASH;
345 p++;
346 }
347 else if(*p == '[') {
348 unsigned char *pp = p + 1; /* cannot handle with pointer to register */
349 if(setcharset(&pp, charset)) {
350 int found = FALSE;
351 if(charset[(unsigned int)*s])
352 found = TRUE;
353 else if(charset[CURLFNM_ALNUM])
354 found = ISALNUM(*s);
355 else if(charset[CURLFNM_ALPHA])
356 found = ISALPHA(*s);
357 else if(charset[CURLFNM_DIGIT])
358 found = ISDIGIT(*s);
359 else if(charset[CURLFNM_XDIGIT])
360 found = ISXDIGIT(*s);
361 else if(charset[CURLFNM_PRINT])
362 found = ISPRINT(*s);
363 else if(charset[CURLFNM_SPACE])
364 found = ISSPACE(*s);
365 else if(charset[CURLFNM_UPPER])
366 found = ISUPPER(*s);
367 else if(charset[CURLFNM_LOWER])
368 found = ISLOWER(*s);
369 else if(charset[CURLFNM_BLANK])
370 found = ISBLANK(*s);
371 else if(charset[CURLFNM_GRAPH])
372 found = ISGRAPH(*s);
373
374 if(charset[CURLFNM_NEGATE])
375 found = !found;
376
377 if(found) {
378 p = pp + 1;
379 s++;
380 memset(charset, 0, CURLFNM_CHSET_SIZE);
381 }
382 else
383 return CURL_FNMATCH_NOMATCH;
384 }
385 else
386 return CURL_FNMATCH_FAIL;
387 }
388 else {
389 if(*p++ != *s++)
390 return CURL_FNMATCH_NOMATCH;
391 }
392 break;
393 case CURLFNM_LOOP_BACKSLASH:
394 if(ISPRINT(*p)) {
395 if(*p++ == *s++)
396 state = CURLFNM_LOOP_DEFAULT;
397 else
398 return CURL_FNMATCH_NOMATCH;
399 }
400 else
401 return CURL_FNMATCH_FAIL;
402 break;
403 }
404 }
405}
406
407/*
408 * @unittest: 1307
409 */
410int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
411{
412 (void)ptr; /* the argument is specified by the curl_fnmatch_callback
413 prototype, but not used by Curl_fnmatch() */
414 if(!pattern || !string) {
415 return CURL_FNMATCH_FAIL;
416 }
417 return loop((unsigned char *)pattern, (unsigned char *)string);
418}
Note: See TracBrowser for help on using the repository browser.