Annotation of embedaddon/curl/lib/ftplistparser.c, revision 1.1
1.1 ! misho 1: /***************************************************************************
! 2: * _ _ ____ _
! 3: * Project ___| | | | _ \| |
! 4: * / __| | | | |_) | |
! 5: * | (__| |_| | _ <| |___
! 6: * \___|\___/|_| \_\_____|
! 7: *
! 8: * Copyright (C) 1998 - 2019, 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:
! 23: /**
! 24: * Now implemented:
! 25: *
! 26: * 1) Unix version 1
! 27: * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
! 28: * 2) Unix version 2
! 29: * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
! 30: * 3) Unix version 3
! 31: * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
! 32: * 4) Unix symlink
! 33: * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
! 34: * 5) DOS style
! 35: * 01-29-97 11:32PM <DIR> prog
! 36: */
! 37:
! 38: #include "curl_setup.h"
! 39:
! 40: #ifndef CURL_DISABLE_FTP
! 41:
! 42: #include <curl/curl.h>
! 43:
! 44: #include "urldata.h"
! 45: #include "fileinfo.h"
! 46: #include "llist.h"
! 47: #include "strtoofft.h"
! 48: #include "ftp.h"
! 49: #include "ftplistparser.h"
! 50: #include "curl_fnmatch.h"
! 51: #include "curl_memory.h"
! 52: #include "multiif.h"
! 53: /* The last #include file should be: */
! 54: #include "memdebug.h"
! 55:
! 56: /* allocs buffer which will contain one line of LIST command response */
! 57: #define FTP_BUFFER_ALLOCSIZE 160
! 58:
! 59: typedef enum {
! 60: PL_UNIX_TOTALSIZE = 0,
! 61: PL_UNIX_FILETYPE,
! 62: PL_UNIX_PERMISSION,
! 63: PL_UNIX_HLINKS,
! 64: PL_UNIX_USER,
! 65: PL_UNIX_GROUP,
! 66: PL_UNIX_SIZE,
! 67: PL_UNIX_TIME,
! 68: PL_UNIX_FILENAME,
! 69: PL_UNIX_SYMLINK
! 70: } pl_unix_mainstate;
! 71:
! 72: typedef union {
! 73: enum {
! 74: PL_UNIX_TOTALSIZE_INIT = 0,
! 75: PL_UNIX_TOTALSIZE_READING
! 76: } total_dirsize;
! 77:
! 78: enum {
! 79: PL_UNIX_HLINKS_PRESPACE = 0,
! 80: PL_UNIX_HLINKS_NUMBER
! 81: } hlinks;
! 82:
! 83: enum {
! 84: PL_UNIX_USER_PRESPACE = 0,
! 85: PL_UNIX_USER_PARSING
! 86: } user;
! 87:
! 88: enum {
! 89: PL_UNIX_GROUP_PRESPACE = 0,
! 90: PL_UNIX_GROUP_NAME
! 91: } group;
! 92:
! 93: enum {
! 94: PL_UNIX_SIZE_PRESPACE = 0,
! 95: PL_UNIX_SIZE_NUMBER
! 96: } size;
! 97:
! 98: enum {
! 99: PL_UNIX_TIME_PREPART1 = 0,
! 100: PL_UNIX_TIME_PART1,
! 101: PL_UNIX_TIME_PREPART2,
! 102: PL_UNIX_TIME_PART2,
! 103: PL_UNIX_TIME_PREPART3,
! 104: PL_UNIX_TIME_PART3
! 105: } time;
! 106:
! 107: enum {
! 108: PL_UNIX_FILENAME_PRESPACE = 0,
! 109: PL_UNIX_FILENAME_NAME,
! 110: PL_UNIX_FILENAME_WINDOWSEOL
! 111: } filename;
! 112:
! 113: enum {
! 114: PL_UNIX_SYMLINK_PRESPACE = 0,
! 115: PL_UNIX_SYMLINK_NAME,
! 116: PL_UNIX_SYMLINK_PRETARGET1,
! 117: PL_UNIX_SYMLINK_PRETARGET2,
! 118: PL_UNIX_SYMLINK_PRETARGET3,
! 119: PL_UNIX_SYMLINK_PRETARGET4,
! 120: PL_UNIX_SYMLINK_TARGET,
! 121: PL_UNIX_SYMLINK_WINDOWSEOL
! 122: } symlink;
! 123: } pl_unix_substate;
! 124:
! 125: typedef enum {
! 126: PL_WINNT_DATE = 0,
! 127: PL_WINNT_TIME,
! 128: PL_WINNT_DIRORSIZE,
! 129: PL_WINNT_FILENAME
! 130: } pl_winNT_mainstate;
! 131:
! 132: typedef union {
! 133: enum {
! 134: PL_WINNT_TIME_PRESPACE = 0,
! 135: PL_WINNT_TIME_TIME
! 136: } time;
! 137: enum {
! 138: PL_WINNT_DIRORSIZE_PRESPACE = 0,
! 139: PL_WINNT_DIRORSIZE_CONTENT
! 140: } dirorsize;
! 141: enum {
! 142: PL_WINNT_FILENAME_PRESPACE = 0,
! 143: PL_WINNT_FILENAME_CONTENT,
! 144: PL_WINNT_FILENAME_WINEOL
! 145: } filename;
! 146: } pl_winNT_substate;
! 147:
! 148: /* This struct is used in wildcard downloading - for parsing LIST response */
! 149: struct ftp_parselist_data {
! 150: enum {
! 151: OS_TYPE_UNKNOWN = 0,
! 152: OS_TYPE_UNIX,
! 153: OS_TYPE_WIN_NT
! 154: } os_type;
! 155:
! 156: union {
! 157: struct {
! 158: pl_unix_mainstate main;
! 159: pl_unix_substate sub;
! 160: } UNIX;
! 161:
! 162: struct {
! 163: pl_winNT_mainstate main;
! 164: pl_winNT_substate sub;
! 165: } NT;
! 166: } state;
! 167:
! 168: CURLcode error;
! 169: struct fileinfo *file_data;
! 170: unsigned int item_length;
! 171: size_t item_offset;
! 172: struct {
! 173: size_t filename;
! 174: size_t user;
! 175: size_t group;
! 176: size_t time;
! 177: size_t perm;
! 178: size_t symlink_target;
! 179: } offsets;
! 180: };
! 181:
! 182: struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
! 183: {
! 184: return calloc(1, sizeof(struct ftp_parselist_data));
! 185: }
! 186:
! 187:
! 188: void Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp)
! 189: {
! 190: struct ftp_parselist_data *parser = *parserp;
! 191: if(parser)
! 192: Curl_fileinfo_cleanup(parser->file_data);
! 193: free(parser);
! 194: *parserp = NULL;
! 195: }
! 196:
! 197:
! 198: CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
! 199: {
! 200: return pl_data->error;
! 201: }
! 202:
! 203:
! 204: #define FTP_LP_MALFORMATED_PERM 0x01000000
! 205:
! 206: static int ftp_pl_get_permission(const char *str)
! 207: {
! 208: int permissions = 0;
! 209: /* USER */
! 210: if(str[0] == 'r')
! 211: permissions |= 1 << 8;
! 212: else if(str[0] != '-')
! 213: permissions |= FTP_LP_MALFORMATED_PERM;
! 214: if(str[1] == 'w')
! 215: permissions |= 1 << 7;
! 216: else if(str[1] != '-')
! 217: permissions |= FTP_LP_MALFORMATED_PERM;
! 218:
! 219: if(str[2] == 'x')
! 220: permissions |= 1 << 6;
! 221: else if(str[2] == 's') {
! 222: permissions |= 1 << 6;
! 223: permissions |= 1 << 11;
! 224: }
! 225: else if(str[2] == 'S')
! 226: permissions |= 1 << 11;
! 227: else if(str[2] != '-')
! 228: permissions |= FTP_LP_MALFORMATED_PERM;
! 229: /* GROUP */
! 230: if(str[3] == 'r')
! 231: permissions |= 1 << 5;
! 232: else if(str[3] != '-')
! 233: permissions |= FTP_LP_MALFORMATED_PERM;
! 234: if(str[4] == 'w')
! 235: permissions |= 1 << 4;
! 236: else if(str[4] != '-')
! 237: permissions |= FTP_LP_MALFORMATED_PERM;
! 238: if(str[5] == 'x')
! 239: permissions |= 1 << 3;
! 240: else if(str[5] == 's') {
! 241: permissions |= 1 << 3;
! 242: permissions |= 1 << 10;
! 243: }
! 244: else if(str[5] == 'S')
! 245: permissions |= 1 << 10;
! 246: else if(str[5] != '-')
! 247: permissions |= FTP_LP_MALFORMATED_PERM;
! 248: /* others */
! 249: if(str[6] == 'r')
! 250: permissions |= 1 << 2;
! 251: else if(str[6] != '-')
! 252: permissions |= FTP_LP_MALFORMATED_PERM;
! 253: if(str[7] == 'w')
! 254: permissions |= 1 << 1;
! 255: else if(str[7] != '-')
! 256: permissions |= FTP_LP_MALFORMATED_PERM;
! 257: if(str[8] == 'x')
! 258: permissions |= 1;
! 259: else if(str[8] == 't') {
! 260: permissions |= 1;
! 261: permissions |= 1 << 9;
! 262: }
! 263: else if(str[8] == 'T')
! 264: permissions |= 1 << 9;
! 265: else if(str[8] != '-')
! 266: permissions |= FTP_LP_MALFORMATED_PERM;
! 267:
! 268: return permissions;
! 269: }
! 270:
! 271: static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
! 272: struct fileinfo *infop)
! 273: {
! 274: curl_fnmatch_callback compare;
! 275: struct WildcardData *wc = &conn->data->wildcard;
! 276: struct ftp_wc *ftpwc = wc->protdata;
! 277: struct curl_llist *llist = &wc->filelist;
! 278: struct ftp_parselist_data *parser = ftpwc->parser;
! 279: bool add = TRUE;
! 280: struct curl_fileinfo *finfo = &infop->info;
! 281:
! 282: /* move finfo pointers to b_data */
! 283: char *str = finfo->b_data;
! 284: finfo->filename = str + parser->offsets.filename;
! 285: finfo->strings.group = parser->offsets.group ?
! 286: str + parser->offsets.group : NULL;
! 287: finfo->strings.perm = parser->offsets.perm ?
! 288: str + parser->offsets.perm : NULL;
! 289: finfo->strings.target = parser->offsets.symlink_target ?
! 290: str + parser->offsets.symlink_target : NULL;
! 291: finfo->strings.time = str + parser->offsets.time;
! 292: finfo->strings.user = parser->offsets.user ?
! 293: str + parser->offsets.user : NULL;
! 294:
! 295: /* get correct fnmatch callback */
! 296: compare = conn->data->set.fnmatch;
! 297: if(!compare)
! 298: compare = Curl_fnmatch;
! 299:
! 300: /* filter pattern-corresponding filenames */
! 301: Curl_set_in_callback(conn->data, true);
! 302: if(compare(conn->data->set.fnmatch_data, wc->pattern,
! 303: finfo->filename) == 0) {
! 304: /* discard symlink which is containing multiple " -> " */
! 305: if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
! 306: (strstr(finfo->strings.target, " -> "))) {
! 307: add = FALSE;
! 308: }
! 309: }
! 310: else {
! 311: add = FALSE;
! 312: }
! 313: Curl_set_in_callback(conn->data, false);
! 314:
! 315: if(add) {
! 316: Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
! 317: }
! 318: else {
! 319: Curl_fileinfo_cleanup(infop);
! 320: }
! 321:
! 322: ftpwc->parser->file_data = NULL;
! 323: return CURLE_OK;
! 324: }
! 325:
! 326: size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
! 327: void *connptr)
! 328: {
! 329: size_t bufflen = size*nmemb;
! 330: struct connectdata *conn = (struct connectdata *)connptr;
! 331: struct ftp_wc *ftpwc = conn->data->wildcard.protdata;
! 332: struct ftp_parselist_data *parser = ftpwc->parser;
! 333: struct fileinfo *infop;
! 334: struct curl_fileinfo *finfo;
! 335: unsigned long i = 0;
! 336: CURLcode result;
! 337: size_t retsize = bufflen;
! 338:
! 339: if(parser->error) { /* error in previous call */
! 340: /* scenario:
! 341: * 1. call => OK..
! 342: * 2. call => OUT_OF_MEMORY (or other error)
! 343: * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
! 344: * in wc_statemach()
! 345: */
! 346: goto fail;
! 347: }
! 348:
! 349: if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
! 350: /* considering info about FILE response format */
! 351: parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
! 352: OS_TYPE_WIN_NT : OS_TYPE_UNIX;
! 353: }
! 354:
! 355: while(i < bufflen) { /* FSM */
! 356:
! 357: char c = buffer[i];
! 358: if(!parser->file_data) { /* tmp file data is not allocated yet */
! 359: parser->file_data = Curl_fileinfo_alloc();
! 360: if(!parser->file_data) {
! 361: parser->error = CURLE_OUT_OF_MEMORY;
! 362: goto fail;
! 363: }
! 364: parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
! 365: if(!parser->file_data->info.b_data) {
! 366: parser->error = CURLE_OUT_OF_MEMORY;
! 367: goto fail;
! 368: }
! 369: parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
! 370: parser->item_offset = 0;
! 371: parser->item_length = 0;
! 372: }
! 373:
! 374: infop = parser->file_data;
! 375: finfo = &infop->info;
! 376: finfo->b_data[finfo->b_used++] = c;
! 377:
! 378: if(finfo->b_used >= finfo->b_size - 1) {
! 379: /* if it is important, extend buffer space for file data */
! 380: char *tmp = realloc(finfo->b_data,
! 381: finfo->b_size + FTP_BUFFER_ALLOCSIZE);
! 382: if(tmp) {
! 383: finfo->b_size += FTP_BUFFER_ALLOCSIZE;
! 384: finfo->b_data = tmp;
! 385: }
! 386: else {
! 387: Curl_fileinfo_cleanup(parser->file_data);
! 388: parser->file_data = NULL;
! 389: parser->error = CURLE_OUT_OF_MEMORY;
! 390: goto fail;
! 391: }
! 392: }
! 393:
! 394: switch(parser->os_type) {
! 395: case OS_TYPE_UNIX:
! 396: switch(parser->state.UNIX.main) {
! 397: case PL_UNIX_TOTALSIZE:
! 398: switch(parser->state.UNIX.sub.total_dirsize) {
! 399: case PL_UNIX_TOTALSIZE_INIT:
! 400: if(c == 't') {
! 401: parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
! 402: parser->item_length++;
! 403: }
! 404: else {
! 405: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 406: /* start FSM again not considering size of directory */
! 407: finfo->b_used = 0;
! 408: continue;
! 409: }
! 410: break;
! 411: case PL_UNIX_TOTALSIZE_READING:
! 412: parser->item_length++;
! 413: if(c == '\r') {
! 414: parser->item_length--;
! 415: finfo->b_used--;
! 416: }
! 417: else if(c == '\n') {
! 418: finfo->b_data[parser->item_length - 1] = 0;
! 419: if(strncmp("total ", finfo->b_data, 6) == 0) {
! 420: char *endptr = finfo->b_data + 6;
! 421: /* here we can deal with directory size, pass the leading white
! 422: spaces and then the digits */
! 423: while(ISSPACE(*endptr))
! 424: endptr++;
! 425: while(ISDIGIT(*endptr))
! 426: endptr++;
! 427: if(*endptr != 0) {
! 428: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 429: goto fail;
! 430: }
! 431: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 432: finfo->b_used = 0;
! 433: }
! 434: else {
! 435: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 436: goto fail;
! 437: }
! 438: }
! 439: break;
! 440: }
! 441: break;
! 442: case PL_UNIX_FILETYPE:
! 443: switch(c) {
! 444: case '-':
! 445: finfo->filetype = CURLFILETYPE_FILE;
! 446: break;
! 447: case 'd':
! 448: finfo->filetype = CURLFILETYPE_DIRECTORY;
! 449: break;
! 450: case 'l':
! 451: finfo->filetype = CURLFILETYPE_SYMLINK;
! 452: break;
! 453: case 'p':
! 454: finfo->filetype = CURLFILETYPE_NAMEDPIPE;
! 455: break;
! 456: case 's':
! 457: finfo->filetype = CURLFILETYPE_SOCKET;
! 458: break;
! 459: case 'c':
! 460: finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
! 461: break;
! 462: case 'b':
! 463: finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
! 464: break;
! 465: case 'D':
! 466: finfo->filetype = CURLFILETYPE_DOOR;
! 467: break;
! 468: default:
! 469: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 470: goto fail;
! 471: }
! 472: parser->state.UNIX.main = PL_UNIX_PERMISSION;
! 473: parser->item_length = 0;
! 474: parser->item_offset = 1;
! 475: break;
! 476: case PL_UNIX_PERMISSION:
! 477: parser->item_length++;
! 478: if(parser->item_length <= 9) {
! 479: if(!strchr("rwx-tTsS", c)) {
! 480: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 481: goto fail;
! 482: }
! 483: }
! 484: else if(parser->item_length == 10) {
! 485: unsigned int perm;
! 486: if(c != ' ') {
! 487: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 488: goto fail;
! 489: }
! 490: finfo->b_data[10] = 0; /* terminate permissions */
! 491: perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
! 492: if(perm & FTP_LP_MALFORMATED_PERM) {
! 493: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 494: goto fail;
! 495: }
! 496: parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
! 497: parser->file_data->info.perm = perm;
! 498: parser->offsets.perm = parser->item_offset;
! 499:
! 500: parser->item_length = 0;
! 501: parser->state.UNIX.main = PL_UNIX_HLINKS;
! 502: parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
! 503: }
! 504: break;
! 505: case PL_UNIX_HLINKS:
! 506: switch(parser->state.UNIX.sub.hlinks) {
! 507: case PL_UNIX_HLINKS_PRESPACE:
! 508: if(c != ' ') {
! 509: if(c >= '0' && c <= '9') {
! 510: parser->item_offset = finfo->b_used - 1;
! 511: parser->item_length = 1;
! 512: parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
! 513: }
! 514: else {
! 515: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 516: goto fail;
! 517: }
! 518: }
! 519: break;
! 520: case PL_UNIX_HLINKS_NUMBER:
! 521: parser->item_length ++;
! 522: if(c == ' ') {
! 523: char *p;
! 524: long int hlinks;
! 525: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 526: hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
! 527: if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
! 528: parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
! 529: parser->file_data->info.hardlinks = hlinks;
! 530: }
! 531: parser->item_length = 0;
! 532: parser->item_offset = 0;
! 533: parser->state.UNIX.main = PL_UNIX_USER;
! 534: parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
! 535: }
! 536: else if(c < '0' || c > '9') {
! 537: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 538: goto fail;
! 539: }
! 540: break;
! 541: }
! 542: break;
! 543: case PL_UNIX_USER:
! 544: switch(parser->state.UNIX.sub.user) {
! 545: case PL_UNIX_USER_PRESPACE:
! 546: if(c != ' ') {
! 547: parser->item_offset = finfo->b_used - 1;
! 548: parser->item_length = 1;
! 549: parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
! 550: }
! 551: break;
! 552: case PL_UNIX_USER_PARSING:
! 553: parser->item_length++;
! 554: if(c == ' ') {
! 555: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 556: parser->offsets.user = parser->item_offset;
! 557: parser->state.UNIX.main = PL_UNIX_GROUP;
! 558: parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
! 559: parser->item_offset = 0;
! 560: parser->item_length = 0;
! 561: }
! 562: break;
! 563: }
! 564: break;
! 565: case PL_UNIX_GROUP:
! 566: switch(parser->state.UNIX.sub.group) {
! 567: case PL_UNIX_GROUP_PRESPACE:
! 568: if(c != ' ') {
! 569: parser->item_offset = finfo->b_used - 1;
! 570: parser->item_length = 1;
! 571: parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
! 572: }
! 573: break;
! 574: case PL_UNIX_GROUP_NAME:
! 575: parser->item_length++;
! 576: if(c == ' ') {
! 577: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 578: parser->offsets.group = parser->item_offset;
! 579: parser->state.UNIX.main = PL_UNIX_SIZE;
! 580: parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
! 581: parser->item_offset = 0;
! 582: parser->item_length = 0;
! 583: }
! 584: break;
! 585: }
! 586: break;
! 587: case PL_UNIX_SIZE:
! 588: switch(parser->state.UNIX.sub.size) {
! 589: case PL_UNIX_SIZE_PRESPACE:
! 590: if(c != ' ') {
! 591: if(c >= '0' && c <= '9') {
! 592: parser->item_offset = finfo->b_used - 1;
! 593: parser->item_length = 1;
! 594: parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
! 595: }
! 596: else {
! 597: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 598: goto fail;
! 599: }
! 600: }
! 601: break;
! 602: case PL_UNIX_SIZE_NUMBER:
! 603: parser->item_length++;
! 604: if(c == ' ') {
! 605: char *p;
! 606: curl_off_t fsize;
! 607: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 608: if(!curlx_strtoofft(finfo->b_data + parser->item_offset,
! 609: &p, 10, &fsize)) {
! 610: if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
! 611: fsize != CURL_OFF_T_MIN) {
! 612: parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
! 613: parser->file_data->info.size = fsize;
! 614: }
! 615: parser->item_length = 0;
! 616: parser->item_offset = 0;
! 617: parser->state.UNIX.main = PL_UNIX_TIME;
! 618: parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
! 619: }
! 620: }
! 621: else if(!ISDIGIT(c)) {
! 622: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 623: goto fail;
! 624: }
! 625: break;
! 626: }
! 627: break;
! 628: case PL_UNIX_TIME:
! 629: switch(parser->state.UNIX.sub.time) {
! 630: case PL_UNIX_TIME_PREPART1:
! 631: if(c != ' ') {
! 632: if(ISALNUM(c)) {
! 633: parser->item_offset = finfo->b_used -1;
! 634: parser->item_length = 1;
! 635: parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
! 636: }
! 637: else {
! 638: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 639: goto fail;
! 640: }
! 641: }
! 642: break;
! 643: case PL_UNIX_TIME_PART1:
! 644: parser->item_length++;
! 645: if(c == ' ') {
! 646: parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
! 647: }
! 648: else if(!ISALNUM(c) && c != '.') {
! 649: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 650: goto fail;
! 651: }
! 652: break;
! 653: case PL_UNIX_TIME_PREPART2:
! 654: parser->item_length++;
! 655: if(c != ' ') {
! 656: if(ISALNUM(c)) {
! 657: parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
! 658: }
! 659: else {
! 660: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 661: goto fail;
! 662: }
! 663: }
! 664: break;
! 665: case PL_UNIX_TIME_PART2:
! 666: parser->item_length++;
! 667: if(c == ' ') {
! 668: parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
! 669: }
! 670: else if(!ISALNUM(c) && c != '.') {
! 671: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 672: goto fail;
! 673: }
! 674: break;
! 675: case PL_UNIX_TIME_PREPART3:
! 676: parser->item_length++;
! 677: if(c != ' ') {
! 678: if(ISALNUM(c)) {
! 679: parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
! 680: }
! 681: else {
! 682: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 683: goto fail;
! 684: }
! 685: }
! 686: break;
! 687: case PL_UNIX_TIME_PART3:
! 688: parser->item_length++;
! 689: if(c == ' ') {
! 690: finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
! 691: parser->offsets.time = parser->item_offset;
! 692: /*
! 693: if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
! 694: parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
! 695: }
! 696: */
! 697: if(finfo->filetype == CURLFILETYPE_SYMLINK) {
! 698: parser->state.UNIX.main = PL_UNIX_SYMLINK;
! 699: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
! 700: }
! 701: else {
! 702: parser->state.UNIX.main = PL_UNIX_FILENAME;
! 703: parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
! 704: }
! 705: }
! 706: else if(!ISALNUM(c) && c != '.' && c != ':') {
! 707: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 708: goto fail;
! 709: }
! 710: break;
! 711: }
! 712: break;
! 713: case PL_UNIX_FILENAME:
! 714: switch(parser->state.UNIX.sub.filename) {
! 715: case PL_UNIX_FILENAME_PRESPACE:
! 716: if(c != ' ') {
! 717: parser->item_offset = finfo->b_used - 1;
! 718: parser->item_length = 1;
! 719: parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
! 720: }
! 721: break;
! 722: case PL_UNIX_FILENAME_NAME:
! 723: parser->item_length++;
! 724: if(c == '\r') {
! 725: parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
! 726: }
! 727: else if(c == '\n') {
! 728: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 729: parser->offsets.filename = parser->item_offset;
! 730: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 731: result = ftp_pl_insert_finfo(conn, infop);
! 732: if(result) {
! 733: parser->error = result;
! 734: goto fail;
! 735: }
! 736: }
! 737: break;
! 738: case PL_UNIX_FILENAME_WINDOWSEOL:
! 739: if(c == '\n') {
! 740: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 741: parser->offsets.filename = parser->item_offset;
! 742: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 743: result = ftp_pl_insert_finfo(conn, infop);
! 744: if(result) {
! 745: parser->error = result;
! 746: goto fail;
! 747: }
! 748: }
! 749: else {
! 750: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 751: goto fail;
! 752: }
! 753: break;
! 754: }
! 755: break;
! 756: case PL_UNIX_SYMLINK:
! 757: switch(parser->state.UNIX.sub.symlink) {
! 758: case PL_UNIX_SYMLINK_PRESPACE:
! 759: if(c != ' ') {
! 760: parser->item_offset = finfo->b_used - 1;
! 761: parser->item_length = 1;
! 762: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
! 763: }
! 764: break;
! 765: case PL_UNIX_SYMLINK_NAME:
! 766: parser->item_length++;
! 767: if(c == ' ') {
! 768: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
! 769: }
! 770: else if(c == '\r' || c == '\n') {
! 771: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 772: goto fail;
! 773: }
! 774: break;
! 775: case PL_UNIX_SYMLINK_PRETARGET1:
! 776: parser->item_length++;
! 777: if(c == '-') {
! 778: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
! 779: }
! 780: else if(c == '\r' || c == '\n') {
! 781: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 782: goto fail;
! 783: }
! 784: else {
! 785: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
! 786: }
! 787: break;
! 788: case PL_UNIX_SYMLINK_PRETARGET2:
! 789: parser->item_length++;
! 790: if(c == '>') {
! 791: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
! 792: }
! 793: else if(c == '\r' || c == '\n') {
! 794: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 795: goto fail;
! 796: }
! 797: else {
! 798: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
! 799: }
! 800: break;
! 801: case PL_UNIX_SYMLINK_PRETARGET3:
! 802: parser->item_length++;
! 803: if(c == ' ') {
! 804: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
! 805: /* now place where is symlink following */
! 806: finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
! 807: parser->offsets.filename = parser->item_offset;
! 808: parser->item_length = 0;
! 809: parser->item_offset = 0;
! 810: }
! 811: else if(c == '\r' || c == '\n') {
! 812: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 813: goto fail;
! 814: }
! 815: else {
! 816: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
! 817: }
! 818: break;
! 819: case PL_UNIX_SYMLINK_PRETARGET4:
! 820: if(c != '\r' && c != '\n') {
! 821: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
! 822: parser->item_offset = finfo->b_used - 1;
! 823: parser->item_length = 1;
! 824: }
! 825: else {
! 826: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 827: goto fail;
! 828: }
! 829: break;
! 830: case PL_UNIX_SYMLINK_TARGET:
! 831: parser->item_length++;
! 832: if(c == '\r') {
! 833: parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
! 834: }
! 835: else if(c == '\n') {
! 836: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 837: parser->offsets.symlink_target = parser->item_offset;
! 838: result = ftp_pl_insert_finfo(conn, infop);
! 839: if(result) {
! 840: parser->error = result;
! 841: goto fail;
! 842: }
! 843: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 844: }
! 845: break;
! 846: case PL_UNIX_SYMLINK_WINDOWSEOL:
! 847: if(c == '\n') {
! 848: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 849: parser->offsets.symlink_target = parser->item_offset;
! 850: result = ftp_pl_insert_finfo(conn, infop);
! 851: if(result) {
! 852: parser->error = result;
! 853: goto fail;
! 854: }
! 855: parser->state.UNIX.main = PL_UNIX_FILETYPE;
! 856: }
! 857: else {
! 858: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 859: goto fail;
! 860: }
! 861: break;
! 862: }
! 863: break;
! 864: }
! 865: break;
! 866: case OS_TYPE_WIN_NT:
! 867: switch(parser->state.NT.main) {
! 868: case PL_WINNT_DATE:
! 869: parser->item_length++;
! 870: if(parser->item_length < 9) {
! 871: if(!strchr("0123456789-", c)) { /* only simple control */
! 872: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 873: goto fail;
! 874: }
! 875: }
! 876: else if(parser->item_length == 9) {
! 877: if(c == ' ') {
! 878: parser->state.NT.main = PL_WINNT_TIME;
! 879: parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
! 880: }
! 881: else {
! 882: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 883: goto fail;
! 884: }
! 885: }
! 886: else {
! 887: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 888: goto fail;
! 889: }
! 890: break;
! 891: case PL_WINNT_TIME:
! 892: parser->item_length++;
! 893: switch(parser->state.NT.sub.time) {
! 894: case PL_WINNT_TIME_PRESPACE:
! 895: if(!ISSPACE(c)) {
! 896: parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
! 897: }
! 898: break;
! 899: case PL_WINNT_TIME_TIME:
! 900: if(c == ' ') {
! 901: parser->offsets.time = parser->item_offset;
! 902: finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
! 903: parser->state.NT.main = PL_WINNT_DIRORSIZE;
! 904: parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
! 905: parser->item_length = 0;
! 906: }
! 907: else if(!strchr("APM0123456789:", c)) {
! 908: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 909: goto fail;
! 910: }
! 911: break;
! 912: }
! 913: break;
! 914: case PL_WINNT_DIRORSIZE:
! 915: switch(parser->state.NT.sub.dirorsize) {
! 916: case PL_WINNT_DIRORSIZE_PRESPACE:
! 917: if(c != ' ') {
! 918: parser->item_offset = finfo->b_used - 1;
! 919: parser->item_length = 1;
! 920: parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
! 921: }
! 922: break;
! 923: case PL_WINNT_DIRORSIZE_CONTENT:
! 924: parser->item_length ++;
! 925: if(c == ' ') {
! 926: finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
! 927: if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
! 928: finfo->filetype = CURLFILETYPE_DIRECTORY;
! 929: finfo->size = 0;
! 930: }
! 931: else {
! 932: char *endptr;
! 933: if(curlx_strtoofft(finfo->b_data +
! 934: parser->item_offset,
! 935: &endptr, 10, &finfo->size)) {
! 936: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 937: goto fail;
! 938: }
! 939: /* correct file type */
! 940: parser->file_data->info.filetype = CURLFILETYPE_FILE;
! 941: }
! 942:
! 943: parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
! 944: parser->item_length = 0;
! 945: parser->state.NT.main = PL_WINNT_FILENAME;
! 946: parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
! 947: }
! 948: break;
! 949: }
! 950: break;
! 951: case PL_WINNT_FILENAME:
! 952: switch(parser->state.NT.sub.filename) {
! 953: case PL_WINNT_FILENAME_PRESPACE:
! 954: if(c != ' ') {
! 955: parser->item_offset = finfo->b_used -1;
! 956: parser->item_length = 1;
! 957: parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
! 958: }
! 959: break;
! 960: case PL_WINNT_FILENAME_CONTENT:
! 961: parser->item_length++;
! 962: if(c == '\r') {
! 963: parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
! 964: finfo->b_data[finfo->b_used - 1] = 0;
! 965: }
! 966: else if(c == '\n') {
! 967: parser->offsets.filename = parser->item_offset;
! 968: finfo->b_data[finfo->b_used - 1] = 0;
! 969: parser->offsets.filename = parser->item_offset;
! 970: result = ftp_pl_insert_finfo(conn, infop);
! 971: if(result) {
! 972: parser->error = result;
! 973: goto fail;
! 974: }
! 975: parser->state.NT.main = PL_WINNT_DATE;
! 976: parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
! 977: }
! 978: break;
! 979: case PL_WINNT_FILENAME_WINEOL:
! 980: if(c == '\n') {
! 981: parser->offsets.filename = parser->item_offset;
! 982: result = ftp_pl_insert_finfo(conn, infop);
! 983: if(result) {
! 984: parser->error = result;
! 985: goto fail;
! 986: }
! 987: parser->state.NT.main = PL_WINNT_DATE;
! 988: parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
! 989: }
! 990: else {
! 991: parser->error = CURLE_FTP_BAD_FILE_LIST;
! 992: goto fail;
! 993: }
! 994: break;
! 995: }
! 996: break;
! 997: }
! 998: break;
! 999: default:
! 1000: retsize = bufflen + 1;
! 1001: goto fail;
! 1002: }
! 1003:
! 1004: i++;
! 1005: }
! 1006: return retsize;
! 1007:
! 1008: fail:
! 1009:
! 1010: /* Clean up any allocated memory. */
! 1011: if(parser->file_data) {
! 1012: Curl_fileinfo_cleanup(parser->file_data);
! 1013: parser->file_data = NULL;
! 1014: }
! 1015:
! 1016: return retsize;
! 1017: }
! 1018:
! 1019: #endif /* CURL_DISABLE_FTP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>