tool_urlglob.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 #include "tool_setup.h"
23 
24 #define ENABLE_CURLX_PRINTF
25 /* use our own printf() functions */
26 #include "curlx.h"
27 #include "tool_cfgable.h"
28 #include "tool_doswin.h"
29 #include "tool_urlglob.h"
30 #include "tool_vms.h"
31 
32 #include "memdebug.h" /* keep this as LAST include */
33 
34 #define GLOBERROR(string, column, code) \
35  glob->error = string, glob->pos = column, code
36 
37 void glob_cleanup(URLGlob* glob);
38 
39 static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
40 {
41  URLPattern *pat = &glob->pattern[glob->size];
42  pat->type = UPTSet;
43  pat->content.Set.size = 1;
44  pat->content.Set.ptr_s = 0;
45  pat->globindex = -1;
46 
47  pat->content.Set.elements = malloc(sizeof(char *));
48 
49  if(!pat->content.Set.elements)
50  return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
51 
52  pat->content.Set.elements[0] = malloc(len + 1);
53  if(!pat->content.Set.elements[0])
54  return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
55 
56  memcpy(pat->content.Set.elements[0], fixed, len);
57  pat->content.Set.elements[0][len] = 0;
58 
59  return CURLE_OK;
60 }
61 
62 /* multiply
63  *
64  * Multiplies and checks for overflow.
65  */
66 static int multiply(unsigned long *amount, long with)
67 {
68  unsigned long sum = *amount * with;
69  if(!with) {
70  *amount = 0;
71  return 0;
72  }
73  if(sum/with != *amount)
74  return 1; /* didn't fit, bail out */
75  *amount = sum;
76  return 0;
77 }
78 
79 static CURLcode glob_set(URLGlob *glob, char **patternp,
80  size_t *posp, unsigned long *amount,
81  int globindex)
82 {
83  /* processes a set expression with the point behind the opening '{'
84  ','-separated elements are collected until the next closing '}'
85  */
86  URLPattern *pat;
87  bool done = FALSE;
88  char *buf = glob->glob_buffer;
89  char *pattern = *patternp;
90  char *opattern = pattern;
91  size_t opos = *posp-1;
92 
93  pat = &glob->pattern[glob->size];
94  /* patterns 0,1,2,... correspond to size=1,3,5,... */
95  pat->type = UPTSet;
96  pat->content.Set.size = 0;
97  pat->content.Set.ptr_s = 0;
98  pat->content.Set.elements = NULL;
99  pat->globindex = globindex;
100 
101  while(!done) {
102  switch (*pattern) {
103  case '\0': /* URL ended while set was still open */
104  return GLOBERROR("unmatched brace", opos, CURLE_URL_MALFORMAT);
105 
106  case '{':
107  case '[': /* no nested expressions at this time */
108  return GLOBERROR("nested brace", *posp, CURLE_URL_MALFORMAT);
109 
110  case '}': /* set element completed */
111  if(opattern == pattern)
112  return GLOBERROR("empty string within braces", *posp,
114 
115  /* add 1 to size since it'll be incremented below */
116  if(multiply(amount, pat->content.Set.size + 1))
117  return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
118 
119  /* fall-through */
120  case ',':
121 
122  *buf = '\0';
123  if(pat->content.Set.elements) {
124  char **new_arr = realloc(pat->content.Set.elements,
125  (pat->content.Set.size + 1) * sizeof(char *));
126  if(!new_arr)
127  return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
128 
129  pat->content.Set.elements = new_arr;
130  }
131  else
132  pat->content.Set.elements = malloc(sizeof(char *));
133 
134  if(!pat->content.Set.elements)
135  return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
136 
137  pat->content.Set.elements[pat->content.Set.size] =
138  strdup(glob->glob_buffer);
139  if(!pat->content.Set.elements[pat->content.Set.size])
140  return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
141  ++pat->content.Set.size;
142 
143  if(*pattern == '}') {
144  pattern++; /* pass the closing brace */
145  done = TRUE;
146  continue;
147  }
148 
149  buf = glob->glob_buffer;
150  ++pattern;
151  ++(*posp);
152  break;
153 
154  case ']': /* illegal closing bracket */
155  return GLOBERROR("unexpected close bracket", *posp, CURLE_URL_MALFORMAT);
156 
157  case '\\': /* escaped character, skip '\' */
158  if(pattern[1]) {
159  ++pattern;
160  ++(*posp);
161  }
162  /* intentional fallthrough */
163  default:
164  *buf++ = *pattern++; /* copy character to set element */
165  ++(*posp);
166  }
167  }
168 
169  *patternp = pattern; /* return with the new position */
170  return CURLE_OK;
171 }
172 
173 static CURLcode glob_range(URLGlob *glob, char **patternp,
174  size_t *posp, unsigned long *amount,
175  int globindex)
176 {
177  /* processes a range expression with the point behind the opening '['
178  - char range: e.g. "a-z]", "B-Q]"
179  - num range: e.g. "0-9]", "17-2000]"
180  - num range with leading zeros: e.g. "001-999]"
181  expression is checked for well-formedness and collected until the next ']'
182  */
183  URLPattern *pat;
184  int rc;
185  char *pattern = *patternp;
186  char *c;
187 
188  pat = &glob->pattern[glob->size];
189  pat->globindex = globindex;
190 
191  if(ISALPHA(*pattern)) {
192  /* character range detected */
193  char min_c;
194  char max_c;
195  char end_c;
196  unsigned long step = 1;
197 
198  pat->type = UPTCharRange;
199 
200  rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
201 
202  if(rc == 3) {
203  if(end_c == ':') {
204  char *endp;
205  errno = 0;
206  step = strtoul(&pattern[4], &endp, 10);
207  if(errno || &pattern[4] == endp || *endp != ']')
208  step = 0;
209  else
210  pattern = endp + 1;
211  }
212  else if(end_c != ']')
213  /* then this is wrong */
214  rc = 0;
215  else
216  /* end_c == ']' */
217  pattern += 4;
218  }
219 
220  *posp += (pattern - *patternp);
221 
222  if(rc != 3 || !step || step > (unsigned)INT_MAX ||
223  (min_c == max_c && step != 1) ||
224  (min_c != max_c && (min_c > max_c || step > (unsigned)(max_c - min_c) ||
225  (max_c - min_c) > ('z' - 'a'))))
226  /* the pattern is not well-formed */
227  return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
228 
229  /* if there was a ":[num]" thing, use that as step or else use 1 */
230  pat->content.CharRange.step = (int)step;
231  pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
232  pat->content.CharRange.max_c = max_c;
233 
234  if(multiply(amount, ((pat->content.CharRange.max_c -
235  pat->content.CharRange.min_c) /
236  pat->content.CharRange.step + 1)))
237  return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
238  }
239  else if(ISDIGIT(*pattern)) {
240  /* numeric range detected */
241  unsigned long min_n;
242  unsigned long max_n = 0;
243  unsigned long step_n = 0;
244  char *endp;
245 
246  pat->type = UPTNumRange;
247  pat->content.NumRange.padlength = 0;
248 
249  if(*pattern == '0') {
250  /* leading zero specified, count them! */
251  c = pattern;
252  while(ISDIGIT(*c)) {
253  c++;
254  ++pat->content.NumRange.padlength; /* padding length is set for all
255  instances of this pattern */
256  }
257  }
258 
259  errno = 0;
260  min_n = strtoul(pattern, &endp, 10);
261  if(errno || (endp == pattern))
262  endp = NULL;
263  else {
264  if(*endp != '-')
265  endp = NULL;
266  else {
267  pattern = endp + 1;
268  while(*pattern && ISBLANK(*pattern))
269  pattern++;
270  if(!ISDIGIT(*pattern)) {
271  endp = NULL;
272  goto fail;
273  }
274  errno = 0;
275  max_n = strtoul(pattern, &endp, 10);
276  if(errno)
277  /* overflow */
278  endp = NULL;
279  else if(*endp == ':') {
280  pattern = endp + 1;
281  errno = 0;
282  step_n = strtoul(pattern, &endp, 10);
283  if(errno)
284  /* over/underflow situation */
285  endp = NULL;
286  }
287  else
288  step_n = 1;
289  if(endp && (*endp == ']')) {
290  pattern = endp + 1;
291  }
292  else
293  endp = NULL;
294  }
295  }
296 
297  fail:
298  *posp += (pattern - *patternp);
299 
300  if(!endp || !step_n ||
301  (min_n == max_n && step_n != 1) ||
302  (min_n != max_n && (min_n > max_n || step_n > (max_n - min_n))))
303  /* the pattern is not well-formed */
304  return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
305 
306  /* typecasting to ints are fine here since we make sure above that we
307  are within 31 bits */
308  pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
309  pat->content.NumRange.max_n = max_n;
310  pat->content.NumRange.step = step_n;
311 
312  if(multiply(amount, ((pat->content.NumRange.max_n -
313  pat->content.NumRange.min_n) /
314  pat->content.NumRange.step + 1)))
315  return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
316  }
317  else
318  return GLOBERROR("bad range specification", *posp, CURLE_URL_MALFORMAT);
319 
320  *patternp = pattern;
321  return CURLE_OK;
322 }
323 
324 static bool peek_ipv6(const char *str, size_t *skip)
325 {
326  /*
327  * Scan for a potential IPv6 literal.
328  * - Valid globs contain a hyphen and <= 1 colon.
329  * - IPv6 literals contain no hyphens and >= 2 colons.
330  */
331  size_t i = 0;
332  size_t colons = 0;
333  if(str[i++] != '[') {
334  return FALSE;
335  }
336  for(;;) {
337  const char c = str[i++];
338  if(ISALNUM(c) || c == '.' || c == '%') {
339  /* ok */
340  }
341  else if(c == ':') {
342  colons++;
343  }
344  else if(c == ']') {
345  *skip = i;
346  return colons >= 2 ? TRUE : FALSE;
347  }
348  else {
349  return FALSE;
350  }
351  }
352 }
353 
354 static CURLcode glob_parse(URLGlob *glob, char *pattern,
355  size_t pos, unsigned long *amount)
356 {
357  /* processes a literal string component of a URL
358  special characters '{' and '[' branch to set/range processing functions
359  */
361  int globindex = 0; /* count "actual" globs */
362 
363  *amount = 1;
364 
365  while(*pattern && !res) {
366  char *buf = glob->glob_buffer;
367  size_t sublen = 0;
368  while(*pattern && *pattern != '{') {
369  if(*pattern == '[') {
370  /* Skip over potential IPv6 literals. */
371  size_t skip;
372  if(peek_ipv6(pattern, &skip)) {
373  memcpy(buf, pattern, skip);
374  buf += skip;
375  pattern += skip;
376  sublen += skip;
377  continue;
378  }
379  break;
380  }
381  if(*pattern == '}' || *pattern == ']')
382  return GLOBERROR("unmatched close brace/bracket", pos,
384 
385  /* only allow \ to escape known "special letters" */
386  if(*pattern == '\\' &&
387  (*(pattern + 1) == '{' || *(pattern + 1) == '[' ||
388  *(pattern + 1) == '}' || *(pattern + 1) == ']') ) {
389 
390  /* escape character, skip '\' */
391  ++pattern;
392  ++pos;
393  }
394  *buf++ = *pattern++; /* copy character to literal */
395  ++pos;
396  sublen++;
397  }
398  if(sublen) {
399  /* we got a literal string, add it as a single-item list */
400  *buf = '\0';
401  res = glob_fixed(glob, glob->glob_buffer, sublen);
402  }
403  else {
404  switch (*pattern) {
405  case '\0': /* done */
406  break;
407 
408  case '{':
409  /* process set pattern */
410  pattern++;
411  pos++;
412  res = glob_set(glob, &pattern, &pos, amount, globindex++);
413  break;
414 
415  case '[':
416  /* process range pattern */
417  pattern++;
418  pos++;
419  res = glob_range(glob, &pattern, &pos, amount, globindex++);
420  break;
421  }
422  }
423 
424  if(++glob->size >= GLOB_PATTERN_NUM)
425  return GLOBERROR("too many globs", pos, CURLE_URL_MALFORMAT);
426  }
427  return res;
428 }
429 
430 CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum,
431  FILE *error)
432 {
433  /*
434  * We can deal with any-size, just make a buffer with the same length
435  * as the specified URL!
436  */
437  URLGlob *glob_expand;
438  unsigned long amount = 0;
439  char *glob_buffer;
440  CURLcode res;
441 
442  *glob = NULL;
443 
444  glob_buffer = malloc(strlen(url) + 1);
445  if(!glob_buffer)
446  return CURLE_OUT_OF_MEMORY;
447  glob_buffer[0] = 0;
448 
449  glob_expand = calloc(1, sizeof(URLGlob));
450  if(!glob_expand) {
451  Curl_safefree(glob_buffer);
452  return CURLE_OUT_OF_MEMORY;
453  }
454  glob_expand->urllen = strlen(url);
455  glob_expand->glob_buffer = glob_buffer;
456 
457  res = glob_parse(glob_expand, url, 1, &amount);
458  if(!res)
459  *urlnum = amount;
460  else {
461  if(error && glob_expand->error) {
462  char text[128];
463  const char *t;
464  if(glob_expand->pos) {
465  snprintf(text, sizeof(text), "%s in column %zu", glob_expand->error,
466  glob_expand->pos);
467  t = text;
468  }
469  else
470  t = glob_expand->error;
471 
472  /* send error description to the error-stream */
473  fprintf(error, "curl: (%d) [globbing] %s\n", res, t);
474  }
475  /* it failed, we cleanup */
476  glob_cleanup(glob_expand);
477  *urlnum = 1;
478  return res;
479  }
480 
481  *glob = glob_expand;
482  return CURLE_OK;
483 }
484 
486 {
487  size_t i;
488  int elem;
489 
490  for(i = 0; i < glob->size; i++) {
491  if((glob->pattern[i].type == UPTSet) &&
492  (glob->pattern[i].content.Set.elements)) {
493  for(elem = glob->pattern[i].content.Set.size - 1;
494  elem >= 0;
495  --elem) {
496  Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
497  }
498  Curl_safefree(glob->pattern[i].content.Set.elements);
499  }
500  }
501  Curl_safefree(glob->glob_buffer);
502  Curl_safefree(glob);
503 }
504 
505 CURLcode glob_next_url(char **globbed, URLGlob *glob)
506 {
507  URLPattern *pat;
508  size_t i;
509  size_t len;
510  size_t buflen = glob->urllen + 1;
511  char *buf = glob->glob_buffer;
512 
513  *globbed = NULL;
514 
515  if(!glob->beenhere)
516  glob->beenhere = 1;
517  else {
518  bool carry = TRUE;
519 
520  /* implement a counter over the index ranges of all patterns, starting
521  with the rightmost pattern */
522  for(i = 0; carry && (i < glob->size); i++) {
523  carry = FALSE;
524  pat = &glob->pattern[glob->size - 1 - i];
525  switch(pat->type) {
526  case UPTSet:
527  if((pat->content.Set.elements) &&
528  (++pat->content.Set.ptr_s == pat->content.Set.size)) {
529  pat->content.Set.ptr_s = 0;
530  carry = TRUE;
531  }
532  break;
533  case UPTCharRange:
534  pat->content.CharRange.ptr_c =
535  (char)(pat->content.CharRange.step +
536  (int)((unsigned char)pat->content.CharRange.ptr_c));
537  if(pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
538  pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
539  carry = TRUE;
540  }
541  break;
542  case UPTNumRange:
543  pat->content.NumRange.ptr_n += pat->content.NumRange.step;
544  if(pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
545  pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
546  carry = TRUE;
547  }
548  break;
549  default:
550  printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
551  return CURLE_FAILED_INIT;
552  }
553  }
554  if(carry) { /* first pattern ptr has run into overflow, done! */
555  /* TODO: verify if this should actally return CURLE_OK. */
556  return CURLE_OK; /* CURLE_OK to match previous behavior */
557  }
558  }
559 
560  for(i = 0; i < glob->size; ++i) {
561  pat = &glob->pattern[i];
562  switch(pat->type) {
563  case UPTSet:
564  if(pat->content.Set.elements) {
565  snprintf(buf, buflen, "%s",
566  pat->content.Set.elements[pat->content.Set.ptr_s]);
567  len = strlen(buf);
568  buf += len;
569  buflen -= len;
570  }
571  break;
572  case UPTCharRange:
573  if(buflen) {
574  *buf++ = pat->content.CharRange.ptr_c;
575  *buf = '\0';
576  buflen--;
577  }
578  break;
579  case UPTNumRange:
580  snprintf(buf, buflen, "%0*ld",
581  pat->content.NumRange.padlength,
582  pat->content.NumRange.ptr_n);
583  len = strlen(buf);
584  buf += len;
585  buflen -= len;
586  break;
587  default:
588  printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
589  return CURLE_FAILED_INIT;
590  }
591  }
592 
593  *globbed = strdup(glob->glob_buffer);
594  if(!*globbed)
595  return CURLE_OUT_OF_MEMORY;
596 
597  return CURLE_OK;
598 }
599 
600 CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
601 {
602  char *target;
603  size_t allocsize;
604  char numbuf[18];
605  char *appendthis = NULL;
606  size_t appendlen = 0;
607  size_t stringlen = 0;
608 
609  *result = NULL;
610 
611  /* We cannot use the glob_buffer for storage here since the filename may
612  * be longer than the URL we use. We allocate a good start size, then
613  * we need to realloc in case of need.
614  */
615  allocsize = strlen(filename) + 1; /* make it at least one byte to store the
616  trailing zero */
617  target = malloc(allocsize);
618  if(!target)
619  return CURLE_OUT_OF_MEMORY;
620 
621  while(*filename) {
622  if(*filename == '#' && ISDIGIT(filename[1])) {
623  unsigned long i;
624  char *ptr = filename;
625  unsigned long num = strtoul(&filename[1], &filename, 10);
626  URLPattern *pat = NULL;
627 
628  if(num < glob->size) {
629  num--; /* make it zero based */
630  /* find the correct glob entry */
631  for(i = 0; i<glob->size; i++) {
632  if(glob->pattern[i].globindex == (int)num) {
633  pat = &glob->pattern[i];
634  break;
635  }
636  }
637  }
638 
639  if(pat) {
640  switch(pat->type) {
641  case UPTSet:
642  if(pat->content.Set.elements) {
643  appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
644  appendlen =
645  strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
646  }
647  break;
648  case UPTCharRange:
649  numbuf[0] = pat->content.CharRange.ptr_c;
650  numbuf[1] = 0;
651  appendthis = numbuf;
652  appendlen = 1;
653  break;
654  case UPTNumRange:
655  snprintf(numbuf, sizeof(numbuf), "%0*lu",
656  pat->content.NumRange.padlength,
657  pat->content.NumRange.ptr_n);
658  appendthis = numbuf;
659  appendlen = strlen(numbuf);
660  break;
661  default:
662  fprintf(stderr, "internal error: invalid pattern type (%d)\n",
663  (int)pat->type);
664  Curl_safefree(target);
665  return CURLE_FAILED_INIT;
666  }
667  }
668  else {
669  /* #[num] out of range, use the #[num] in the output */
670  filename = ptr;
671  appendthis = filename++;
672  appendlen = 1;
673  }
674  }
675  else {
676  appendthis = filename++;
677  appendlen = 1;
678  }
679  if(appendlen + stringlen >= allocsize) {
680  char *newstr;
681  /* we append a single byte to allow for the trailing byte to be appended
682  at the end of this function outside the while() loop */
683  allocsize = (appendlen + stringlen) * 2;
684  newstr = realloc(target, allocsize + 1);
685  if(!newstr) {
686  Curl_safefree(target);
687  return CURLE_OUT_OF_MEMORY;
688  }
689  target = newstr;
690  }
691  memcpy(&target[stringlen], appendthis, appendlen);
692  stringlen += appendlen;
693  }
694  target[stringlen]= '\0';
695 
696 #if defined(MSDOS) || defined(WIN32)
697  {
698  char *sanitized;
699  SANITIZEcode sc = sanitize_file_name(&sanitized, target,
700  (SANITIZE_ALLOW_PATH |
701  SANITIZE_ALLOW_RESERVED));
702  Curl_safefree(target);
703  if(sc)
704  return CURLE_URL_MALFORMAT;
705  target = sanitized;
706  }
707 #endif /* MSDOS || WIN32 */
708 
709  *result = target;
710  return CURLE_OK;
711 }
#define ISALPHA(x)
CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
Definition: tool_urlglob.c:600
URLPattern pattern[GLOB_PATTERN_NUM]
Definition: tool_urlglob.h:62
struct URLPattern::@38::@39 Set
struct URLPattern::@38::@41 NumRange
size_t size
Definition: tool_urlglob.h:63
#define strdup(ptr)
Definition: curl_memory.h:122
UNITTEST_START char * ptr
Definition: unit1330.c:38
CURLcode
Definition: curl.h:454
#define GLOBERROR(string, column, code)
Definition: tool_urlglob.c:34
union URLPattern::@38 content
#define ISALNUM(x)
static int res
#define realloc(ptr, size)
Definition: curl_memory.h:128
#define ISBLANK(x)
#define malloc(size)
Definition: curl_memory.h:124
geometry_msgs::TransformStamped t
UNITTEST_START int result
Definition: unit1304.c:49
unsigned int i
Definition: unit1303.c:79
size_t urllen
Definition: tool_urlglob.h:64
size_t len
Definition: curl_sasl.c:55
char beenhere
Definition: tool_urlglob.h:66
static int multiply(unsigned long *amount, long with)
Definition: tool_urlglob.c:66
memcpy(filename, filename1, strlen(filename1))
const char * str
Definition: unit1398.c:33
#define FALSE
struct URLPattern::@38::@40 CharRange
void glob_cleanup(URLGlob *glob)
Definition: tool_urlglob.c:485
UNITTEST_START int rc
Definition: unit1301.c:31
URLPatternType type
Definition: tool_urlglob.h:33
#define printf
Definition: curl_printf.h:40
#define ISDIGIT(x)
#define fail(msg)
Definition: curlcheck.h:51
static CURLcode glob_set(URLGlob *glob, char **patternp, size_t *posp, unsigned long *amount, int globindex)
Definition: tool_urlglob.c:79
#define GLOB_PATTERN_NUM
Definition: tool_urlglob.h:59
static CURLcode glob_parse(URLGlob *glob, char *pattern, size_t pos, unsigned long *amount)
Definition: tool_urlglob.c:354
Definition: curl.h:455
size_t pos
Definition: tool_urlglob.h:68
const char * error
Definition: tool_urlglob.h:67
static CURLcode glob_range(URLGlob *glob, char **patternp, size_t *posp, unsigned long *amount, int globindex)
Definition: tool_urlglob.c:173
#define Curl_safefree(ptr)
Definition: memdebug.h:170
unsigned int step
static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
Definition: tool_urlglob.c:39
static bool peek_ipv6(const char *str, size_t *skip)
Definition: tool_urlglob.c:324
CURLcode glob_url(URLGlob **glob, char *url, unsigned long *urlnum, FILE *error)
Definition: tool_urlglob.c:430
char buf[3]
Definition: unit1398.c:32
CURLcode glob_next_url(char **globbed, URLGlob *glob)
Definition: tool_urlglob.c:505
size_t size
Definition: unit1302.c:52
#define fprintf
Definition: curl_printf.h:41
static void skip(const char **date)
Definition: parsedate.c:260
#define snprintf
Definition: curl_printf.h:42
#define TRUE
char * glob_buffer
Definition: tool_urlglob.h:65
#define calloc(nbelem, size)
Definition: curl_memory.h:126


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:16