113498266Sopenharmony_ci/***************************************************************************
213498266Sopenharmony_ci *                                  _   _ ____  _
313498266Sopenharmony_ci *  Project                     ___| | | |  _ \| |
413498266Sopenharmony_ci *                             / __| | | | |_) | |
513498266Sopenharmony_ci *                            | (__| |_| |  _ <| |___
613498266Sopenharmony_ci *                             \___|\___/|_| \_\_____|
713498266Sopenharmony_ci *
813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
913498266Sopenharmony_ci *
1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which
1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms
1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html.
1313498266Sopenharmony_ci *
1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell
1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is
1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file.
1713498266Sopenharmony_ci *
1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
1913498266Sopenharmony_ci * KIND, either express or implied.
2013498266Sopenharmony_ci *
2113498266Sopenharmony_ci * SPDX-License-Identifier: curl
2213498266Sopenharmony_ci *
2313498266Sopenharmony_ci ***************************************************************************/
2413498266Sopenharmony_ci
2513498266Sopenharmony_ci#include "curl_setup.h"
2613498266Sopenharmony_ci#ifndef CURL_DISABLE_FTP
2713498266Sopenharmony_ci#include <curl/curl.h>
2813498266Sopenharmony_ci
2913498266Sopenharmony_ci#include "curl_fnmatch.h"
3013498266Sopenharmony_ci#include "curl_memory.h"
3113498266Sopenharmony_ci
3213498266Sopenharmony_ci/* The last #include file should be: */
3313498266Sopenharmony_ci#include "memdebug.h"
3413498266Sopenharmony_ci
3513498266Sopenharmony_ci#ifndef HAVE_FNMATCH
3613498266Sopenharmony_ci
3713498266Sopenharmony_ci#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
3813498266Sopenharmony_ci#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
3913498266Sopenharmony_ci
4013498266Sopenharmony_ci#define CURLFNM_NEGATE  CURLFNM_CHARSET_LEN
4113498266Sopenharmony_ci
4213498266Sopenharmony_ci#define CURLFNM_ALNUM   (CURLFNM_CHARSET_LEN + 1)
4313498266Sopenharmony_ci#define CURLFNM_DIGIT   (CURLFNM_CHARSET_LEN + 2)
4413498266Sopenharmony_ci#define CURLFNM_XDIGIT  (CURLFNM_CHARSET_LEN + 3)
4513498266Sopenharmony_ci#define CURLFNM_ALPHA   (CURLFNM_CHARSET_LEN + 4)
4613498266Sopenharmony_ci#define CURLFNM_PRINT   (CURLFNM_CHARSET_LEN + 5)
4713498266Sopenharmony_ci#define CURLFNM_BLANK   (CURLFNM_CHARSET_LEN + 6)
4813498266Sopenharmony_ci#define CURLFNM_LOWER   (CURLFNM_CHARSET_LEN + 7)
4913498266Sopenharmony_ci#define CURLFNM_GRAPH   (CURLFNM_CHARSET_LEN + 8)
5013498266Sopenharmony_ci#define CURLFNM_SPACE   (CURLFNM_CHARSET_LEN + 9)
5113498266Sopenharmony_ci#define CURLFNM_UPPER   (CURLFNM_CHARSET_LEN + 10)
5213498266Sopenharmony_ci
5313498266Sopenharmony_citypedef enum {
5413498266Sopenharmony_ci  CURLFNM_SCHS_DEFAULT = 0,
5513498266Sopenharmony_ci  CURLFNM_SCHS_RIGHTBR,
5613498266Sopenharmony_ci  CURLFNM_SCHS_RIGHTBRLEFTBR
5713498266Sopenharmony_ci} setcharset_state;
5813498266Sopenharmony_ci
5913498266Sopenharmony_citypedef enum {
6013498266Sopenharmony_ci  CURLFNM_PKW_INIT = 0,
6113498266Sopenharmony_ci  CURLFNM_PKW_DDOT
6213498266Sopenharmony_ci} parsekey_state;
6313498266Sopenharmony_ci
6413498266Sopenharmony_citypedef enum {
6513498266Sopenharmony_ci  CCLASS_OTHER = 0,
6613498266Sopenharmony_ci  CCLASS_DIGIT,
6713498266Sopenharmony_ci  CCLASS_UPPER,
6813498266Sopenharmony_ci  CCLASS_LOWER
6913498266Sopenharmony_ci} char_class;
7013498266Sopenharmony_ci
7113498266Sopenharmony_ci#define SETCHARSET_OK     1
7213498266Sopenharmony_ci#define SETCHARSET_FAIL   0
7313498266Sopenharmony_ci
7413498266Sopenharmony_cistatic int parsekeyword(unsigned char **pattern, unsigned char *charset)
7513498266Sopenharmony_ci{
7613498266Sopenharmony_ci  parsekey_state state = CURLFNM_PKW_INIT;
7713498266Sopenharmony_ci#define KEYLEN 10
7813498266Sopenharmony_ci  char keyword[KEYLEN] = { 0 };
7913498266Sopenharmony_ci  int i;
8013498266Sopenharmony_ci  unsigned char *p = *pattern;
8113498266Sopenharmony_ci  bool found = FALSE;
8213498266Sopenharmony_ci  for(i = 0; !found; i++) {
8313498266Sopenharmony_ci    char c = *p++;
8413498266Sopenharmony_ci    if(i >= KEYLEN)
8513498266Sopenharmony_ci      return SETCHARSET_FAIL;
8613498266Sopenharmony_ci    switch(state) {
8713498266Sopenharmony_ci    case CURLFNM_PKW_INIT:
8813498266Sopenharmony_ci      if(ISLOWER(c))
8913498266Sopenharmony_ci        keyword[i] = c;
9013498266Sopenharmony_ci      else if(c == ':')
9113498266Sopenharmony_ci        state = CURLFNM_PKW_DDOT;
9213498266Sopenharmony_ci      else
9313498266Sopenharmony_ci        return SETCHARSET_FAIL;
9413498266Sopenharmony_ci      break;
9513498266Sopenharmony_ci    case CURLFNM_PKW_DDOT:
9613498266Sopenharmony_ci      if(c == ']')
9713498266Sopenharmony_ci        found = TRUE;
9813498266Sopenharmony_ci      else
9913498266Sopenharmony_ci        return SETCHARSET_FAIL;
10013498266Sopenharmony_ci    }
10113498266Sopenharmony_ci  }
10213498266Sopenharmony_ci#undef KEYLEN
10313498266Sopenharmony_ci
10413498266Sopenharmony_ci  *pattern = p; /* move caller's pattern pointer */
10513498266Sopenharmony_ci  if(strcmp(keyword, "digit") == 0)
10613498266Sopenharmony_ci    charset[CURLFNM_DIGIT] = 1;
10713498266Sopenharmony_ci  else if(strcmp(keyword, "alnum") == 0)
10813498266Sopenharmony_ci    charset[CURLFNM_ALNUM] = 1;
10913498266Sopenharmony_ci  else if(strcmp(keyword, "alpha") == 0)
11013498266Sopenharmony_ci    charset[CURLFNM_ALPHA] = 1;
11113498266Sopenharmony_ci  else if(strcmp(keyword, "xdigit") == 0)
11213498266Sopenharmony_ci    charset[CURLFNM_XDIGIT] = 1;
11313498266Sopenharmony_ci  else if(strcmp(keyword, "print") == 0)
11413498266Sopenharmony_ci    charset[CURLFNM_PRINT] = 1;
11513498266Sopenharmony_ci  else if(strcmp(keyword, "graph") == 0)
11613498266Sopenharmony_ci    charset[CURLFNM_GRAPH] = 1;
11713498266Sopenharmony_ci  else if(strcmp(keyword, "space") == 0)
11813498266Sopenharmony_ci    charset[CURLFNM_SPACE] = 1;
11913498266Sopenharmony_ci  else if(strcmp(keyword, "blank") == 0)
12013498266Sopenharmony_ci    charset[CURLFNM_BLANK] = 1;
12113498266Sopenharmony_ci  else if(strcmp(keyword, "upper") == 0)
12213498266Sopenharmony_ci    charset[CURLFNM_UPPER] = 1;
12313498266Sopenharmony_ci  else if(strcmp(keyword, "lower") == 0)
12413498266Sopenharmony_ci    charset[CURLFNM_LOWER] = 1;
12513498266Sopenharmony_ci  else
12613498266Sopenharmony_ci    return SETCHARSET_FAIL;
12713498266Sopenharmony_ci  return SETCHARSET_OK;
12813498266Sopenharmony_ci}
12913498266Sopenharmony_ci
13013498266Sopenharmony_ci/* Return the character class. */
13113498266Sopenharmony_cistatic char_class charclass(unsigned char c)
13213498266Sopenharmony_ci{
13313498266Sopenharmony_ci  if(ISUPPER(c))
13413498266Sopenharmony_ci    return CCLASS_UPPER;
13513498266Sopenharmony_ci  if(ISLOWER(c))
13613498266Sopenharmony_ci    return CCLASS_LOWER;
13713498266Sopenharmony_ci  if(ISDIGIT(c))
13813498266Sopenharmony_ci    return CCLASS_DIGIT;
13913498266Sopenharmony_ci  return CCLASS_OTHER;
14013498266Sopenharmony_ci}
14113498266Sopenharmony_ci
14213498266Sopenharmony_ci/* Include a character or a range in set. */
14313498266Sopenharmony_cistatic void setcharorrange(unsigned char **pp, unsigned char *charset)
14413498266Sopenharmony_ci{
14513498266Sopenharmony_ci  unsigned char *p = (*pp)++;
14613498266Sopenharmony_ci  unsigned char c = *p++;
14713498266Sopenharmony_ci
14813498266Sopenharmony_ci  charset[c] = 1;
14913498266Sopenharmony_ci  if(ISALNUM(c) && *p++ == '-') {
15013498266Sopenharmony_ci    char_class cc = charclass(c);
15113498266Sopenharmony_ci    unsigned char endrange = *p++;
15213498266Sopenharmony_ci
15313498266Sopenharmony_ci    if(endrange == '\\')
15413498266Sopenharmony_ci      endrange = *p++;
15513498266Sopenharmony_ci    if(endrange >= c && charclass(endrange) == cc) {
15613498266Sopenharmony_ci      while(c++ != endrange)
15713498266Sopenharmony_ci        if(charclass(c) == cc)  /* Chars in class may be not consecutive. */
15813498266Sopenharmony_ci          charset[c] = 1;
15913498266Sopenharmony_ci      *pp = p;
16013498266Sopenharmony_ci    }
16113498266Sopenharmony_ci  }
16213498266Sopenharmony_ci}
16313498266Sopenharmony_ci
16413498266Sopenharmony_ci/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
16513498266Sopenharmony_cistatic int setcharset(unsigned char **p, unsigned char *charset)
16613498266Sopenharmony_ci{
16713498266Sopenharmony_ci  setcharset_state state = CURLFNM_SCHS_DEFAULT;
16813498266Sopenharmony_ci  bool something_found = FALSE;
16913498266Sopenharmony_ci  unsigned char c;
17013498266Sopenharmony_ci
17113498266Sopenharmony_ci  memset(charset, 0, CURLFNM_CHSET_SIZE);
17213498266Sopenharmony_ci  for(;;) {
17313498266Sopenharmony_ci    c = **p;
17413498266Sopenharmony_ci    if(!c)
17513498266Sopenharmony_ci      return SETCHARSET_FAIL;
17613498266Sopenharmony_ci
17713498266Sopenharmony_ci    switch(state) {
17813498266Sopenharmony_ci    case CURLFNM_SCHS_DEFAULT:
17913498266Sopenharmony_ci      if(c == ']') {
18013498266Sopenharmony_ci        if(something_found)
18113498266Sopenharmony_ci          return SETCHARSET_OK;
18213498266Sopenharmony_ci        something_found = TRUE;
18313498266Sopenharmony_ci        state = CURLFNM_SCHS_RIGHTBR;
18413498266Sopenharmony_ci        charset[c] = 1;
18513498266Sopenharmony_ci        (*p)++;
18613498266Sopenharmony_ci      }
18713498266Sopenharmony_ci      else if(c == '[') {
18813498266Sopenharmony_ci        unsigned char *pp = *p + 1;
18913498266Sopenharmony_ci
19013498266Sopenharmony_ci        if(*pp++ == ':' && parsekeyword(&pp, charset))
19113498266Sopenharmony_ci          *p = pp;
19213498266Sopenharmony_ci        else {
19313498266Sopenharmony_ci          charset[c] = 1;
19413498266Sopenharmony_ci          (*p)++;
19513498266Sopenharmony_ci        }
19613498266Sopenharmony_ci        something_found = TRUE;
19713498266Sopenharmony_ci      }
19813498266Sopenharmony_ci      else if(c == '^' || c == '!') {
19913498266Sopenharmony_ci        if(!something_found) {
20013498266Sopenharmony_ci          if(charset[CURLFNM_NEGATE]) {
20113498266Sopenharmony_ci            charset[c] = 1;
20213498266Sopenharmony_ci            something_found = TRUE;
20313498266Sopenharmony_ci          }
20413498266Sopenharmony_ci          else
20513498266Sopenharmony_ci            charset[CURLFNM_NEGATE] = 1; /* negate charset */
20613498266Sopenharmony_ci        }
20713498266Sopenharmony_ci        else
20813498266Sopenharmony_ci          charset[c] = 1;
20913498266Sopenharmony_ci        (*p)++;
21013498266Sopenharmony_ci      }
21113498266Sopenharmony_ci      else if(c == '\\') {
21213498266Sopenharmony_ci        c = *(++(*p));
21313498266Sopenharmony_ci        if(c)
21413498266Sopenharmony_ci          setcharorrange(p, charset);
21513498266Sopenharmony_ci        else
21613498266Sopenharmony_ci          charset['\\'] = 1;
21713498266Sopenharmony_ci        something_found = TRUE;
21813498266Sopenharmony_ci      }
21913498266Sopenharmony_ci      else {
22013498266Sopenharmony_ci        setcharorrange(p, charset);
22113498266Sopenharmony_ci        something_found = TRUE;
22213498266Sopenharmony_ci      }
22313498266Sopenharmony_ci      break;
22413498266Sopenharmony_ci    case CURLFNM_SCHS_RIGHTBR:
22513498266Sopenharmony_ci      if(c == '[') {
22613498266Sopenharmony_ci        state = CURLFNM_SCHS_RIGHTBRLEFTBR;
22713498266Sopenharmony_ci        charset[c] = 1;
22813498266Sopenharmony_ci        (*p)++;
22913498266Sopenharmony_ci      }
23013498266Sopenharmony_ci      else if(c == ']') {
23113498266Sopenharmony_ci        return SETCHARSET_OK;
23213498266Sopenharmony_ci      }
23313498266Sopenharmony_ci      else if(ISPRINT(c)) {
23413498266Sopenharmony_ci        charset[c] = 1;
23513498266Sopenharmony_ci        (*p)++;
23613498266Sopenharmony_ci        state = CURLFNM_SCHS_DEFAULT;
23713498266Sopenharmony_ci      }
23813498266Sopenharmony_ci      else
23913498266Sopenharmony_ci        /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
24013498266Sopenharmony_ci         * nonsense warning 'statement not reached' at end of the fnc when
24113498266Sopenharmony_ci         * compiling on Solaris */
24213498266Sopenharmony_ci        goto fail;
24313498266Sopenharmony_ci      break;
24413498266Sopenharmony_ci    case CURLFNM_SCHS_RIGHTBRLEFTBR:
24513498266Sopenharmony_ci      if(c == ']')
24613498266Sopenharmony_ci        return SETCHARSET_OK;
24713498266Sopenharmony_ci      state  = CURLFNM_SCHS_DEFAULT;
24813498266Sopenharmony_ci      charset[c] = 1;
24913498266Sopenharmony_ci      (*p)++;
25013498266Sopenharmony_ci      break;
25113498266Sopenharmony_ci    }
25213498266Sopenharmony_ci  }
25313498266Sopenharmony_cifail:
25413498266Sopenharmony_ci  return SETCHARSET_FAIL;
25513498266Sopenharmony_ci}
25613498266Sopenharmony_ci
25713498266Sopenharmony_cistatic int loop(const unsigned char *pattern, const unsigned char *string,
25813498266Sopenharmony_ci                int maxstars)
25913498266Sopenharmony_ci{
26013498266Sopenharmony_ci  unsigned char *p = (unsigned char *)pattern;
26113498266Sopenharmony_ci  unsigned char *s = (unsigned char *)string;
26213498266Sopenharmony_ci  unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
26313498266Sopenharmony_ci
26413498266Sopenharmony_ci  for(;;) {
26513498266Sopenharmony_ci    unsigned char *pp;
26613498266Sopenharmony_ci
26713498266Sopenharmony_ci    switch(*p) {
26813498266Sopenharmony_ci    case '*':
26913498266Sopenharmony_ci      if(!maxstars)
27013498266Sopenharmony_ci        return CURL_FNMATCH_NOMATCH;
27113498266Sopenharmony_ci      /* Regroup consecutive stars and question marks. This can be done because
27213498266Sopenharmony_ci         '*?*?*' can be expressed as '??*'. */
27313498266Sopenharmony_ci      for(;;) {
27413498266Sopenharmony_ci        if(*++p == '\0')
27513498266Sopenharmony_ci          return CURL_FNMATCH_MATCH;
27613498266Sopenharmony_ci        if(*p == '?') {
27713498266Sopenharmony_ci          if(!*s++)
27813498266Sopenharmony_ci            return CURL_FNMATCH_NOMATCH;
27913498266Sopenharmony_ci        }
28013498266Sopenharmony_ci        else if(*p != '*')
28113498266Sopenharmony_ci          break;
28213498266Sopenharmony_ci      }
28313498266Sopenharmony_ci      /* Skip string characters until we find a match with pattern suffix. */
28413498266Sopenharmony_ci      for(maxstars--; *s; s++) {
28513498266Sopenharmony_ci        if(loop(p, s, maxstars) == CURL_FNMATCH_MATCH)
28613498266Sopenharmony_ci          return CURL_FNMATCH_MATCH;
28713498266Sopenharmony_ci      }
28813498266Sopenharmony_ci      return CURL_FNMATCH_NOMATCH;
28913498266Sopenharmony_ci    case '?':
29013498266Sopenharmony_ci      if(!*s)
29113498266Sopenharmony_ci        return CURL_FNMATCH_NOMATCH;
29213498266Sopenharmony_ci      s++;
29313498266Sopenharmony_ci      p++;
29413498266Sopenharmony_ci      break;
29513498266Sopenharmony_ci    case '\0':
29613498266Sopenharmony_ci      return *s? CURL_FNMATCH_NOMATCH: CURL_FNMATCH_MATCH;
29713498266Sopenharmony_ci    case '\\':
29813498266Sopenharmony_ci      if(p[1])
29913498266Sopenharmony_ci        p++;
30013498266Sopenharmony_ci      if(*s++ != *p++)
30113498266Sopenharmony_ci        return CURL_FNMATCH_NOMATCH;
30213498266Sopenharmony_ci      break;
30313498266Sopenharmony_ci    case '[':
30413498266Sopenharmony_ci      pp = p + 1; /* Copy in case of syntax error in set. */
30513498266Sopenharmony_ci      if(setcharset(&pp, charset)) {
30613498266Sopenharmony_ci        int found = FALSE;
30713498266Sopenharmony_ci        if(!*s)
30813498266Sopenharmony_ci          return CURL_FNMATCH_NOMATCH;
30913498266Sopenharmony_ci        if(charset[(unsigned int)*s])
31013498266Sopenharmony_ci          found = TRUE;
31113498266Sopenharmony_ci        else if(charset[CURLFNM_ALNUM])
31213498266Sopenharmony_ci          found = ISALNUM(*s);
31313498266Sopenharmony_ci        else if(charset[CURLFNM_ALPHA])
31413498266Sopenharmony_ci          found = ISALPHA(*s);
31513498266Sopenharmony_ci        else if(charset[CURLFNM_DIGIT])
31613498266Sopenharmony_ci          found = ISDIGIT(*s);
31713498266Sopenharmony_ci        else if(charset[CURLFNM_XDIGIT])
31813498266Sopenharmony_ci          found = ISXDIGIT(*s);
31913498266Sopenharmony_ci        else if(charset[CURLFNM_PRINT])
32013498266Sopenharmony_ci          found = ISPRINT(*s);
32113498266Sopenharmony_ci        else if(charset[CURLFNM_SPACE])
32213498266Sopenharmony_ci          found = ISSPACE(*s);
32313498266Sopenharmony_ci        else if(charset[CURLFNM_UPPER])
32413498266Sopenharmony_ci          found = ISUPPER(*s);
32513498266Sopenharmony_ci        else if(charset[CURLFNM_LOWER])
32613498266Sopenharmony_ci          found = ISLOWER(*s);
32713498266Sopenharmony_ci        else if(charset[CURLFNM_BLANK])
32813498266Sopenharmony_ci          found = ISBLANK(*s);
32913498266Sopenharmony_ci        else if(charset[CURLFNM_GRAPH])
33013498266Sopenharmony_ci          found = ISGRAPH(*s);
33113498266Sopenharmony_ci
33213498266Sopenharmony_ci        if(charset[CURLFNM_NEGATE])
33313498266Sopenharmony_ci          found = !found;
33413498266Sopenharmony_ci
33513498266Sopenharmony_ci        if(!found)
33613498266Sopenharmony_ci          return CURL_FNMATCH_NOMATCH;
33713498266Sopenharmony_ci        p = pp + 1;
33813498266Sopenharmony_ci        s++;
33913498266Sopenharmony_ci        break;
34013498266Sopenharmony_ci      }
34113498266Sopenharmony_ci      /* Syntax error in set; mismatch! */
34213498266Sopenharmony_ci      return CURL_FNMATCH_NOMATCH;
34313498266Sopenharmony_ci
34413498266Sopenharmony_ci    default:
34513498266Sopenharmony_ci      if(*p++ != *s++)
34613498266Sopenharmony_ci        return CURL_FNMATCH_NOMATCH;
34713498266Sopenharmony_ci      break;
34813498266Sopenharmony_ci    }
34913498266Sopenharmony_ci  }
35013498266Sopenharmony_ci}
35113498266Sopenharmony_ci
35213498266Sopenharmony_ci/*
35313498266Sopenharmony_ci * @unittest: 1307
35413498266Sopenharmony_ci */
35513498266Sopenharmony_ciint Curl_fnmatch(void *ptr, const char *pattern, const char *string)
35613498266Sopenharmony_ci{
35713498266Sopenharmony_ci  (void)ptr; /* the argument is specified by the curl_fnmatch_callback
35813498266Sopenharmony_ci                prototype, but not used by Curl_fnmatch() */
35913498266Sopenharmony_ci  if(!pattern || !string) {
36013498266Sopenharmony_ci    return CURL_FNMATCH_FAIL;
36113498266Sopenharmony_ci  }
36213498266Sopenharmony_ci  return loop((unsigned char *)pattern, (unsigned char *)string, 2);
36313498266Sopenharmony_ci}
36413498266Sopenharmony_ci#else
36513498266Sopenharmony_ci#include <fnmatch.h>
36613498266Sopenharmony_ci/*
36713498266Sopenharmony_ci * @unittest: 1307
36813498266Sopenharmony_ci */
36913498266Sopenharmony_ciint Curl_fnmatch(void *ptr, const char *pattern, const char *string)
37013498266Sopenharmony_ci{
37113498266Sopenharmony_ci  (void)ptr; /* the argument is specified by the curl_fnmatch_callback
37213498266Sopenharmony_ci                prototype, but not used by Curl_fnmatch() */
37313498266Sopenharmony_ci  if(!pattern || !string) {
37413498266Sopenharmony_ci    return CURL_FNMATCH_FAIL;
37513498266Sopenharmony_ci  }
37613498266Sopenharmony_ci
37713498266Sopenharmony_ci  switch(fnmatch(pattern, string, 0)) {
37813498266Sopenharmony_ci  case 0:
37913498266Sopenharmony_ci    return CURL_FNMATCH_MATCH;
38013498266Sopenharmony_ci  case FNM_NOMATCH:
38113498266Sopenharmony_ci    return CURL_FNMATCH_NOMATCH;
38213498266Sopenharmony_ci  default:
38313498266Sopenharmony_ci    return CURL_FNMATCH_FAIL;
38413498266Sopenharmony_ci  }
38513498266Sopenharmony_ci  /* not reached */
38613498266Sopenharmony_ci}
38713498266Sopenharmony_ci
38813498266Sopenharmony_ci#endif
38913498266Sopenharmony_ci
39013498266Sopenharmony_ci#endif /* if FTP is disabled */
391