Annotation of embedaddon/curl/src/tool_urlglob.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2020, 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: static CURLcode glob_fixed(URLGlob *glob, char *fixed, size_t len)
! 38: {
! 39: URLPattern *pat = &glob->pattern[glob->size];
! 40: pat->type = UPTSet;
! 41: pat->content.Set.size = 1;
! 42: pat->content.Set.ptr_s = 0;
! 43: pat->globindex = -1;
! 44:
! 45: pat->content.Set.elements = malloc(sizeof(char *));
! 46:
! 47: if(!pat->content.Set.elements)
! 48: return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
! 49:
! 50: pat->content.Set.elements[0] = malloc(len + 1);
! 51: if(!pat->content.Set.elements[0])
! 52: return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
! 53:
! 54: memcpy(pat->content.Set.elements[0], fixed, len);
! 55: pat->content.Set.elements[0][len] = 0;
! 56:
! 57: return CURLE_OK;
! 58: }
! 59:
! 60: /* multiply
! 61: *
! 62: * Multiplies and checks for overflow.
! 63: */
! 64: static int multiply(unsigned long *amount, long with)
! 65: {
! 66: unsigned long sum = *amount * with;
! 67: if(!with) {
! 68: *amount = 0;
! 69: return 0;
! 70: }
! 71: if(sum/with != *amount)
! 72: return 1; /* didn't fit, bail out */
! 73: *amount = sum;
! 74: return 0;
! 75: }
! 76:
! 77: static CURLcode glob_set(URLGlob *glob, char **patternp,
! 78: size_t *posp, unsigned long *amount,
! 79: int globindex)
! 80: {
! 81: /* processes a set expression with the point behind the opening '{'
! 82: ','-separated elements are collected until the next closing '}'
! 83: */
! 84: URLPattern *pat;
! 85: bool done = FALSE;
! 86: char *buf = glob->glob_buffer;
! 87: char *pattern = *patternp;
! 88: char *opattern = pattern;
! 89: size_t opos = *posp-1;
! 90:
! 91: pat = &glob->pattern[glob->size];
! 92: /* patterns 0,1,2,... correspond to size=1,3,5,... */
! 93: pat->type = UPTSet;
! 94: pat->content.Set.size = 0;
! 95: pat->content.Set.ptr_s = 0;
! 96: pat->content.Set.elements = NULL;
! 97: pat->globindex = globindex;
! 98:
! 99: while(!done) {
! 100: switch (*pattern) {
! 101: case '\0': /* URL ended while set was still open */
! 102: return GLOBERROR("unmatched brace", opos, CURLE_URL_MALFORMAT);
! 103:
! 104: case '{':
! 105: case '[': /* no nested expressions at this time */
! 106: return GLOBERROR("nested brace", *posp, CURLE_URL_MALFORMAT);
! 107:
! 108: case '}': /* set element completed */
! 109: if(opattern == pattern)
! 110: return GLOBERROR("empty string within braces", *posp,
! 111: CURLE_URL_MALFORMAT);
! 112:
! 113: /* add 1 to size since it'll be incremented below */
! 114: if(multiply(amount, pat->content.Set.size + 1))
! 115: return GLOBERROR("range overflow", 0, CURLE_URL_MALFORMAT);
! 116:
! 117: /* FALLTHROUGH */
! 118: case ',':
! 119:
! 120: *buf = '\0';
! 121: if(pat->content.Set.elements) {
! 122: char **new_arr = realloc(pat->content.Set.elements,
! 123: (pat->content.Set.size + 1) * sizeof(char *));
! 124: if(!new_arr)
! 125: return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
! 126:
! 127: pat->content.Set.elements = new_arr;
! 128: }
! 129: else
! 130: pat->content.Set.elements = malloc(sizeof(char *));
! 131:
! 132: if(!pat->content.Set.elements)
! 133: return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
! 134:
! 135: pat->content.Set.elements[pat->content.Set.size] =
! 136: strdup(glob->glob_buffer);
! 137: if(!pat->content.Set.elements[pat->content.Set.size])
! 138: return GLOBERROR("out of memory", 0, CURLE_OUT_OF_MEMORY);
! 139: ++pat->content.Set.size;
! 140:
! 141: if(*pattern == '}') {
! 142: pattern++; /* pass the closing brace */
! 143: done = TRUE;
! 144: continue;
! 145: }
! 146:
! 147: buf = glob->glob_buffer;
! 148: ++pattern;
! 149: ++(*posp);
! 150: break;
! 151:
! 152: case ']': /* illegal closing bracket */
! 153: return GLOBERROR("unexpected close bracket", *posp, CURLE_URL_MALFORMAT);
! 154:
! 155: case '\\': /* escaped character, skip '\' */
! 156: if(pattern[1]) {
! 157: ++pattern;
! 158: ++(*posp);
! 159: }
! 160: /* FALLTHROUGH */
! 161: default:
! 162: *buf++ = *pattern++; /* copy character to set element */
! 163: ++(*posp);
! 164: }
! 165: }
! 166:
! 167: *patternp = pattern; /* return with the new position */
! 168: return CURLE_OK;
! 169: }
! 170:
! 171: static CURLcode glob_range(URLGlob *glob, char **patternp,
! 172: size_t *posp, unsigned long *amount,
! 173: int globindex)
! 174: {
! 175: /* processes a range expression with the point behind the opening '['
! 176: - char range: e.g. "a-z]", "B-Q]"
! 177: - num range: e.g. "0-9]", "17-2000]"
! 178: - num range with leading zeros: e.g. "001-999]"
! 179: expression is checked for well-formedness and collected until the next ']'
! 180: */
! 181: URLPattern *pat;
! 182: int rc;
! 183: char *pattern = *patternp;
! 184: char *c;
! 185:
! 186: pat = &glob->pattern[glob->size];
! 187: pat->globindex = globindex;
! 188:
! 189: if(ISALPHA(*pattern)) {
! 190: /* character range detected */
! 191: char min_c;
! 192: char max_c;
! 193: char end_c;
! 194: unsigned long step = 1;
! 195:
! 196: pat->type = UPTCharRange;
! 197:
! 198: rc = sscanf(pattern, "%c-%c%c", &min_c, &max_c, &end_c);
! 199:
! 200: if(rc == 3) {
! 201: if(end_c == ':') {
! 202: char *endp;
! 203: errno = 0;
! 204: step = strtoul(&pattern[4], &endp, 10);
! 205: if(errno || &pattern[4] == endp || *endp != ']')
! 206: step = 0;
! 207: else
! 208: pattern = endp + 1;
! 209: }
! 210: else if(end_c != ']')
! 211: /* then this is wrong */
! 212: rc = 0;
! 213: else
! 214: /* end_c == ']' */
! 215: pattern += 4;
! 216: }
! 217:
! 218: *posp += (pattern - *patternp);
! 219:
! 220: if(rc != 3 || !step || step > (unsigned)INT_MAX ||
! 221: (min_c == max_c && step != 1) ||
! 222: (min_c != max_c && (min_c > max_c || step > (unsigned)(max_c - min_c) ||
! 223: (max_c - min_c) > ('z' - 'a'))))
! 224: /* the pattern is not well-formed */
! 225: return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
! 226:
! 227: /* if there was a ":[num]" thing, use that as step or else use 1 */
! 228: pat->content.CharRange.step = (int)step;
! 229: pat->content.CharRange.ptr_c = pat->content.CharRange.min_c = min_c;
! 230: pat->content.CharRange.max_c = max_c;
! 231:
! 232: if(multiply(amount, ((pat->content.CharRange.max_c -
! 233: pat->content.CharRange.min_c) /
! 234: pat->content.CharRange.step + 1)))
! 235: return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
! 236: }
! 237: else if(ISDIGIT(*pattern)) {
! 238: /* numeric range detected */
! 239: unsigned long min_n;
! 240: unsigned long max_n = 0;
! 241: unsigned long step_n = 0;
! 242: char *endp;
! 243:
! 244: pat->type = UPTNumRange;
! 245: pat->content.NumRange.padlength = 0;
! 246:
! 247: if(*pattern == '0') {
! 248: /* leading zero specified, count them! */
! 249: c = pattern;
! 250: while(ISDIGIT(*c)) {
! 251: c++;
! 252: ++pat->content.NumRange.padlength; /* padding length is set for all
! 253: instances of this pattern */
! 254: }
! 255: }
! 256:
! 257: errno = 0;
! 258: min_n = strtoul(pattern, &endp, 10);
! 259: if(errno || (endp == pattern))
! 260: endp = NULL;
! 261: else {
! 262: if(*endp != '-')
! 263: endp = NULL;
! 264: else {
! 265: pattern = endp + 1;
! 266: while(*pattern && ISBLANK(*pattern))
! 267: pattern++;
! 268: if(!ISDIGIT(*pattern)) {
! 269: endp = NULL;
! 270: goto fail;
! 271: }
! 272: errno = 0;
! 273: max_n = strtoul(pattern, &endp, 10);
! 274: if(errno)
! 275: /* overflow */
! 276: endp = NULL;
! 277: else if(*endp == ':') {
! 278: pattern = endp + 1;
! 279: errno = 0;
! 280: step_n = strtoul(pattern, &endp, 10);
! 281: if(errno)
! 282: /* over/underflow situation */
! 283: endp = NULL;
! 284: }
! 285: else
! 286: step_n = 1;
! 287: if(endp && (*endp == ']')) {
! 288: pattern = endp + 1;
! 289: }
! 290: else
! 291: endp = NULL;
! 292: }
! 293: }
! 294:
! 295: fail:
! 296: *posp += (pattern - *patternp);
! 297:
! 298: if(!endp || !step_n ||
! 299: (min_n == max_n && step_n != 1) ||
! 300: (min_n != max_n && (min_n > max_n || step_n > (max_n - min_n))))
! 301: /* the pattern is not well-formed */
! 302: return GLOBERROR("bad range", *posp, CURLE_URL_MALFORMAT);
! 303:
! 304: /* typecasting to ints are fine here since we make sure above that we
! 305: are within 31 bits */
! 306: pat->content.NumRange.ptr_n = pat->content.NumRange.min_n = min_n;
! 307: pat->content.NumRange.max_n = max_n;
! 308: pat->content.NumRange.step = step_n;
! 309:
! 310: if(multiply(amount, ((pat->content.NumRange.max_n -
! 311: pat->content.NumRange.min_n) /
! 312: pat->content.NumRange.step + 1)))
! 313: return GLOBERROR("range overflow", *posp, CURLE_URL_MALFORMAT);
! 314: }
! 315: else
! 316: return GLOBERROR("bad range specification", *posp, CURLE_URL_MALFORMAT);
! 317:
! 318: *patternp = pattern;
! 319: return CURLE_OK;
! 320: }
! 321:
! 322: static bool peek_ipv6(const char *str, size_t *skip)
! 323: {
! 324: /*
! 325: * Scan for a potential IPv6 literal.
! 326: * - Valid globs contain a hyphen and <= 1 colon.
! 327: * - IPv6 literals contain no hyphens and >= 2 colons.
! 328: */
! 329: size_t i = 0;
! 330: size_t colons = 0;
! 331: if(str[i++] != '[') {
! 332: return FALSE;
! 333: }
! 334: for(;;) {
! 335: const char c = str[i++];
! 336: if(ISALNUM(c) || c == '.' || c == '%') {
! 337: /* ok */
! 338: }
! 339: else if(c == ':') {
! 340: colons++;
! 341: }
! 342: else if(c == ']') {
! 343: *skip = i;
! 344: return colons >= 2 ? TRUE : FALSE;
! 345: }
! 346: else {
! 347: return FALSE;
! 348: }
! 349: }
! 350: }
! 351:
! 352: static CURLcode glob_parse(URLGlob *glob, char *pattern,
! 353: size_t pos, unsigned long *amount)
! 354: {
! 355: /* processes a literal string component of a URL
! 356: special characters '{' and '[' branch to set/range processing functions
! 357: */
! 358: CURLcode res = CURLE_OK;
! 359: int globindex = 0; /* count "actual" globs */
! 360:
! 361: *amount = 1;
! 362:
! 363: while(*pattern && !res) {
! 364: char *buf = glob->glob_buffer;
! 365: size_t sublen = 0;
! 366: while(*pattern && *pattern != '{') {
! 367: if(*pattern == '[') {
! 368: /* skip over IPv6 literals and [] */
! 369: size_t skip = 0;
! 370: if(!peek_ipv6(pattern, &skip) && (pattern[1] == ']'))
! 371: skip = 2;
! 372: if(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,
! 383: CURLE_URL_MALFORMAT);
! 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[512];
! 463: const char *t;
! 464: if(glob_expand->pos) {
! 465: msnprintf(text, sizeof(text), "%s in URL position %zu:\n%s\n%*s^",
! 466: glob_expand->error,
! 467: glob_expand->pos, url, glob_expand->pos - 1, " ");
! 468: t = text;
! 469: }
! 470: else
! 471: t = glob_expand->error;
! 472:
! 473: /* send error description to the error-stream */
! 474: fprintf(error, "curl: (%d) %s\n", res, t);
! 475: }
! 476: /* it failed, we cleanup */
! 477: glob_cleanup(glob_expand);
! 478: *urlnum = 1;
! 479: return res;
! 480: }
! 481:
! 482: *glob = glob_expand;
! 483: return CURLE_OK;
! 484: }
! 485:
! 486: void glob_cleanup(URLGlob* glob)
! 487: {
! 488: size_t i;
! 489: int elem;
! 490:
! 491: if(!glob)
! 492: return;
! 493:
! 494: for(i = 0; i < glob->size; i++) {
! 495: if((glob->pattern[i].type == UPTSet) &&
! 496: (glob->pattern[i].content.Set.elements)) {
! 497: for(elem = glob->pattern[i].content.Set.size - 1;
! 498: elem >= 0;
! 499: --elem) {
! 500: Curl_safefree(glob->pattern[i].content.Set.elements[elem]);
! 501: }
! 502: Curl_safefree(glob->pattern[i].content.Set.elements);
! 503: }
! 504: }
! 505: Curl_safefree(glob->glob_buffer);
! 506: Curl_safefree(glob);
! 507: }
! 508:
! 509: CURLcode glob_next_url(char **globbed, URLGlob *glob)
! 510: {
! 511: URLPattern *pat;
! 512: size_t i;
! 513: size_t len;
! 514: size_t buflen = glob->urllen + 1;
! 515: char *buf = glob->glob_buffer;
! 516:
! 517: *globbed = NULL;
! 518:
! 519: if(!glob->beenhere)
! 520: glob->beenhere = 1;
! 521: else {
! 522: bool carry = TRUE;
! 523:
! 524: /* implement a counter over the index ranges of all patterns, starting
! 525: with the rightmost pattern */
! 526: for(i = 0; carry && (i < glob->size); i++) {
! 527: carry = FALSE;
! 528: pat = &glob->pattern[glob->size - 1 - i];
! 529: switch(pat->type) {
! 530: case UPTSet:
! 531: if((pat->content.Set.elements) &&
! 532: (++pat->content.Set.ptr_s == pat->content.Set.size)) {
! 533: pat->content.Set.ptr_s = 0;
! 534: carry = TRUE;
! 535: }
! 536: break;
! 537: case UPTCharRange:
! 538: pat->content.CharRange.ptr_c =
! 539: (char)(pat->content.CharRange.step +
! 540: (int)((unsigned char)pat->content.CharRange.ptr_c));
! 541: if(pat->content.CharRange.ptr_c > pat->content.CharRange.max_c) {
! 542: pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
! 543: carry = TRUE;
! 544: }
! 545: break;
! 546: case UPTNumRange:
! 547: pat->content.NumRange.ptr_n += pat->content.NumRange.step;
! 548: if(pat->content.NumRange.ptr_n > pat->content.NumRange.max_n) {
! 549: pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
! 550: carry = TRUE;
! 551: }
! 552: break;
! 553: default:
! 554: printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
! 555: return CURLE_FAILED_INIT;
! 556: }
! 557: }
! 558: if(carry) { /* first pattern ptr has run into overflow, done! */
! 559: return CURLE_OK;
! 560: }
! 561: }
! 562:
! 563: for(i = 0; i < glob->size; ++i) {
! 564: pat = &glob->pattern[i];
! 565: switch(pat->type) {
! 566: case UPTSet:
! 567: if(pat->content.Set.elements) {
! 568: msnprintf(buf, buflen, "%s",
! 569: pat->content.Set.elements[pat->content.Set.ptr_s]);
! 570: len = strlen(buf);
! 571: buf += len;
! 572: buflen -= len;
! 573: }
! 574: break;
! 575: case UPTCharRange:
! 576: if(buflen) {
! 577: *buf++ = pat->content.CharRange.ptr_c;
! 578: *buf = '\0';
! 579: buflen--;
! 580: }
! 581: break;
! 582: case UPTNumRange:
! 583: msnprintf(buf, buflen, "%0*lu",
! 584: pat->content.NumRange.padlength,
! 585: pat->content.NumRange.ptr_n);
! 586: len = strlen(buf);
! 587: buf += len;
! 588: buflen -= len;
! 589: break;
! 590: default:
! 591: printf("internal error: invalid pattern type (%d)\n", (int)pat->type);
! 592: return CURLE_FAILED_INIT;
! 593: }
! 594: }
! 595:
! 596: *globbed = strdup(glob->glob_buffer);
! 597: if(!*globbed)
! 598: return CURLE_OUT_OF_MEMORY;
! 599:
! 600: return CURLE_OK;
! 601: }
! 602:
! 603: CURLcode glob_match_url(char **result, char *filename, URLGlob *glob)
! 604: {
! 605: char *target;
! 606: size_t allocsize;
! 607: char numbuf[18];
! 608: char *appendthis = (char *)"";
! 609: size_t appendlen = 0;
! 610: size_t stringlen = 0;
! 611:
! 612: *result = NULL;
! 613:
! 614: /* We cannot use the glob_buffer for storage here since the filename may
! 615: * be longer than the URL we use. We allocate a good start size, then
! 616: * we need to realloc in case of need.
! 617: */
! 618: allocsize = strlen(filename) + 1; /* make it at least one byte to store the
! 619: trailing zero */
! 620: target = malloc(allocsize);
! 621: if(!target)
! 622: return CURLE_OUT_OF_MEMORY;
! 623:
! 624: while(*filename) {
! 625: if(*filename == '#' && ISDIGIT(filename[1])) {
! 626: char *ptr = filename;
! 627: unsigned long num = strtoul(&filename[1], &filename, 10);
! 628: URLPattern *pat = NULL;
! 629:
! 630: if(num && (num < glob->size)) {
! 631: unsigned long i;
! 632: num--; /* make it zero based */
! 633: /* find the correct glob entry */
! 634: for(i = 0; i<glob->size; i++) {
! 635: if(glob->pattern[i].globindex == (int)num) {
! 636: pat = &glob->pattern[i];
! 637: break;
! 638: }
! 639: }
! 640: }
! 641:
! 642: if(pat) {
! 643: switch(pat->type) {
! 644: case UPTSet:
! 645: if(pat->content.Set.elements) {
! 646: appendthis = pat->content.Set.elements[pat->content.Set.ptr_s];
! 647: appendlen =
! 648: strlen(pat->content.Set.elements[pat->content.Set.ptr_s]);
! 649: }
! 650: break;
! 651: case UPTCharRange:
! 652: numbuf[0] = pat->content.CharRange.ptr_c;
! 653: numbuf[1] = 0;
! 654: appendthis = numbuf;
! 655: appendlen = 1;
! 656: break;
! 657: case UPTNumRange:
! 658: msnprintf(numbuf, sizeof(numbuf), "%0*lu",
! 659: pat->content.NumRange.padlength,
! 660: pat->content.NumRange.ptr_n);
! 661: appendthis = numbuf;
! 662: appendlen = strlen(numbuf);
! 663: break;
! 664: default:
! 665: fprintf(stderr, "internal error: invalid pattern type (%d)\n",
! 666: (int)pat->type);
! 667: Curl_safefree(target);
! 668: return CURLE_FAILED_INIT;
! 669: }
! 670: }
! 671: else {
! 672: /* #[num] out of range, use the #[num] in the output */
! 673: filename = ptr;
! 674: appendthis = filename++;
! 675: appendlen = 1;
! 676: }
! 677: }
! 678: else {
! 679: appendthis = filename++;
! 680: appendlen = 1;
! 681: }
! 682: if(appendlen + stringlen >= allocsize) {
! 683: char *newstr;
! 684: /* we append a single byte to allow for the trailing byte to be appended
! 685: at the end of this function outside the while() loop */
! 686: allocsize = (appendlen + stringlen) * 2;
! 687: newstr = realloc(target, allocsize + 1);
! 688: if(!newstr) {
! 689: Curl_safefree(target);
! 690: return CURLE_OUT_OF_MEMORY;
! 691: }
! 692: target = newstr;
! 693: }
! 694: memcpy(&target[stringlen], appendthis, appendlen);
! 695: stringlen += appendlen;
! 696: }
! 697: target[stringlen]= '\0';
! 698:
! 699: #if defined(MSDOS) || defined(WIN32)
! 700: {
! 701: char *sanitized;
! 702: SANITIZEcode sc = sanitize_file_name(&sanitized, target,
! 703: (SANITIZE_ALLOW_PATH |
! 704: SANITIZE_ALLOW_RESERVED));
! 705: Curl_safefree(target);
! 706: if(sc)
! 707: return CURLE_URL_MALFORMAT;
! 708: target = sanitized;
! 709: }
! 710: #endif /* MSDOS || WIN32 */
! 711:
! 712: *result = target;
! 713: return CURLE_OK;
! 714: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>