Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #include <curl/curl.h>
00026
00027 #include "curl_fnmatch.h"
00028 #include "curl_memory.h"
00029
00030
00031 #include "memdebug.h"
00032
00033 #define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
00034 #define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
00035
00036 #define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
00037
00038 #define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
00039 #define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
00040 #define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
00041 #define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
00042 #define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
00043 #define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
00044 #define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
00045 #define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
00046 #define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
00047 #define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
00048
00049 typedef enum {
00050 CURLFNM_LOOP_DEFAULT = 0,
00051 CURLFNM_LOOP_BACKSLASH
00052 } loop_state;
00053
00054 typedef enum {
00055 CURLFNM_SCHS_DEFAULT = 0,
00056 CURLFNM_SCHS_MAYRANGE,
00057 CURLFNM_SCHS_MAYRANGE2,
00058 CURLFNM_SCHS_RIGHTBR,
00059 CURLFNM_SCHS_RIGHTBRLEFTBR
00060 } setcharset_state;
00061
00062 typedef enum {
00063 CURLFNM_PKW_INIT = 0,
00064 CURLFNM_PKW_DDOT
00065 } parsekey_state;
00066
00067 #define SETCHARSET_OK 1
00068 #define SETCHARSET_FAIL 0
00069
00070 static int parsekeyword(unsigned char **pattern, unsigned char *charset)
00071 {
00072 parsekey_state state = CURLFNM_PKW_INIT;
00073 #define KEYLEN 10
00074 char keyword[KEYLEN] = { 0 };
00075 int found = FALSE;
00076 int i;
00077 unsigned char *p = *pattern;
00078 for(i = 0; !found; i++) {
00079 char c = *p++;
00080 if(i >= KEYLEN)
00081 return SETCHARSET_FAIL;
00082 switch(state) {
00083 case CURLFNM_PKW_INIT:
00084 if(ISALPHA(c) && ISLOWER(c))
00085 keyword[i] = c;
00086 else if(c == ':')
00087 state = CURLFNM_PKW_DDOT;
00088 else
00089 return 0;
00090 break;
00091 case CURLFNM_PKW_DDOT:
00092 if(c == ']')
00093 found = TRUE;
00094 else
00095 return SETCHARSET_FAIL;
00096 }
00097 }
00098 #undef KEYLEN
00099
00100 *pattern = p;
00101 if(strcmp(keyword, "digit") == 0)
00102 charset[CURLFNM_DIGIT] = 1;
00103 else if(strcmp(keyword, "alnum") == 0)
00104 charset[CURLFNM_ALNUM] = 1;
00105 else if(strcmp(keyword, "alpha") == 0)
00106 charset[CURLFNM_ALPHA] = 1;
00107 else if(strcmp(keyword, "xdigit") == 0)
00108 charset[CURLFNM_XDIGIT] = 1;
00109 else if(strcmp(keyword, "print") == 0)
00110 charset[CURLFNM_PRINT] = 1;
00111 else if(strcmp(keyword, "graph") == 0)
00112 charset[CURLFNM_GRAPH] = 1;
00113 else if(strcmp(keyword, "space") == 0)
00114 charset[CURLFNM_SPACE] = 1;
00115 else if(strcmp(keyword, "blank") == 0)
00116 charset[CURLFNM_BLANK] = 1;
00117 else if(strcmp(keyword, "upper") == 0)
00118 charset[CURLFNM_UPPER] = 1;
00119 else if(strcmp(keyword, "lower") == 0)
00120 charset[CURLFNM_LOWER] = 1;
00121 else
00122 return SETCHARSET_FAIL;
00123 return SETCHARSET_OK;
00124 }
00125
00126
00127 static int setcharset(unsigned char **p, unsigned char *charset)
00128 {
00129 setcharset_state state = CURLFNM_SCHS_DEFAULT;
00130 unsigned char rangestart = 0;
00131 unsigned char lastchar = 0;
00132 bool something_found = FALSE;
00133 unsigned char c;
00134 for(;;) {
00135 c = **p;
00136 switch(state) {
00137 case CURLFNM_SCHS_DEFAULT:
00138 if(ISALNUM(c)) {
00139 rangestart = c;
00140 charset[c] = 1;
00141 (*p)++;
00142 state = CURLFNM_SCHS_MAYRANGE;
00143 something_found = TRUE;
00144 }
00145 else if(c == ']') {
00146 if(something_found)
00147 return SETCHARSET_OK;
00148 else
00149 something_found = TRUE;
00150 state = CURLFNM_SCHS_RIGHTBR;
00151 charset[c] = 1;
00152 (*p)++;
00153 }
00154 else if(c == '[') {
00155 char c2 = *((*p)+1);
00156 if(c2 == ':') {
00157 (*p) += 2;
00158 if(parsekeyword(p, charset)) {
00159 state = CURLFNM_SCHS_DEFAULT;
00160 }
00161 else
00162 return SETCHARSET_FAIL;
00163 }
00164 else {
00165 charset[c] = 1;
00166 (*p)++;
00167 }
00168 something_found = TRUE;
00169 }
00170 else if(c == '?' || c == '*') {
00171 something_found = TRUE;
00172 charset[c] = 1;
00173 (*p)++;
00174 }
00175 else if(c == '^' || c == '!') {
00176 if(!something_found) {
00177 if(charset[CURLFNM_NEGATE]) {
00178 charset[c] = 1;
00179 something_found = TRUE;
00180 }
00181 else
00182 charset[CURLFNM_NEGATE] = 1;
00183 }
00184 else
00185 charset[c] = 1;
00186 (*p)++;
00187 }
00188 else if(c == '\\') {
00189 c = *(++(*p));
00190 if(ISPRINT((c))) {
00191 something_found = TRUE;
00192 state = CURLFNM_SCHS_MAYRANGE;
00193 charset[c] = 1;
00194 rangestart = c;
00195 (*p)++;
00196 }
00197 else
00198 return SETCHARSET_FAIL;
00199 }
00200 else if(c == '\0') {
00201 return SETCHARSET_FAIL;
00202 }
00203 else {
00204 charset[c] = 1;
00205 (*p)++;
00206 something_found = TRUE;
00207 }
00208 break;
00209 case CURLFNM_SCHS_MAYRANGE:
00210 if(c == '-') {
00211 charset[c] = 1;
00212 (*p)++;
00213 lastchar = '-';
00214 state = CURLFNM_SCHS_MAYRANGE2;
00215 }
00216 else if(c == '[') {
00217 state = CURLFNM_SCHS_DEFAULT;
00218 }
00219 else if(ISALNUM(c)) {
00220 charset[c] = 1;
00221 (*p)++;
00222 }
00223 else if(c == '\\') {
00224 c = *(++(*p));
00225 if(ISPRINT(c)) {
00226 charset[c] = 1;
00227 (*p)++;
00228 }
00229 else
00230 return SETCHARSET_FAIL;
00231 }
00232 else if(c == ']') {
00233 return SETCHARSET_OK;
00234 }
00235 else
00236 return SETCHARSET_FAIL;
00237 break;
00238 case CURLFNM_SCHS_MAYRANGE2:
00239 if(c == '\\') {
00240 c = *(++(*p));
00241 if(!ISPRINT(c))
00242 return SETCHARSET_FAIL;
00243 }
00244 if(c == ']') {
00245 return SETCHARSET_OK;
00246 }
00247 else if(c == '\\') {
00248 c = *(++(*p));
00249 if(ISPRINT(c)) {
00250 charset[c] = 1;
00251 state = CURLFNM_SCHS_DEFAULT;
00252 (*p)++;
00253 }
00254 else
00255 return SETCHARSET_FAIL;
00256 }
00257 if(c >= rangestart) {
00258 if((ISLOWER(c) && ISLOWER(rangestart)) ||
00259 (ISDIGIT(c) && ISDIGIT(rangestart)) ||
00260 (ISUPPER(c) && ISUPPER(rangestart))) {
00261 charset[lastchar] = 0;
00262 rangestart++;
00263 while(rangestart++ <= c)
00264 charset[rangestart-1] = 1;
00265 (*p)++;
00266 state = CURLFNM_SCHS_DEFAULT;
00267 }
00268 else
00269 return SETCHARSET_FAIL;
00270 }
00271 break;
00272 case CURLFNM_SCHS_RIGHTBR:
00273 if(c == '[') {
00274 state = CURLFNM_SCHS_RIGHTBRLEFTBR;
00275 charset[c] = 1;
00276 (*p)++;
00277 }
00278 else if(c == ']') {
00279 return SETCHARSET_OK;
00280 }
00281 else if(c == '\0') {
00282 return SETCHARSET_FAIL;
00283 }
00284 else if(ISPRINT(c)) {
00285 charset[c] = 1;
00286 (*p)++;
00287 state = CURLFNM_SCHS_DEFAULT;
00288 }
00289 else
00290
00291
00292
00293 goto fail;
00294 break;
00295 case CURLFNM_SCHS_RIGHTBRLEFTBR:
00296 if(c == ']') {
00297 return SETCHARSET_OK;
00298 }
00299 else {
00300 state = CURLFNM_SCHS_DEFAULT;
00301 charset[c] = 1;
00302 (*p)++;
00303 }
00304 break;
00305 }
00306 }
00307 fail:
00308 return SETCHARSET_FAIL;
00309 }
00310
00311 static int loop(const unsigned char *pattern, const unsigned char *string)
00312 {
00313 loop_state state = CURLFNM_LOOP_DEFAULT;
00314 unsigned char *p = (unsigned char *)pattern;
00315 unsigned char *s = (unsigned char *)string;
00316 unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
00317 int rc = 0;
00318
00319 for(;;) {
00320 switch(state) {
00321 case CURLFNM_LOOP_DEFAULT:
00322 if(*p == '*') {
00323 while(*(p+1) == '*')
00324 p++;
00325 if(*s == '\0' && *(p+1) == '\0')
00326 return CURL_FNMATCH_MATCH;
00327 rc = loop(p + 1, s);
00328 if(rc == CURL_FNMATCH_MATCH)
00329 return CURL_FNMATCH_MATCH;
00330 if(*s)
00331 s++;
00332 else
00333 return CURL_FNMATCH_NOMATCH;
00334 }
00335 else if(*p == '?') {
00336 if(ISPRINT(*s)) {
00337 s++;
00338 p++;
00339 }
00340 else if(*s == '\0')
00341 return CURL_FNMATCH_NOMATCH;
00342 else
00343 return CURL_FNMATCH_FAIL;
00344 }
00345 else if(*p == '\0') {
00346 if(*s == '\0')
00347 return CURL_FNMATCH_MATCH;
00348 else
00349 return CURL_FNMATCH_NOMATCH;
00350 }
00351 else if(*p == '\\') {
00352 state = CURLFNM_LOOP_BACKSLASH;
00353 p++;
00354 }
00355 else if(*p == '[') {
00356 unsigned char *pp = p+1;
00357 if(setcharset(&pp, charset)) {
00358 int found = FALSE;
00359 if(charset[(unsigned int)*s])
00360 found = TRUE;
00361 else if(charset[CURLFNM_ALNUM])
00362 found = ISALNUM(*s);
00363 else if(charset[CURLFNM_ALPHA])
00364 found = ISALPHA(*s);
00365 else if(charset[CURLFNM_DIGIT])
00366 found = ISDIGIT(*s);
00367 else if(charset[CURLFNM_XDIGIT])
00368 found = ISXDIGIT(*s);
00369 else if(charset[CURLFNM_PRINT])
00370 found = ISPRINT(*s);
00371 else if(charset[CURLFNM_SPACE])
00372 found = ISSPACE(*s);
00373 else if(charset[CURLFNM_UPPER])
00374 found = ISUPPER(*s);
00375 else if(charset[CURLFNM_LOWER])
00376 found = ISLOWER(*s);
00377 else if(charset[CURLFNM_BLANK])
00378 found = ISBLANK(*s);
00379 else if(charset[CURLFNM_GRAPH])
00380 found = ISGRAPH(*s);
00381
00382 if(charset[CURLFNM_NEGATE])
00383 found = !found;
00384
00385 if(found) {
00386 p = pp+1;
00387 s++;
00388 memset(charset, 0, CURLFNM_CHSET_SIZE);
00389 }
00390 else
00391 return CURL_FNMATCH_NOMATCH;
00392 }
00393 else
00394 return CURL_FNMATCH_FAIL;
00395 }
00396 else {
00397 if(*p++ != *s++)
00398 return CURL_FNMATCH_NOMATCH;
00399 }
00400 break;
00401 case CURLFNM_LOOP_BACKSLASH:
00402 if(ISPRINT(*p)) {
00403 if(*p++ == *s++)
00404 state = CURLFNM_LOOP_DEFAULT;
00405 else
00406 return CURL_FNMATCH_NOMATCH;
00407 }
00408 else
00409 return CURL_FNMATCH_FAIL;
00410 break;
00411 }
00412 }
00413 }
00414
00415
00416
00417
00418 int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
00419 {
00420 (void)ptr;
00421
00422 if(!pattern || !string) {
00423 return CURL_FNMATCH_FAIL;
00424 }
00425 return loop((unsigned char *)pattern, (unsigned char *)string);
00426 }