curl_fnmatch.c
Go to the documentation of this file.
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 
49 typedef enum {
52 } loop_state;
53 
54 typedef enum {
61 
62 typedef enum {
66 
67 #define SETCHARSET_OK 1
68 #define SETCHARSET_FAIL 0
69 
70 static int parsekeyword(unsigned char **pattern, unsigned char *charset)
71 {
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) */
127 static int setcharset(unsigned char **p, unsigned char *charset)
128 {
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  switch(state) {
138  if(ISALNUM(c)) { /* ASCII value */
139  rangestart = c;
140  charset[c] = 1;
141  (*p)++;
142  state = CURLFNM_SCHS_MAYRANGE;
143  something_found = TRUE;
144  }
145  else if(c == ']') {
146  if(something_found)
147  return SETCHARSET_OK;
148  something_found = TRUE;
149  state = CURLFNM_SCHS_RIGHTBR;
150  charset[c] = 1;
151  (*p)++;
152  }
153  else if(c == '[') {
154  char c2 = *((*p) + 1);
155  if(c2 == ':') { /* there has to be a keyword */
156  (*p) += 2;
157  if(parsekeyword(p, charset)) {
158  state = CURLFNM_SCHS_DEFAULT;
159  }
160  else
161  return SETCHARSET_FAIL;
162  }
163  else {
164  charset[c] = 1;
165  (*p)++;
166  }
167  something_found = TRUE;
168  }
169  else if(c == '?' || c == '*') {
170  something_found = TRUE;
171  charset[c] = 1;
172  (*p)++;
173  }
174  else if(c == '^' || c == '!') {
175  if(!something_found) {
176  if(charset[CURLFNM_NEGATE]) {
177  charset[c] = 1;
178  something_found = TRUE;
179  }
180  else
181  charset[CURLFNM_NEGATE] = 1; /* negate charset */
182  }
183  else
184  charset[c] = 1;
185  (*p)++;
186  }
187  else if(c == '\\') {
188  c = *(++(*p));
189  if(ISPRINT((c))) {
190  something_found = TRUE;
191  state = CURLFNM_SCHS_MAYRANGE;
192  charset[c] = 1;
193  rangestart = c;
194  (*p)++;
195  }
196  else
197  return SETCHARSET_FAIL;
198  }
199  else if(c == '\0') {
200  return SETCHARSET_FAIL;
201  }
202  else {
203  charset[c] = 1;
204  (*p)++;
205  something_found = TRUE;
206  }
207  break;
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;
238  if(c == '\\') {
239  c = *(++(*p));
240  if(!ISPRINT(c))
241  return SETCHARSET_FAIL;
242  }
243  if(c == ']') {
244  return SETCHARSET_OK;
245  }
246  if(c == '\\') {
247  c = *(++(*p));
248  if(ISPRINT(c)) {
249  charset[c] = 1;
250  state = CURLFNM_SCHS_DEFAULT;
251  (*p)++;
252  }
253  else
254  return SETCHARSET_FAIL;
255  }
256  if(c >= rangestart) {
257  if((ISLOWER(c) && ISLOWER(rangestart)) ||
258  (ISDIGIT(c) && ISDIGIT(rangestart)) ||
259  (ISUPPER(c) && ISUPPER(rangestart))) {
260  charset[lastchar] = 0;
261  rangestart++;
262  while(rangestart++ <= c)
263  charset[rangestart-1] = 1;
264  (*p)++;
265  state = CURLFNM_SCHS_DEFAULT;
266  }
267  else
268  return SETCHARSET_FAIL;
269  }
270  break;
272  if(c == '[') {
274  charset[c] = 1;
275  (*p)++;
276  }
277  else if(c == ']') {
278  return SETCHARSET_OK;
279  }
280  else if(c == '\0') {
281  return SETCHARSET_FAIL;
282  }
283  else if(ISPRINT(c)) {
284  charset[c] = 1;
285  (*p)++;
286  state = CURLFNM_SCHS_DEFAULT;
287  }
288  else
289  /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
290  * nonsense warning 'statement not reached' at end of the fnc when
291  * compiling on Solaris */
292  goto fail;
293  break;
295  if(c == ']') {
296  return SETCHARSET_OK;
297  }
298  else {
299  state = CURLFNM_SCHS_DEFAULT;
300  charset[c] = 1;
301  (*p)++;
302  }
303  break;
304  }
305  }
306 fail:
307  return SETCHARSET_FAIL;
308 }
309 
310 static int loop(const unsigned char *pattern, const unsigned char *string)
311 {
313  unsigned char *p = (unsigned char *)pattern;
314  unsigned char *s = (unsigned char *)string;
315  unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
316  int rc = 0;
317 
318  for(;;) {
319  switch(state) {
321  if(*p == '*') {
322  while(*(p + 1) == '*') /* eliminate multiple stars */
323  p++;
324  if(*s == '\0' && *(p + 1) == '\0')
325  return CURL_FNMATCH_MATCH;
326  rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
327  if(rc == CURL_FNMATCH_MATCH)
328  return CURL_FNMATCH_MATCH;
329  if(*s) /* let the star eat up one character */
330  s++;
331  else
332  return CURL_FNMATCH_NOMATCH;
333  }
334  else if(*p == '?') {
335  if(ISPRINT(*s)) {
336  s++;
337  p++;
338  }
339  else if(*s == '\0')
340  return CURL_FNMATCH_NOMATCH;
341  else
342  return CURL_FNMATCH_FAIL; /* cannot deal with other character */
343  }
344  else if(*p == '\0') {
345  if(*s == '\0')
346  return CURL_FNMATCH_MATCH;
347  return CURL_FNMATCH_NOMATCH;
348  }
349  else if(*p == '\\') {
350  state = CURLFNM_LOOP_BACKSLASH;
351  p++;
352  }
353  else if(*p == '[') {
354  unsigned char *pp = p + 1; /* cannot handle with pointer to register */
355  if(setcharset(&pp, charset)) {
356  int found = FALSE;
357  if(charset[(unsigned int)*s])
358  found = TRUE;
359  else if(charset[CURLFNM_ALNUM])
360  found = ISALNUM(*s);
361  else if(charset[CURLFNM_ALPHA])
362  found = ISALPHA(*s);
363  else if(charset[CURLFNM_DIGIT])
364  found = ISDIGIT(*s);
365  else if(charset[CURLFNM_XDIGIT])
366  found = ISXDIGIT(*s);
367  else if(charset[CURLFNM_PRINT])
368  found = ISPRINT(*s);
369  else if(charset[CURLFNM_SPACE])
370  found = ISSPACE(*s);
371  else if(charset[CURLFNM_UPPER])
372  found = ISUPPER(*s);
373  else if(charset[CURLFNM_LOWER])
374  found = ISLOWER(*s);
375  else if(charset[CURLFNM_BLANK])
376  found = ISBLANK(*s);
377  else if(charset[CURLFNM_GRAPH])
378  found = ISGRAPH(*s);
379 
380  if(charset[CURLFNM_NEGATE])
381  found = !found;
382 
383  if(found) {
384  p = pp + 1;
385  s++;
386  memset(charset, 0, CURLFNM_CHSET_SIZE);
387  }
388  else
389  return CURL_FNMATCH_NOMATCH;
390  }
391  else
392  return CURL_FNMATCH_FAIL;
393  }
394  else {
395  if(*p++ != *s++)
396  return CURL_FNMATCH_NOMATCH;
397  }
398  break;
400  if(ISPRINT(*p)) {
401  if(*p++ == *s++)
402  state = CURLFNM_LOOP_DEFAULT;
403  else
404  return CURL_FNMATCH_NOMATCH;
405  }
406  else
407  return CURL_FNMATCH_FAIL;
408  break;
409  }
410  }
411 }
412 
413 /*
414  * @unittest: 1307
415  */
416 int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
417 {
418  (void)ptr; /* the argument is specified by the curl_fnmatch_callback
419  prototype, but not used by Curl_fnmatch() */
420  if(!pattern || !string) {
421  return CURL_FNMATCH_FAIL;
422  }
423  return loop((unsigned char *)pattern, (unsigned char *)string);
424 }
#define state(x, y)
Definition: ftp.c:100
#define ISALPHA(x)
static int loop(const unsigned char *pattern, const unsigned char *string)
Definition: curl_fnmatch.c:310
XmlRpcServer s
UNITTEST_START char * ptr
Definition: unit1330.c:38
static int setcharset(unsigned char **p, unsigned char *charset)
Definition: curl_fnmatch.c:127
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
Definition: curl_fnmatch.c:416
#define CURLFNM_UPPER
Definition: curl_fnmatch.c:47
#define ISALNUM(x)
#define CURLFNM_DIGIT
Definition: curl_fnmatch.c:39
loop_state
Definition: curl_fnmatch.c:49
#define CURLFNM_GRAPH
Definition: curl_fnmatch.c:45
parsekey_state
Definition: curl_fnmatch.c:62
#define ISBLANK(x)
const char ** p
Definition: unit1394.c:76
#define CURLFNM_ALPHA
Definition: curl_fnmatch.c:41
unsigned int i
Definition: unit1303.c:79
#define SETCHARSET_FAIL
Definition: curl_fnmatch.c:68
#define CURL_FNMATCH_FAIL
Definition: curl_fnmatch.h:27
setcharset_state
Definition: curl_fnmatch.c:54
static int parsekeyword(unsigned char **pattern, unsigned char *charset)
Definition: curl_fnmatch.c:70
#define CURLFNM_LOWER
Definition: curl_fnmatch.c:44
#define FALSE
#define ISLOWER(x)
UNITTEST_START int rc
Definition: unit1301.c:31
#define CURLFNM_XDIGIT
Definition: curl_fnmatch.c:40
#define ISDIGIT(x)
#define fail(msg)
Definition: curlcheck.h:51
#define ISPRINT(x)
#define SETCHARSET_OK
Definition: curl_fnmatch.c:67
#define CURLFNM_NEGATE
Definition: curl_fnmatch.c:36
#define ISSPACE(x)
#define CURLFNM_BLANK
Definition: curl_fnmatch.c:43
#define CURLFNM_PRINT
Definition: curl_fnmatch.c:42
#define ISXDIGIT(x)
#define CURL_FNMATCH_NOMATCH
Definition: curl_fnmatch.h:26
#define ISGRAPH(x)
#define CURLFNM_SPACE
Definition: curl_fnmatch.c:46
#define CURLFNM_CHSET_SIZE
Definition: curl_fnmatch.c:34
#define TRUE
#define CURL_FNMATCH_MATCH
Definition: curl_fnmatch.h:25
#define ISUPPER(x)
#define KEYLEN
#define CURLFNM_ALNUM
Definition: curl_fnmatch.c:38


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:08