diff options
author | Daniel Stenberg <daniel@haxx.se> | 2013-08-15 13:05:25 +0200 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2013-08-16 11:52:08 +0200 |
commit | 5ca96cb84410270e233c92bf1b2583cba40c3fad (patch) | |
tree | e577dbc96ddf320574a030213f4880815558ea84 /src | |
parent | 10afe7cf105d03b94b34f937d53e9b352b87817c (diff) |
urlglob: better detect unclosed braces, empty lists and overflows
A rather big overhaul and cleanup.
1 - curl wouldn't properly detect and reject globbing that ended with an
open brace if there were brackets or braces before it. Like "{}{" or
"[0-1]{"
2 - curl wouldn't properly reject empty lists so that "{}{}" would
result in curl getting (nil) strings in the output.
3 - By using strtoul() instead of sscanf() the code will now detected
over and underflows. It now also better parses the step argument to only
accept positive numbers and only step counters that is smaller than the
delta between the maximum and minimum numbers.
4 - By switching to unsigned longs instead of signed ints for the
counters, the max values for []-ranges are now very large (on 64bit
machines).
5 - Bumped the maximum number of globs in a single URL to 100 (from 10)
6 - Simplified the code somewhat and now it stores fixed strings as
single- entry lists. That's also one of the reasons why I did (5) as now
all strings between "globs" will take a slot in the array.
Added test 1234 and 1235 to verify. Updated test 87.
This commit fixes three separate bug reports.
Bug: http://curl.haxx.se/bug/view.cgi?id=1264
Bug: http://curl.haxx.se/bug/view.cgi?id=1265
Bug: http://curl.haxx.se/bug/view.cgi?id=1266
Reported-by: Will Dietz
Diffstat (limited to 'src')
-rw-r--r-- | src/tool_operate.c | 15 | ||||
-rw-r--r-- | src/tool_urlglob.c | 473 | ||||
-rw-r--r-- | src/tool_urlglob.h | 25 |
3 files changed, 264 insertions, 249 deletions
diff --git a/src/tool_operate.c b/src/tool_operate.c index ed60e7031..dbbbc26c2 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -196,6 +196,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) bool stillflags; int res = 0; int i; + unsigned long li; bool orig_noprogress; bool orig_isatty; @@ -465,10 +466,10 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) for(urlnode = config->url_list; urlnode; urlnode = urlnode->next) { - int up; /* upload file counter within a single upload glob */ + unsigned long up; /* upload file counter within a single upload glob */ char *infiles; /* might be a glob pattern */ char *outfiles; - int infilenum; + unsigned long infilenum; URLGlob *inglob; int metalink = 0; /* nonzero for metalink download. */ @@ -533,7 +534,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) char *uploadfile; /* a single file, never a glob */ int separator; URLGlob *urls; - int urlnum; + unsigned long urlnum; uploadfile = NULL; urls = NULL; @@ -583,7 +584,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) separator= ((!outfiles || curlx_strequal(outfiles, "-")) && urlnum > 1); /* Here's looping around each globbed URL */ - for(i = 0 ; i < urlnum; i++) { + for(li = 0 ; li < urlnum; li++) { int infd; bool infdopen; @@ -628,7 +629,7 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) if(res) goto show_error; } - else if(!i) { + else if(!li) { this_url = strdup(urlnode->url); if(!this_url) { res = CURLE_OUT_OF_MEMORY; @@ -863,8 +864,8 @@ int operate(struct Configurable *config, int argc, argv_item_t argv[]) } if(urlnum > 1 && !(config->mute)) { - fprintf(config->errors, "\n[%d/%d]: %s --> %s\n", - i+1, urlnum, this_url, outfile ? outfile : "<stdout>"); + fprintf(config->errors, "\n[%lu/%lu]: %s --> %s\n", + li+1, urlnum, this_url, outfile ? outfile : "<stdout>"); if(separator) printf("%s%s\n", CURLseparator, this_url); } diff --git a/src/tool_urlglob.c b/src/tool_urlglob.c index 2821d008d..0e454c19c 100644 --- a/src/tool_urlglob.c +++ b/src/tool_urlglob.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -35,39 +35,53 @@ typedef enum { GLOB_ERROR } GlobCode; -/* - * glob_word() - * - * Input a full globbed string, set the forth argument to the amount of - * strings we get out of this. Return GlobCode. - */ -static GlobCode glob_word(URLGlob *, /* object anchor */ - char *, /* globbed string */ - size_t, /* position */ - int *); /* returned number of strings */ - -static GlobCode glob_set(URLGlob *glob, char *pattern, - size_t pos, int *amount) +void glob_cleanup(URLGlob* glob); + +static GlobCode glob_fixed(URLGlob *glob, unsigned long *amount) +{ + URLPattern *pat = &glob->pattern[glob->size]; + pat->type = UPTSet; + pat->content.Set.size = 1; + pat->content.Set.ptr_s = 0; + pat->globindex = -1; + + (*amount)++; + + pat->content.Set.elements = malloc(sizeof(char*)); + + if(!pat->content.Set.elements) { + snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); + return GLOB_NO_MEM; + } + pat->content.Set.elements[0] = strdup(glob->glob_buffer); + if(!pat->content.Set.elements[0]) { + snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); + return GLOB_NO_MEM; + } + + return GLOB_OK; +} + +static GlobCode glob_set(URLGlob *glob, char **patternp, + size_t pos, unsigned long *amount, + int globindex) { /* processes a set expression with the point behind the opening '{' ','-separated elements are collected until the next closing '}' */ URLPattern *pat; - GlobCode res; bool done = FALSE; - char* buf = glob->glob_buffer; + char *buf = glob->glob_buffer; + char *pattern = *patternp; + char *opattern = pattern; - pat = &glob->pattern[glob->size / 2]; + pat = &glob->pattern[glob->size]; /* patterns 0,1,2,... correspond to size=1,3,5,... */ pat->type = UPTSet; pat->content.Set.size = 0; pat->content.Set.ptr_s = 0; pat->content.Set.elements = NULL; - - if(++glob->size > (GLOB_PATTERN_NUM*2)) { - snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n"); - return GLOB_ERROR; - } + pat->globindex = globindex; while(!done) { switch (*pattern) { @@ -82,60 +96,46 @@ static GlobCode glob_set(URLGlob *glob, char *pattern, "nested braces not supported at pos %zu\n", pos); return GLOB_ERROR; - case ',': case '}': /* set element completed */ + if(opattern == pattern) { + snprintf(glob->errormsg, sizeof(glob->errormsg), + "no string within braces at pos %zu\n", pos); + return GLOB_ERROR; + } + /* add 1 since it'll be incremented below */ + (*amount) *= (pat->content.Set.size+1); + /* fall-through */ + case ',': + *buf = '\0'; if(pat->content.Set.elements) { char **new_arr = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*)); if(!new_arr) { - short elem; - for(elem = 0; elem < pat->content.Set.size; elem++) - Curl_safefree(pat->content.Set.elements[elem]); - Curl_safefree(pat->content.Set.elements); - pat->content.Set.ptr_s = 0; - pat->content.Set.size = 0; + snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); + return GLOB_NO_MEM; } + pat->content.Set.elements = new_arr; } else pat->content.Set.elements = malloc(sizeof(char*)); + if(!pat->content.Set.elements) { snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); return GLOB_NO_MEM; } + pat->content.Set.elements[pat->content.Set.size] = strdup(glob->glob_buffer); if(!pat->content.Set.elements[pat->content.Set.size]) { - short elem; - for(elem = 0; elem < pat->content.Set.size; elem++) - Curl_safefree(pat->content.Set.elements[elem]); - Curl_safefree(pat->content.Set.elements); - pat->content.Set.ptr_s = 0; - pat->content.Set.size = 0; snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); return GLOB_NO_MEM; } ++pat->content.Set.size; if(*pattern == '}') { - /* entire set pattern completed */ - int wordamount; - - /* always check for a literal (may be "") between patterns */ - res = glob_word(glob, ++pattern, ++pos, &wordamount); - if(res) { - short elem; - for(elem = 0; elem < pat->content.Set.size; elem++) - Curl_safefree(pat->content.Set.elements[elem]); - Curl_safefree(pat->content.Set.elements); - pat->content.Set.ptr_s = 0; - pat->content.Set.size = 0; - return res; - } - - *amount = pat->content.Set.size * wordamount; - + pattern++; /* pass the closing brace */ done = TRUE; continue; } @@ -161,11 +161,14 @@ static GlobCode glob_set(URLGlob *glob, char *pattern, ++pos; } } + + *patternp = pattern; /* return with the new position */ return GLOB_OK; } -static GlobCode glob_range(URLGlob *glob, char *pattern, - size_t pos, int *amount) +static GlobCode glob_range(URLGlob *glob, char **patternp, + size_t pos, unsigned long *amount, + int globindex) { /* processes a range expression with the point behind the opening '[' - char range: e.g. "a-z]", "B-Q]" @@ -174,84 +177,119 @@ static GlobCode glob_range(URLGlob *glob, char *pattern, expression is checked for well-formedness and collected until the next ']' */ URLPattern *pat; - char *c; - char sep; - char sep2; - int step; int rc; - GlobCode res; - int wordamount = 1; + char *pattern = *patternp; + char *c; - pat = &glob->pattern[glob->size / 2]; - /* patterns 0,1,2,... correspond to size=1,3,5,... */ - if(++glob->size > (GLOB_PATTERN_NUM*2)) { - snprintf(glob->errormsg, sizeof(glob->errormsg), "too many globs used\n"); - return GLOB_ERROR; - } + pat = &glob->pattern[glob->size]; + pat->globindex = globindex; if(ISALPHA(*pattern)) { /* character range detected */ char min_c; char max_c; + int step=1; pat->type = UPTCharRange; - rc = sscanf(pattern, "%c-%c%c%d%c", &min_c, &max_c, &sep, &step, &sep2); + rc = sscanf(pattern, "%c-%c", &min_c, &max_c); - if((rc < 3) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a'))) { - /* the pattern is not well-formed */ - snprintf(glob->errormsg, sizeof(glob->errormsg), - "error: bad range specification after pos %zu\n", pos); - return GLOB_ERROR; + if((rc == 2) && (pattern[3] == ':')) { + char *endp; + unsigned long lstep; + errno = 0; + lstep = strtoul(&pattern[3], &endp, 10); + if(errno || (*endp != ']')) + step = -1; + else { + pattern = endp+1; + step = (int)lstep; + if(step > (max_c - min_c)) + step = -1; + } } + else + pattern+=3; - /* check the (first) separating character */ - if((sep != ']') && (sep != ':')) { + if((rc != 2) || (min_c >= max_c) || ((max_c - min_c) > ('z' - 'a')) || + (step < 0) ) { + /* the pattern is not well-formed */ snprintf(glob->errormsg, sizeof(glob->errormsg), - "error: unsupported character (%c) after range at pos %zu\n", - sep, pos); + "error: bad range specification after pos %zu\n", pos); return GLOB_ERROR; } /* if there was a ":[num]" thing, use that as step or else use 1 */ - pat->content.CharRange.step = - ((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1; - + pat->content.CharRange.step = step; pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c; pat->content.CharRange.max_c = max_c; + + *amount *= (pat->content.CharRange.max_c - + pat->content.CharRange.min_c + 1); } else if(ISDIGIT(*pattern)) { /* numeric range detected */ - int min_n; - int max_n; + unsigned long min_n; + unsigned long max_n; + unsigned long step_n; + char *endp; pat->type = UPTNumRange; pat->content.NumRange.padlength = 0; - rc = sscanf(pattern, "%d-%d%c%d%c", &min_n, &max_n, &sep, &step, &sep2); + if(*pattern == '0') { + /* leading zero specified, count them! */ + c = pattern; + while(ISDIGIT(*c)) { + c++; + ++pat->content.NumRange.padlength; /* padding length is set for all + instances of this pattern */ + } + } - if((rc < 2) || (min_n > max_n)) { + errno = 0; + min_n = strtoul(pattern, &endp, 10); + if(errno || (endp == pattern)) + endp=NULL; + else { + if(*endp != '-') + endp = NULL; + else { + pattern = endp+1; + errno = 0; + max_n = strtoul(pattern, &endp, 10); + if(errno || (*endp == ':')) { + pattern = endp+1; + errno = 0; + step_n = strtoul(pattern, &endp, 10); + if(errno) + /* over/underflow situation */ + endp = NULL; + } + else + step_n = 1; + if(*endp == ']') { + pattern= endp+1; + } + else + endp = NULL; + } + } + + if(!endp || (min_n > max_n) || (step_n > (max_n - min_n))) { /* the pattern is not well-formed */ snprintf(glob->errormsg, sizeof(glob->errormsg), "error: bad range specification after pos %zu\n", pos); return GLOB_ERROR; } + /* typecasting to ints are fine here since we make sure above that we + are within 31 bits */ pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n; pat->content.NumRange.max_n = max_n; + pat->content.NumRange.step = step_n; - /* if there was a ":[num]" thing, use that as step or else use 1 */ - pat->content.NumRange.step = - ((sep == ':') && (rc == 5) && (sep2 == ']')) ? step : 1; - - if(*pattern == '0') { - /* leading zero specified */ - c = pattern; - while(ISDIGIT(*c)) { - c++; - ++pat->content.NumRange.padlength; /* padding length is set for all - instances of this pattern */ - } - } + *amount *= (pat->content.NumRange.max_n - + pat->content.NumRange.min_n + 1); } else { snprintf(glob->errormsg, sizeof(glob->errormsg), @@ -259,105 +297,87 @@ static GlobCode glob_range(URLGlob *glob, char *pattern, return GLOB_ERROR; } - c = (char*)strchr(pattern, ']'); /* continue after next ']' */ - if(c) - c++; - else { - snprintf(glob->errormsg, sizeof(glob->errormsg), "missing ']'"); - return GLOB_ERROR; /* missing ']' */ - } - - /* always check for a literal (may be "") between patterns */ - - res = glob_word(glob, c, pos + (c - pattern), &wordamount); - if(res == GLOB_ERROR) { - wordamount = 1; - res = GLOB_OK; - } - - if(!res) { - if(pat->type == UPTCharRange) - *amount = wordamount * (pat->content.CharRange.max_c - - pat->content.CharRange.min_c + 1); - else - *amount = wordamount * (pat->content.NumRange.max_n - - pat->content.NumRange.min_n + 1); - } - - return res; /* GLOB_OK or GLOB_NO_MEM */ + *patternp = pattern; + return GLOB_OK; } -static GlobCode glob_word(URLGlob *glob, char *pattern, - size_t pos, int *amount) +static GlobCode glob_parse(URLGlob *glob, char *pattern, + size_t pos, unsigned long *amount) { /* processes a literal string component of a URL special characters '{' and '[' branch to set/range processing functions */ char* buf = glob->glob_buffer; - size_t litindex; GlobCode res = GLOB_OK; + int globindex = 0; /* count "actual" globs */ + + while(*pattern && !res) { + int sublen = 0; + while(*pattern && *pattern != '{' && *pattern != '[') { + if(*pattern == '}' || *pattern == ']') { + snprintf(glob->errormsg, sizeof(glob->errormsg), + "unmatched close brace/bracket at pos %zu\n", pos); + return GLOB_ERROR; + } - *amount = 1; /* default is one single string */ + /* only allow \ to escape known "special letters" */ + if(*pattern == '\\' && + (*(pattern+1) == '{' || *(pattern+1) == '[' || + *(pattern+1) == '}' || *(pattern+1) == ']') ) { - while(*pattern != '\0' && *pattern != '{' && *pattern != '[') { - if(*pattern == '}' || *pattern == ']') { - snprintf(glob->errormsg, sizeof(glob->errormsg), - "unmatched close brace/bracket at pos %zu\n", pos); - return GLOB_ERROR; + /* escape character, skip '\' */ + ++pattern; + ++pos; + } + *buf++ = *pattern++; /* copy character to literal */ + ++pos; + sublen++; + } + if(sublen) { + /* we got a literal string, add it as a single-item list */ + *buf = '\0'; + res = glob_fixed(glob, amount); } + else { + if(!*amount) + *amount = 1; - /* only allow \ to escape known "special letters" */ - if(*pattern == '\\' && - (*(pattern+1) == '{' || *(pattern+1) == '[' || - *(pattern+1) == '}' || *(pattern+1) == ']') ) { + switch (*pattern) { + case '\0': /* done */ + break; - /* escape character, skip '\' */ - ++pattern; - ++pos; + case '{': + /* process set pattern */ + pattern++; + res = glob_set(glob, &pattern, ++pos, amount, globindex++); + break; + + case '[': + /* process range pattern */ + pattern++; + res = glob_range(glob, &pattern, ++pos, amount, globindex++); + break; + } } - *buf++ = *pattern++; /* copy character to literal */ - ++pos; - } - *buf = '\0'; - litindex = glob->size / 2; - /* literals 0,1,2,... correspond to size=0,2,4,... */ - glob->literal[litindex] = strdup(glob->glob_buffer); - if(!glob->literal[litindex]) { - snprintf(glob->errormsg, sizeof(glob->errormsg), "out of memory\n"); - return GLOB_NO_MEM; - } - ++glob->size; - - switch (*pattern) { - case '\0': - /* singular URL processed */ - break; - - case '{': - /* process set pattern */ - res = glob_set(glob, ++pattern, ++pos, amount); - break; - - case '[': - /* process range pattern */ - res = glob_range(glob, ++pattern, ++pos, amount); - break; - } - if(res) - Curl_safefree(glob->literal[litindex]); + if(++glob->size > GLOB_PATTERN_NUM) { + snprintf(glob->errormsg, sizeof(glob->errormsg), + "too many globs used\n"); + return GLOB_ERROR; + } + } return res; } -int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error) +int glob_url(URLGlob** glob, char* url, unsigned long *urlnum, FILE *error) { /* * We can deal with any-size, just make a buffer with the same length * as the specified URL! */ URLGlob *glob_expand; - int amount; + unsigned long amount = 0; char *glob_buffer; GlobCode res; @@ -372,12 +392,10 @@ int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error) Curl_safefree(glob_buffer); return CURLE_OUT_OF_MEMORY; } - glob_expand->size = 0; glob_expand->urllen = strlen(url); glob_expand->glob_buffer = glob_buffer; - glob_expand->beenhere = 0; - res = glob_word(glob_expand, url, 1, &amount); + res = glob_parse(glob_expand, url, 1, &amount); if(!res) *urlnum = amount; else { @@ -388,8 +406,7 @@ int glob_url(URLGlob** glob, char* url, int *urlnum, FILE *error) glob_expand->errormsg); } /* it failed, we cleanup */ - Curl_safefree(glob_buffer); - Curl_safefree(glob_expand); + glob_cleanup(glob_expand); *urlnum = 1; return (res == GLOB_NO_MEM) ? CURLE_OUT_OF_MEMORY : CURLE_URL_MALFORMAT; } @@ -404,19 +421,14 @@ void glob_cleanup(URLGlob* glob) int elem; for(i = glob->size - 1; i < glob->size; --i) { - if(!(i & 1)) { /* even indexes contain literals */ - Curl_safefree(glob->literal[i/2]); - } - else { /* odd indexes contain sets or ranges */ - if((glob->pattern[i/2].type == UPTSet) && - (glob->pattern[i/2].content.Set.elements)) { - for(elem = glob->pattern[i/2].content.Set.size - 1; - elem >= 0; - --elem) { - Curl_safefree(glob->pattern[i/2].content.Set.elements[elem]); - } - Curl_safefree(glob->pattern[i/2].content.Set.elements); + if((glob->pattern[i].type == UPTSet) && + (glob->pattern[i].content.Set.elements)) { + for(elem = glob->pattern[i].content.Set.size - 1; + elem >= 0; + --elem) { + Curl_safefree(glob->pattern[i].content.Set.elements[elem]); } + Curl_safefree(glob->pattern[i].content.Set.elements); } } Curl_safefree(glob->glob_buffer); @@ -426,7 +438,6 @@ void glob_cleanup(URLGlob* glob) int glob_next_url(char **globbed, URLGlob *glob) { URLPattern *pat; - char *lit; size_t i; size_t j; size_t len; @@ -442,7 +453,7 @@ int glob_next_url(char **globbed, URLGlob *glob) /* implement a counter over the index ranges of all patterns, starting with the rightmost pattern */ - for(i = glob->size / 2 - 1; carry && (i < glob->size); --i) { + for(i = glob->size - 1; carry && (i < glob->size); --i) { carry = FALSE; pat = &glob->pattern[i]; switch (pat->type) { @@ -480,38 +491,30 @@ int glob_next_url(char **globbed, URLGlob *glob) } for(j = 0; j < glob->size; ++j) { - if(!(j&1)) { /* every other term (j even) is a literal */ - lit = glob->literal[j/2]; - len = snprintf(buf, buflen, "%s", lit); - buf += len; - buflen -= len; - } - else { /* the rest (i odd) are patterns */ - pat = &glob->pattern[j/2]; - switch(pat->type) { - case UPTSet: - if(pat->content.Set.elements) { - len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]); - snprintf(buf, buflen, "%s", - pat->content.Set.elements[pat->content.Set.ptr_s]); - buf += len; - buflen -= len; - } - break; - case UPTCharRange: - *buf++ = pat->content.CharRange.ptr_c; - break; - case UPTNumRange: - len = snprintf(buf, buflen, "%0*d", - pat->content.NumRange.padlength, - pat->content.NumRange.ptr_n); + pat = &glob->pattern[j]; + switch(pat->type) { + case UPTSet: + if(pat->content.Set.elements) { + len = strlen(pat->content.Set.elements[pat->content.Set.ptr_s]); + snprintf(buf, buflen, "%s", + pat->content.Set.elements[pat->content.Set.ptr_s]); buf += len; buflen -= len; - break; - default: - printf("internal error: invalid pattern type (%d)\n", (int)pat->type); - return CURLE_FAILED_INIT; } + break; + case UPTCharRange: + *buf++ = pat->content.CharRange.ptr_c; + break; + case UPTNumRange: + len = snprintf(buf, buflen, "%0*ld", + pat->content.NumRange.padlength, + pat->content.NumRange.ptr_n); + buf += len; + buflen -= len; + break; + default: + printf("internal error: invalid pattern type (%d)\n", (int)pat->type); + return CURLE_FAILED_INIT; } } *buf = '\0'; @@ -549,34 +552,44 @@ int glob_match_url(char **result, char *filename, URLGlob *glob) unsigned long i; char *ptr = filename; unsigned long num = strtoul(&filename[1], &filename, 10); - i = num - 1UL; + URLPattern *pat =NULL; + + if(num < glob->size) { + num--; /* make it zero based */ + /* find the correct glob entry */ + for(i=0; i<glob->size; i++) { + if(glob->pattern[i].globindex == (int)num) { + pat = &glob->pattern[i]; + break; + } + } + } - if(num && (i <= glob->size / 2)) { - URLPattern pat = glob->pattern[i]; - switch (pat.type) { + if(pat) { + switch (pat->type) { case UPTSet: - if(pat.content.Set.elements) { - appendthis = pat.content.Set.elements[pat.content.Set.ptr_s]; + if(pat->content.Set.elements) { + appendthis = pat->content.Set.elements[pat->content.Set.ptr_s]; appendlen = - strlen(pat.content.Set.elements[pat.content.Set.ptr_s]); + strlen(pat->content.Set.elements[pat->content.Set.ptr_s]); } break; case UPTCharRange: - numbuf[0] = pat.content.CharRange.ptr_c; + numbuf[0] = pat->content.CharRange.ptr_c; numbuf[1] = 0; appendthis = numbuf; appendlen = 1; break; case UPTNumRange: snprintf(numbuf, sizeof(numbuf), "%0*d", - pat.content.NumRange.padlength, - pat.content.NumRange.ptr_n); + pat->content.NumRange.padlength, + pat->content.NumRange.ptr_n); appendthis = numbuf; appendlen = strlen(numbuf); break; default: - printf("internal error: invalid pattern type (%d)\n", - (int)pat.type); + fprintf(stderr, "internal error: invalid pattern type (%d)\n", + (int)pat->type); Curl_safefree(target); return CURLE_FAILED_INIT; } diff --git a/src/tool_urlglob.h b/src/tool_urlglob.h index 9c0813750..e1e9c6384 100644 --- a/src/tool_urlglob.h +++ b/src/tool_urlglob.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -31,11 +31,13 @@ typedef enum { typedef struct { URLPatternType type; + int globindex; /* the number of this particular glob or -1 if not used + within {} or [] */ union { struct { char **elements; - short size; - short ptr_s; + int size; + int ptr_s; } Set; struct { char min_c; @@ -44,21 +46,20 @@ typedef struct { int step; } CharRange; struct { - int min_n; - int max_n; - short padlength; - int ptr_n; - int step; + unsigned long min_n; + unsigned long max_n; + int padlength; + unsigned long ptr_n; + unsigned long step; } NumRange ; } content; } URLPattern; /* the total number of globs supported */ -#define GLOB_PATTERN_NUM 9 +#define GLOB_PATTERN_NUM 100 typedef struct { - char *literal[10]; - URLPattern pattern[GLOB_PATTERN_NUM+1]; + URLPattern pattern[GLOB_PATTERN_NUM]; size_t size; size_t urllen; char *glob_buffer; @@ -66,7 +67,7 @@ typedef struct { char errormsg[80]; /* error message buffer */ } URLGlob; -int glob_url(URLGlob**, char*, int *, FILE *); +int glob_url(URLGlob**, char*, unsigned long *, FILE *); int glob_next_url(char **, URLGlob *); int glob_match_url(char **, char*, URLGlob *); void glob_cleanup(URLGlob* glob); |