diff options
-rw-r--r-- | src/tool_operate.c | 15 | ||||
-rw-r--r-- | src/tool_urlglob.c | 473 | ||||
-rw-r--r-- | src/tool_urlglob.h | 25 | ||||
-rw-r--r-- | tests/data/Makefile.am | 2 | ||||
-rw-r--r-- | tests/data/test1234 | 32 | ||||
-rw-r--r-- | tests/data/test1235 | 94 | ||||
-rw-r--r-- | tests/data/test87 | 36 |
7 files changed, 420 insertions, 257 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); diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am index 0d5c29d88..f661b7103 100644 --- a/tests/data/Makefile.am +++ b/tests/data/Makefile.am @@ -93,7 +93,7 @@ test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 \ test1208 test1209 test1210 test1211 test1212 test1213 test1214 test1215 \ test1216 test1217 test1218 test1219 \ test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 \ -test1228 test1229 test1230 test1231 test1232 test1233 \ +test1228 test1229 test1230 test1231 test1232 test1233 test1234 test1235 \ \ test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 \ test1308 test1309 test1310 test1311 test1312 test1313 test1314 test1315 \ diff --git a/tests/data/test1234 b/tests/data/test1234 new file mode 100644 index 000000000..9d7a79fc4 --- /dev/null +++ b/tests/data/test1234 @@ -0,0 +1,32 @@ +<testcase> +<info> +<keywords> +{} list +FAILURE +</keywords> +</info> +# Server-side +<reply> +</reply> + +# Client-side +<client> +<server> +none +</server> + <name> +abusing {}-globbing + </name> + <command> +"%HOSTIP:%HTTPPORT/1234[0-1]{" "%HOSTIP:%HTTPPORT/{}{}{}{" +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +# 3 == CURLE_URL_MALFORMAT +<errorcode> +3 +</errorcode> +</verify> +</testcase> diff --git a/tests/data/test1235 b/tests/data/test1235 new file mode 100644 index 000000000..6c2a6a966 --- /dev/null +++ b/tests/data/test1235 @@ -0,0 +1,94 @@ +<testcase> +<info> +<keywords> +HTTP +HTTP GET +{} list +</keywords> +</info> +# Server-side +<reply> +<data1> +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 15
+
+the number one +</data1> +<data2> +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 16
+
+two is nice too +</data2> +</reply> + +# Client-side +<client> +<server> +http +</server> + <name> +multiple requests using {}{} in the URL + </name> + <command> +"%HOSTIP:%HTTPPORT/{1235,1235}{0001,0002}" +</command> +</client> + +# Verify data after the test has been "shot" +<verify> +<strip> +^User-Agent:.* +</strip> +<protocol> +GET /12350001 HTTP/1.1
+User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /12350002 HTTP/1.1
+User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /12350001 HTTP/1.1
+User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+GET /12350002 HTTP/1.1
+User-Agent: curl/7.8.1-pre3 (sparc-sun-solaris2.7) libcurl 7.8.1-pre3 (OpenSSL 0.9.6a) (krb4 enabled)
+Host: %HOSTIP:%HTTPPORT
+Accept: */*
+
+</protocol> +<stdout> +--_curl_--%HOSTIP:%HTTPPORT/12350001 +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 15
+
+the number one +--_curl_--%HOSTIP:%HTTPPORT/12350002 +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 16
+
+two is nice too +--_curl_--%HOSTIP:%HTTPPORT/12350001 +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 15
+
+the number one +--_curl_--%HOSTIP:%HTTPPORT/12350002 +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 16
+
+two is nice too +</stdout> +</verify> +</testcase> diff --git a/tests/data/test87 b/tests/data/test87 index 40b274b2e..4e436791e 100644 --- a/tests/data/test87 +++ b/tests/data/test87 @@ -8,29 +8,51 @@ FAILURE # # Server-side <reply> +<data1> +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 15
+
+the number one +</data1> +<data2> +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 16
+
+two is nice too +</data2> + </reply> # # Client-side <client> <server> -none +http </server> <features> http </features> <name> -urlglob with bad -o #[num] usage +urlglob with out of range -o #[num] usage </name> <command option="no-output"> -"http://%HOSTIP:%HTTPPORT/[870001-870003]" -o "log/dumpit#2.dump" +"http://%HOSTIP:%HTTPPORT/[870001-870002]" -o "log/dumpit#2.dump" </command> </client> # -# Verify data after the test has been "shot" +# Verify data after the test has been "shot". Note that the command line +# will write both responses into the same file name so only the second +# survives +# <verify> -<errorcode> -2 -</errorcode> +<file name="log/dumpit#2.dump" [mode="text"]> +HTTP/1.1 200 OK
+Funny-head: yesyes
+Content-Length: 16
+
+two is nice too +</file> </verify> </testcase> |