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