From 0825cd80a62c21725fb3615f1fdd3aa6cc5f0f34 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Wed, 12 May 2010 15:33:22 +0200 Subject: FTP: WILDCARDMATCH/CHUNKING/FNMATCH added --- lib/ftplistparser.c | 1009 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1009 insertions(+) create mode 100644 lib/ftplistparser.c (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c new file mode 100644 index 000000000..9d42e8f37 --- /dev/null +++ b/lib/ftplistparser.c @@ -0,0 +1,1009 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at http://curl.haxx.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ + +/** + * Now implemented: + * + * 1) UNIX version 1 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog + * 2) UNIX version 2 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog + * 3) UNIX version 3 + * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog + * 4) UNIX symlink + * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 + * 5) DOS style + * 01-29-97 11:32PM prog + */ + +#include + +#include "ftplistparser.h" +#include "curl_fnmatch.h" + +#include "urldata.h" +#include "ftp.h" +#include "fileinfo.h" +#include "llist.h" +#include "strtoofft.h" +#include "rawstr.h" +#include "ftp.h" + +/* allocs buffer which will contain one line of LIST command response */ +#define FTP_BUFFER_ALLOCSIZE 160 + +typedef enum { + PL_UNIX_FILETYPE = 0, + PL_UNIX_PERMISSION, + PL_UNIX_HLINKS, + PL_UNIX_USER, + PL_UNIX_GROUP, + PL_UNIX_SIZE, + PL_UNIX_TIME, + PL_UNIX_FILENAME, + PL_UNIX_SYMLINK +} pl_unix_mainstate; + +typedef union { + enum { + PL_UNIX_HLINKS_PRESPACE = 0, + PL_UNIX_HLINKS_NUMBER + } hlinks; + + enum { + PL_UNIX_USER_PRESPACE = 0, + PL_UNIX_USER_PARSING + } user; + + enum { + PL_UNIX_GROUP_PRESPACE = 0, + PL_UNIX_GROUP_NAME + } group; + + enum { + PL_UNIX_SIZE_PRESPACE = 0, + PL_UNIX_SIZE_NUMBER + } size; + + enum { + PL_UNIX_TIME_PREPART1 = 0, + PL_UNIX_TIME_PART1, + PL_UNIX_TIME_PREPART2, + PL_UNIX_TIME_PART2, + PL_UNIX_TIME_PREPART3, + PL_UNIX_TIME_PART3 + } time; + + enum { + PL_UNIX_FILENAME_PRESPACE = 0, + PL_UNIX_FILENAME_NAME, + PL_UNIX_FILENAME_WINDOWSEOL + } filename; + + enum { + PL_UNIX_SYMLINK_PRESPACE = 0, + PL_UNIX_SYMLINK_NAME, + PL_UNIX_SYMLINK_PRETARGET1, + PL_UNIX_SYMLINK_PRETARGET2, + PL_UNIX_SYMLINK_PRETARGET3, + PL_UNIX_SYMLINK_PRETARGET4, + PL_UNIX_SYMLINK_TARGET, + PL_UNIX_SYMLINK_WINDOWSEOL + } symlink; +} pl_unix_substate; + +typedef enum { + PL_WINNT_DATE = 0, + PL_WINNT_TIME, + PL_WINNT_DIRORSIZE, + PL_WINNT_FILENAME +} pl_winNT_mainstate; + +typedef union { + enum { + PL_WINNT_TIME_PRESPACE = 0, + PL_WINNT_TIME_TIME + } time; + enum { + PL_WINNT_DIRORSIZE_PRESPACE = 0, + PL_WINNT_DIRORSIZE_CONTENT + } dirorsize; + enum { + PL_WINNT_FILENAME_PRESPACE = 0, + PL_WINNT_FILENAME_CONTENT, + PL_WINNT_FILENAME_WINEOL + } filename; +} pl_winNT_substate; + +/* This struct is used in wildcard downloading - for parsing LIST response */ +struct ftp_parselist_data { + enum { + OS_TYPE_UNKNOWN = 0, + OS_TYPE_UNIX, + OS_TYPE_WIN_NT + } os_type; + + union { + struct { + pl_unix_mainstate main; + pl_unix_substate sub; + } UNIX; + + struct { + pl_winNT_mainstate main; + pl_winNT_substate sub; + } NT; + } state; + + struct { + char *buffer; + size_t bufferlength; /* how many bytes is allocated at *buffer */ + size_t bufferin; /* how many bytes is in buffer */ + } tmpdata; + + struct { + curl_write_callback old_fwritefunc; + FILE *old_file_descriptor; + } backup; + + CURLcode error; + struct curl_fileinfo *file_data; + unsigned int item_length; + size_t item_offset; + struct { + size_t filename; + size_t user; + size_t group; + size_t time; + size_t perm; + size_t symlink_target; + } offsets; +}; + +struct ftp_parselist_data *ftp_parselist_data_alloc(void) +{ + struct ftp_parselist_data *parselist_data = + malloc(sizeof(struct ftp_parselist_data)); + if(!parselist_data) + return ZERO_NULL; + memset(parselist_data, 0, sizeof(struct ftp_parselist_data)); + return parselist_data; +} + + +void ftp_parselist_data_free(struct ftp_parselist_data **pl_data) +{ + if(*pl_data) + free(*pl_data); + *pl_data = NULL; +} + + +CURLcode ftp_parselist_geterror(struct ftp_parselist_data *pl_data) +{ + return pl_data->error; +} + + +#define FTP_LP_MALFORMATED_PERM 0x01000000 + +static int ftp_pl_get_permission(const char *str) +{ + int permissions = 0; + /* USER */ + if(str[0] == 'r') + permissions |= 1 << 8; + else if(str[0] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[1] == 'w') + permissions |= 1 << 7; + else if(str[1] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + if(str[2] == 'x') + permissions |= 1 << 6; + else if(str[2] == 's') { + permissions |= 1 << 6; + permissions |= 1 << 11; + } + else if(str[2] == 'S') + permissions |= 1 << 11; + else if(str[2] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* GROUP */ + if(str[3] == 'r') + permissions |= 1 << 5; + else if(str[3] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[4] == 'w') + permissions |= 1 << 4; + else if(str[4] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[5] == 'x') + permissions |= 1 << 3; + else if(str[5] == 's') { + permissions |= 1 << 3; + permissions |= 1 << 10; + } + else if(str[5] == 'S') + permissions |= 1 << 10; + else if(str[5] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + /* others */ + if(str[6] == 'r') + permissions |= 1 << 2; + else if(str[6] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[7] == 'w') + permissions |= 1 << 1; + else if(str[7] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + if(str[8] == 'x') + permissions |= 1; + else if(str[8] == 't') { + permissions |= 1; + permissions |= 1 << 9; + } + else if(str[8] == 'T') + permissions |= 1 << 9; + else if(str[8] != '-') + permissions |= FTP_LP_MALFORMATED_PERM; + + return permissions; +} + +static void PL_ERROR(struct connectdata *conn, CURLcode err) +{ + struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; + struct ftp_parselist_data *parser = tmpdata->parser; + if(parser->file_data) + Curl_fileinfo_dtor(NULL, parser->file_data); + parser->file_data = NULL; + parser->error = err; +} + +static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string) +{ + (void)parser; + (void)string; + /* TODO + * There could be possible parse timestamp from server. Leaving unimplemented + * for now. + * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to + * parser->file_data->flags + * + * Ftp servers are giving usually these formats: + * Apr 11 1998 (unknown time.. set it to 00:00:00?) + * Apr 11 12:21 (unknown year -> set it to NOW() time?) + * 08-05-09 02:49PM (ms-dos format) + * 20100421092538 -> for MLST/MLSD response + */ + + return FALSE; +} + +static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, + struct curl_fileinfo *finfo) +{ + curl_fnmatch_callback compare; + struct WildcardData *wc = &conn->data->wildcard; + struct ftp_wc_tmpdata *tmpdata = wc->tmp; + struct curl_llist *llist = wc->filelist; + struct ftp_parselist_data *parser = tmpdata->parser; + bool add = TRUE; + + /* move finfo pointers to b_data */ + char *str = finfo->b_data; + finfo->filename = str + parser->offsets.filename; + finfo->strings.group = parser->offsets.group ? + str + parser->offsets.group : NULL; + finfo->strings.perm = parser->offsets.perm ? + str + parser->offsets.perm : NULL; + finfo->strings.target = parser->offsets.symlink_target ? + str + parser->offsets.symlink_target : NULL; + finfo->strings.time = str + parser->offsets.time; + finfo->strings.user = parser->offsets.user ? + str + parser->offsets.user : NULL; + + /* get correct fnmatch callback */ + compare = conn->data->set.fnmatch; + if(!compare) + compare = Curl_fnmatch; + + /* filter pattern-corresponding filenames */ + if(compare(wc->pattern, finfo->filename) == 0) { + /* discard symlink which is containing multiple " -> " */ + if((finfo->filetype == CURLFILETYPE_SYMLINK) && + (strstr(finfo->strings.target, " -> "))) { + add = FALSE; + } + } + else { + add = FALSE; + } + + if(add) { + if(!Curl_llist_insert_next(llist, llist->tail, finfo)) { + Curl_fileinfo_dtor(NULL, finfo); + tmpdata->parser->file_data = NULL; + return CURLE_OUT_OF_MEMORY; + } + } + else { + Curl_fileinfo_dtor(NULL, finfo); + } + + tmpdata->parser->file_data = NULL; + return CURLE_OK; +} + +size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) +{ + size_t bufflen = size*nmemb; + struct connectdata *conn = (struct connectdata *)connptr; + struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp; + struct ftp_parselist_data *parser = tmpdata->parser; + struct curl_fileinfo *finfo; + unsigned long i = 0; + CURLcode rc; + + if(parser->error) { /* error in previous call */ + /* scenario: + * 1. call => OK.. + * 2. call => OUT_OF_MEMORY (or other error) + * 3. (last) call => is skipped RIGHT HERE and the error is hadled later + * in wc_statemach() + */ + return bufflen; + } + + if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { + /* considering info about FILE response format */ + parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ? + OS_TYPE_WIN_NT : OS_TYPE_UNIX; + } + + while(i < bufflen) { /* FSM */ + + char c = buffer[i]; + if(!parser->file_data) { /* tmp file data is not allocated yet */ + parser->file_data = Curl_fileinfo_alloc(); + if(!parser->file_data) { + parser->error = CURLE_OUT_OF_MEMORY; + return bufflen; + } + parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); + if(!parser->file_data->b_data) { + PL_ERROR(conn, CURLE_OUT_OF_MEMORY); + return bufflen; + } + parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; + parser->item_offset = 0; + parser->item_length = 0; + } + + finfo = parser->file_data; + finfo->b_data[finfo->b_used++] = buffer[i]; + + if(finfo->b_used >= finfo->b_size - 1) { + /* if it is important, extend buffer space for file data */ + char *tmp = realloc(finfo->b_data, + finfo->b_size + FTP_BUFFER_ALLOCSIZE); + if(tmp) { + finfo->b_size += FTP_BUFFER_ALLOCSIZE; + finfo->b_data = tmp; + } + else { + Curl_fileinfo_dtor(NULL, parser->file_data); + parser->file_data = NULL; + } + } + + switch (parser->os_type) { + case OS_TYPE_UNIX: + switch (parser->state.UNIX.main) { + case PL_UNIX_FILETYPE: + switch (c) { + case '-': + finfo->filetype = CURLFILETYPE_FILE; + break; + case 'd': + finfo->filetype = CURLFILETYPE_DIRECTORY; + break; + case 'l': + finfo->filetype = CURLFILETYPE_SYMLINK; + break; + case 'p': + finfo->filetype = CURLFILETYPE_NAMEDPIPE; + break; + case 's': + finfo->filetype = CURLFILETYPE_SOCKET; + break; + case 'c': + finfo->filetype = CURLFILETYPE_DEVICE_CHAR; + break; + case 'b': + finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; + break; + case 'D': + finfo->filetype = CURLFILETYPE_DOOR; + break; + default: + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + break; + } + parser->state.UNIX.main = PL_UNIX_PERMISSION; + parser->item_length = 0; + parser->item_offset = 1; + break; + case PL_UNIX_PERMISSION: + parser->item_length++; + if(parser->item_length <= 9) { + if(!strchr("rwx-tTsS", c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else if(parser->item_length == 10) { + int32_t perm; + if(c != ' ') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + finfo->b_data[10] = 0; /* terminate permissions */ + perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset); + if(perm & FTP_LP_MALFORMATED_PERM) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM; + parser->file_data->perm = perm; + parser->offsets.perm = parser->item_offset; + + parser->item_length = 0; + parser->state.UNIX.main = PL_UNIX_HLINKS; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; + } + break; + case PL_UNIX_HLINKS: + switch(parser->state.UNIX.sub.hlinks) { + case PL_UNIX_HLINKS_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_HLINKS_NUMBER: + parser->item_length ++; + if(c == ' ') { + char *p; + long int hlinks; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10); + if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; + parser->file_data->hardlinks = hlinks; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_USER; + parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; + } + else if(c < '0' || c > '9') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_USER: + switch(parser->state.UNIX.sub.user) { + case PL_UNIX_USER_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; + } + break; + case PL_UNIX_USER_PARSING: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.user = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_GROUP; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_GROUP: + switch(parser->state.UNIX.sub.group) { + case PL_UNIX_GROUP_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; + } + break; + case PL_UNIX_GROUP_NAME: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.group = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_SIZE; + parser->state.UNIX.sub.group = PL_UNIX_SIZE_PRESPACE; + parser->item_offset = 0; + parser->item_length = 0; + } + break; + } + break; + case PL_UNIX_SIZE: + switch(parser->state.UNIX.sub.size) { + case PL_UNIX_SIZE_PRESPACE: + if(c != ' ') { + if(c >= '0' && c <= '9') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_SIZE_NUMBER: + parser->item_length++; + if(c == ' ') { + char *p; + curl_off_t fsize; + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); + if(p[0] == '\0' && fsize != CURL_LLONG_MAX && + fsize != CURL_LLONG_MIN) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->file_data->size = fsize; + } + parser->item_length = 0; + parser->item_offset = 0; + parser->state.UNIX.main = PL_UNIX_TIME; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; + } + else if (!ISDIGIT(c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_TIME: + switch(parser->state.UNIX.sub.time) { + case PL_UNIX_TIME_PREPART1: + if(c != ' ') { + if(ISALNUM(c)) { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART1: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.size = PL_UNIX_TIME_PREPART2; + } + else if(!ISALNUM(c) && c != '.') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_TIME_PREPART2: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART2: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.size = PL_UNIX_TIME_PREPART3; + } + else if(!ISALNUM(c) && c != '.') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_TIME_PREPART3: + parser->item_length++; + if(c != ' ') { + if(ISALNUM(c)) { + parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + case PL_UNIX_TIME_PART3: + parser->item_length++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->offsets.time = parser->item_offset; + if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) { + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; + } + if(finfo->filetype == CURLFILETYPE_SYMLINK) { + parser->state.UNIX.main = PL_UNIX_SYMLINK; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; + } + else { + parser->state.UNIX.main = PL_UNIX_FILENAME; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; + } + } + else if(!ISALNUM(c) && c != '.' && c != ':') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_FILENAME: + switch(parser->state.UNIX.sub.filename) { + case PL_UNIX_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; + } + break; + case PL_UNIX_FILENAME_NAME: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + } + break; + case PL_UNIX_FILENAME_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length] = 0; + parser->offsets.filename = parser->item_offset; + parser->state.UNIX.main = PL_UNIX_FILETYPE; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_UNIX_SYMLINK: + switch(parser->state.UNIX.sub.symlink) { + case PL_UNIX_SYMLINK_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_NAME: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_SYMLINK_PRETARGET1: + parser->item_length++; + if(c == '-') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET2: + parser->item_length++; + if(c == '>') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET3: + parser->item_length++; + if(c == ' ') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; + /* now place where is symlink following */ + finfo->b_data[parser->item_offset + parser->item_length - 4] = 0; + parser->offsets.filename = parser->item_offset; + parser->item_length = 0; + parser->item_offset = 0; + } + else if(c == '\r' || c == '\n') { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; + } + break; + case PL_UNIX_SYMLINK_PRETARGET4: + if(c != '\r' && c != '\n') { + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_UNIX_SYMLINK_TARGET: + parser->item_length ++; + if(c == '\r') { + parser->item_length --; + parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; + } + else if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + break; + case PL_UNIX_SYMLINK_WINDOWSEOL: + if(c == '\n') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + parser->offsets.symlink_target = parser->item_offset; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + parser->state.UNIX.main = PL_UNIX_FILETYPE; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + } + break; + case OS_TYPE_WIN_NT: + switch(parser->state.NT.main) { + case PL_WINNT_DATE: + parser->item_length++; + if(parser->item_length < 9) { + if(!strchr("0123456789-", c)) { /* only simple control */ + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else if(parser->item_length == 9) { + if(c == ' ') { + parser->state.NT.main = PL_WINNT_TIME; + parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + case PL_WINNT_TIME: + parser->item_length++; + switch(parser->state.NT.sub.time) { + case PL_WINNT_TIME_PRESPACE: + if(!ISSPACE(c)) { + parser->state.NT.sub.time = PL_WINNT_TIME_TIME; + } + break; + case PL_WINNT_TIME_TIME: + if(c == ' ') { + parser->offsets.time = parser->item_offset; + finfo->b_data[parser->item_offset + parser->item_length -1] = 0; + parser->state.NT.main = PL_WINNT_DIRORSIZE; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; + parser->item_length = 0; + } + else if(!strchr("APM0123456789:", c)) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + case PL_WINNT_DIRORSIZE: + switch(parser->state.NT.sub.dirorsize) { + case PL_WINNT_DIRORSIZE_PRESPACE: + if(c == ' ') { + + } + else { + parser->item_offset = finfo->b_used - 1; + parser->item_length = 1; + parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; + } + break; + case PL_WINNT_DIRORSIZE_CONTENT: + parser->item_length ++; + if(c == ' ') { + finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; + if(strcmp("", finfo->b_data + parser->item_offset) == 0) { + finfo->filetype = CURLFILETYPE_DIRECTORY; + finfo->size = 0; + } + else { + char *endptr; + finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset, + &endptr, 10); + if(!*endptr) { + if(finfo->size < CURL_LLONG_MAX && + finfo->size > CURL_LLONG_MIN) { + + } + else if(finfo->size == CURL_LLONG_MAX || + finfo->size == CURL_LLONG_MIN) { + if(errno == ERANGE) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + /* correct file size */ + parser->file_data->filetype = CURLFILETYPE_FILE; + } + + parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; + parser->item_length = 0; + parser->state.NT.main = PL_WINNT_FILENAME; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; + } + break; + } + break; + case PL_WINNT_FILENAME: + switch (parser->state.NT.sub.filename) { + case PL_WINNT_FILENAME_PRESPACE: + if(c != ' ') { + parser->item_offset = finfo->b_used -1; + parser->item_length = 1; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; + } + break; + case PL_WINNT_FILENAME_CONTENT: + parser->item_length++; + if(c == '\r') { + parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; + finfo->b_data[finfo->b_used - 1] = 0; + } + else if(c == '\n') { + parser->offsets.filename = parser->item_offset; + finfo->b_data[finfo->b_used - 1] = 0; + parser->offsets.filename = parser->item_offset; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = 0; + } + break; + case PL_WINNT_FILENAME_WINEOL: + if(c == '\n') { + parser->offsets.filename = parser->item_offset; + rc = ftp_pl_insert_finfo(conn, finfo); + if(rc) { + PL_ERROR(conn, rc); + return bufflen; + } + parser->state.NT.main = PL_WINNT_DATE; + parser->state.NT.sub.filename = 0; + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + break; + } + break; + } + break; + default: + return bufflen+1; + break; + } + + i++; + } + + return bufflen; +} -- cgit v1.2.1 From e4af5d6efcf9c8ddae087009df1782d890a0e13b Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Sat, 15 May 2010 21:58:50 +0200 Subject: ftp wildcard: fix int32_t and size/group mixups --- lib/ftplistparser.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 9d42e8f37..faf314fe2 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -465,7 +465,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) } } else if(parser->item_length == 10) { - int32_t perm; + unsigned int perm; if(c != ' ') { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; @@ -560,7 +560,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; parser->offsets.group = parser->item_offset; parser->state.UNIX.main = PL_UNIX_SIZE; - parser->state.UNIX.sub.group = PL_UNIX_SIZE_PRESPACE; + parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; parser->item_offset = 0; parser->item_length = 0; } @@ -624,7 +624,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) case PL_UNIX_TIME_PART1: parser->item_length++; if(c == ' ') { - parser->state.UNIX.sub.size = PL_UNIX_TIME_PREPART2; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; } else if(!ISALNUM(c) && c != '.') { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); @@ -646,7 +646,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) case PL_UNIX_TIME_PART2: parser->item_length++; if(c == ' ') { - parser->state.UNIX.sub.size = PL_UNIX_TIME_PREPART3; + parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; } else if(!ISALNUM(c) && c != '.') { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); @@ -917,21 +917,13 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset, &endptr, 10); if(!*endptr) { - if(finfo->size < CURL_LLONG_MAX && - finfo->size > CURL_LLONG_MIN) { - - } - else if(finfo->size == CURL_LLONG_MAX || - finfo->size == CURL_LLONG_MIN) { + if(finfo->size == CURL_LLONG_MAX || + finfo->size == CURL_LLONG_MIN) { if(errno == ERANGE) { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } } - else { - PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); - return bufflen; - } } else { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); @@ -974,7 +966,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) return bufflen; } parser->state.NT.main = PL_WINNT_DATE; - parser->state.NT.sub.filename = 0; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; } break; case PL_WINNT_FILENAME_WINEOL: @@ -986,7 +978,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) return bufflen; } parser->state.NT.main = PL_WINNT_DATE; - parser->state.NT.sub.filename = 0; + parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; } else { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); -- cgit v1.2.1 From 2ffe834bffa893efcd8942736ab14e311a0087b3 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Sun, 16 May 2010 02:49:08 +0200 Subject: ftp wildcard: a new option CURLOPT_FNMATCH_DATA --- lib/ftplistparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index faf314fe2..ff7045b1e 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -330,7 +330,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, compare = Curl_fnmatch; /* filter pattern-corresponding filenames */ - if(compare(wc->pattern, finfo->filename) == 0) { + if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { /* discard symlink which is containing multiple " -> " */ if((finfo->filetype == CURLFILETYPE_SYMLINK) && (strstr(finfo->strings.target, " -> "))) { -- cgit v1.2.1 From 5f53c9d94a41622e14758d81290ff054dfee4395 Mon Sep 17 00:00:00 2001 From: Tor Arntsen Date: Wed, 19 May 2010 14:26:08 +0000 Subject: lib: Fix AIX build failure --- lib/ftplistparser.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index ff7045b1e..4e10c4331 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -35,6 +35,8 @@ * 01-29-97 11:32PM prog */ +#include "setup.h" + #include #include "ftplistparser.h" -- cgit v1.2.1 From 233ec511db140990bbaff622f8edd9f5d28f7399 Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Fri, 28 May 2010 09:45:17 +0200 Subject: lib: eliminate 'statement not reached' warnings --- lib/ftplistparser.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 4e10c4331..947b71417 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -452,7 +452,6 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) default: PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; - break; } parser->state.UNIX.main = PL_UNIX_PERMISSION; parser->item_length = 0; @@ -993,7 +992,6 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) break; default: return bufflen+1; - break; } i++; -- cgit v1.2.1 From 20ae9d4f716cd898ca1aa47b7ea0664ebc57b2ba Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Sat, 29 May 2010 21:28:16 +0200 Subject: strtoofft: rename CURL_LLONG_MIN -> CURL_OFF_T_MIN ... and CURL_LLONG_MAX -> CURL_OFF_T_MAX --- lib/ftplistparser.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 947b71417..95adfe68d 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -590,8 +590,8 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) curl_off_t fsize; finfo->b_data[parser->item_offset + parser->item_length - 1] = 0; fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10); - if(p[0] == '\0' && fsize != CURL_LLONG_MAX && - fsize != CURL_LLONG_MIN) { + if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && + fsize != CURL_OFF_T_MIN) { parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE; parser->file_data->size = fsize; } @@ -918,8 +918,8 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset, &endptr, 10); if(!*endptr) { - if(finfo->size == CURL_LLONG_MAX || - finfo->size == CURL_LLONG_MIN) { + if(finfo->size == CURL_OFF_T_MAX || + finfo->size == CURL_OFF_T_MIN) { if(errno == ERANGE) { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; -- cgit v1.2.1 From 077125e4a2a77384c88b51ffd88c985cabf95193 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 2 Jun 2010 14:13:02 +0200 Subject: include libcurl standard internal headers --- lib/ftplistparser.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 95adfe68d..65addfaa1 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -50,6 +50,13 @@ #include "rawstr.h" #include "ftp.h" +#define _MPRINTF_REPLACE /* use our functions only */ +#include + +#include "curl_memory.h" +/* The last #include file should be: */ +#include "memdebug.h" + /* allocs buffer which will contain one line of LIST command response */ #define FTP_BUFFER_ALLOCSIZE 160 -- cgit v1.2.1 From 475c19c42b01ab23da7a90551d1b07d2ebfd2e5d Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 2 Jun 2010 23:22:38 +0200 Subject: ftplistparser.c: avoid some invalid dereferences --- lib/ftplistparser.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 65addfaa1..c5a2f8c45 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -341,7 +341,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, /* filter pattern-corresponding filenames */ if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { /* discard symlink which is containing multiple " -> " */ - if((finfo->filetype == CURLFILETYPE_SYMLINK) && + if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target (strstr(finfo->strings.target, " -> "))) { add = FALSE; } @@ -424,6 +424,9 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) else { Curl_fileinfo_dtor(NULL, parser->file_data); parser->file_data = NULL; + parser->error = CURLE_OUT_OF_MEMORY; + PL_ERROR(conn, CURLE_OUT_OF_MEMORY); + return bufflen; } } @@ -937,7 +940,7 @@ size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } - /* correct file size */ + /* correct file type */ parser->file_data->filetype = CURLFILETYPE_FILE; } -- cgit v1.2.1 From bc0f3dd15e99db189ae38c04ac660a174b7c27ec Mon Sep 17 00:00:00 2001 From: Kamil Dudka Date: Wed, 2 Jun 2010 23:55:45 +0200 Subject: ftplistparser.c: oops, fix typo in the last commit --- lib/ftplistparser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index c5a2f8c45..ac6d07675 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -341,7 +341,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, /* filter pattern-corresponding filenames */ if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { /* discard symlink which is containing multiple " -> " */ - if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target + if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && (strstr(finfo->strings.target, " -> "))) { add = FALSE; } -- cgit v1.2.1 From 6a0d3233ffacec92ad230f74458454bf65a24eac Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 9 Jun 2010 15:45:46 +0200 Subject: add Curl_ prefix to conform with cURL naming standards --- lib/ftplistparser.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index ac6d07675..3dd661788 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -188,7 +188,7 @@ struct ftp_parselist_data { } offsets; }; -struct ftp_parselist_data *ftp_parselist_data_alloc(void) +struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) { struct ftp_parselist_data *parselist_data = malloc(sizeof(struct ftp_parselist_data)); @@ -199,7 +199,7 @@ struct ftp_parselist_data *ftp_parselist_data_alloc(void) } -void ftp_parselist_data_free(struct ftp_parselist_data **pl_data) +void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data) { if(*pl_data) free(*pl_data); @@ -207,7 +207,7 @@ void ftp_parselist_data_free(struct ftp_parselist_data **pl_data) } -CURLcode ftp_parselist_geterror(struct ftp_parselist_data *pl_data) +CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) { return pl_data->error; } @@ -365,7 +365,8 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, return CURLE_OK; } -size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) +size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, + void *connptr) { size_t bufflen = size*nmemb; struct connectdata *conn = (struct connectdata *)connptr; -- cgit v1.2.1 From 343c4c7072cd5ee16f1e444089db8c7e2ad92430 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Wed, 9 Jun 2010 16:48:19 +0200 Subject: code simplification --- lib/ftplistparser.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 3dd661788..08a794294 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -190,12 +190,7 @@ struct ftp_parselist_data { struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) { - struct ftp_parselist_data *parselist_data = - malloc(sizeof(struct ftp_parselist_data)); - if(!parselist_data) - return ZERO_NULL; - memset(parselist_data, 0, sizeof(struct ftp_parselist_data)); - return parselist_data; + return calloc(1, sizeof(struct ftp_parselist_data)); } -- cgit v1.2.1 From 88af6fbf98dd3091efacd32341e1d131cbfbfda5 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Thu, 10 Jun 2010 04:46:30 +0200 Subject: remove unused 'tmpdata' and 'backup' ftp_parselist_data struct members --- lib/ftplistparser.c | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 08a794294..77444bfd1 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -163,17 +163,6 @@ struct ftp_parselist_data { } NT; } state; - struct { - char *buffer; - size_t bufferlength; /* how many bytes is allocated at *buffer */ - size_t bufferin; /* how many bytes is in buffer */ - } tmpdata; - - struct { - curl_write_callback old_fwritefunc; - FILE *old_file_descriptor; - } backup; - CURLcode error; struct curl_fileinfo *file_data; unsigned int item_length; -- cgit v1.2.1 From f7ae7b36233db35c5e07686d4bf3286193576e27 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Thu, 24 Jun 2010 16:11:55 +0200 Subject: ftp wildcard: FTP LIST parser FIX There was a problem when a UNIX-like server returned information about directory size (total NNNNNN) at the first line of response. --- lib/ftplistparser.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 77444bfd1..c59ea7e16 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -61,7 +61,8 @@ #define FTP_BUFFER_ALLOCSIZE 160 typedef enum { - PL_UNIX_FILETYPE = 0, + PL_UNIX_TOTALSIZE = 0, + PL_UNIX_FILETYPE, PL_UNIX_PERMISSION, PL_UNIX_HLINKS, PL_UNIX_USER, @@ -73,6 +74,11 @@ typedef enum { } pl_unix_mainstate; typedef union { + enum { + PL_UNIX_TOTALSIZE_INIT = 0, + PL_UNIX_TOTALSIZE_READING + } total_dirsize; + enum { PL_UNIX_HLINKS_PRESPACE = 0, PL_UNIX_HLINKS_NUMBER @@ -396,7 +402,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } finfo = parser->file_data; - finfo->b_data[finfo->b_used++] = buffer[i]; + finfo->b_data[finfo->b_used++] = c; if(finfo->b_used >= finfo->b_size - 1) { /* if it is important, extend buffer space for file data */ @@ -418,6 +424,49 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, switch (parser->os_type) { case OS_TYPE_UNIX: switch (parser->state.UNIX.main) { + case PL_UNIX_TOTALSIZE: + switch(parser->state.UNIX.sub.total_dirsize) { + case PL_UNIX_TOTALSIZE_INIT: + if(c == 't') { + parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; + parser->item_length++; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + /* start FSM again not considering size of directory */ + finfo->b_used = 0; + i--; + } + break; + case PL_UNIX_TOTALSIZE_READING: + parser->item_length++; + if(c == '\r') { + parser->item_length--; + finfo->b_used--; + } + else if(c == '\n') { + finfo->b_data[parser->item_length - 1] = 0; + if(strncmp("total ", finfo->b_data, 6) == 0) { + char *endptr = NULL; + /* here we can deal with directory size */ + curlx_strtoofft(finfo->b_data+6, &endptr, 10); + if(*endptr != 0) { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + else { + parser->state.UNIX.main = PL_UNIX_FILETYPE; + finfo->b_used = 0; + } + } + else { + PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); + return bufflen; + } + } + break; + } + break; case PL_UNIX_FILETYPE: switch (c) { case '-': -- cgit v1.2.1 From 7f3b87d8782eae1803b9658e14788f5dcbb3aa6b Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sun, 19 Dec 2010 00:15:12 +0100 Subject: ftp_parselist: fix compiler warning Doing curlx_strtoofft() on the size just to figure out the end of it causes a compiler warning since the result wasn't used, but is also a bit of a waste. --- lib/ftplistparser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index c59ea7e16..6f7475337 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -447,9 +447,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, else if(c == '\n') { finfo->b_data[parser->item_length - 1] = 0; if(strncmp("total ", finfo->b_data, 6) == 0) { - char *endptr = NULL; + char *endptr = finfo->b_data+6; /* here we can deal with directory size */ - curlx_strtoofft(finfo->b_data+6, &endptr, 10); + while(ISSPACE(*endptr)) + endptr++; if(*endptr != 0) { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; -- cgit v1.2.1 From b903186fa0189ff241d756d25d07fdfe9885ae49 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Wed, 20 Apr 2011 15:17:42 +0200 Subject: source cleanup: unify look, style and indent levels By the use of a the new lib/checksrc.pl script that checks that our basic source style rules are followed. --- lib/ftplistparser.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 6f7475337..a3fef3971 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2010, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -329,7 +329,8 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, compare = Curl_fnmatch; /* filter pattern-corresponding filenames */ - if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) { + if(compare(conn->data->set.fnmatch_data, wc->pattern, + finfo->filename) == 0) { /* discard symlink which is containing multiple " -> " */ if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && (strstr(finfo->strings.target, " -> "))) { @@ -645,7 +646,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->state.UNIX.main = PL_UNIX_TIME; parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; } - else if (!ISDIGIT(c)) { + else if(!ISDIGIT(c)) { PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST); return bufflen; } @@ -960,7 +961,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, } else { char *endptr; - finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset, + finfo->size = curlx_strtoofft(finfo->b_data + + parser->item_offset, &endptr, 10); if(!*endptr) { if(finfo->size == CURL_OFF_T_MAX || -- cgit v1.2.1 From 0337b871975ab515c513d2c5d596feb9a489494d Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 25 Jul 2011 04:08:08 +0200 Subject: time.h and sys/time.h inclusion conditionally done in setup_once.h --- lib/ftplistparser.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index a3fef3971..bbf6e9ef9 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -37,8 +37,6 @@ #include "setup.h" -#include - #include "ftplistparser.h" #include "curl_fnmatch.h" -- cgit v1.2.1 From 119f43360b60c903982104944145d9cd8b7ec054 Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Sun, 25 Sep 2011 18:53:29 +0200 Subject: allow write callbacks to indicate OOM to libcurl Allow (*curl_write_callback) write callbacks to return CURL_WRITEFUNC_OUT_OF_MEMORY to properly indicate libcurl of OOM conditions inside the callback itself. --- lib/ftplistparser.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index bbf6e9ef9..12ee51d86 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -354,6 +354,8 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, return CURLE_OK; } +/* Curl_ftp_parselist is a write callback function */ + size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) { @@ -365,6 +367,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, unsigned long i = 0; CURLcode rc; + if(bufflen >= CURL_WRITEFUNC_PAUSE) + /* CURL_WRITEFUNC_PAUSE limits input size */ + return CURL_WRITEFUNC_OUT_OF_MEMORY; + if(parser->error) { /* error in previous call */ /* scenario: * 1. call => OK.. @@ -372,6 +378,9 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, * 3. (last) call => is skipped RIGHT HERE and the error is hadled later * in wc_statemach() */ + if(parser->error == CURLE_OUT_OF_MEMORY) + return CURL_WRITEFUNC_OUT_OF_MEMORY; + return bufflen; } @@ -388,12 +397,12 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->file_data = Curl_fileinfo_alloc(); if(!parser->file_data) { parser->error = CURLE_OUT_OF_MEMORY; - return bufflen; + return CURL_WRITEFUNC_OUT_OF_MEMORY; } parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); if(!parser->file_data->b_data) { PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return bufflen; + return CURL_WRITEFUNC_OUT_OF_MEMORY; } parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; parser->item_offset = 0; @@ -416,7 +425,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->file_data = NULL; parser->error = CURLE_OUT_OF_MEMORY; PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return bufflen; + return CURL_WRITEFUNC_OUT_OF_MEMORY; } } -- cgit v1.2.1 From d9f686db88cc6ed01af8f7d690a9e44b7dcfb6ee Mon Sep 17 00:00:00 2001 From: Yang Tse Date: Mon, 26 Sep 2011 03:18:51 +0200 Subject: remove short-lived CURL_WRITEFUNC_OUT_OF_MEMORY --- lib/ftplistparser.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index 12ee51d86..bbf6e9ef9 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -354,8 +354,6 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, return CURLE_OK; } -/* Curl_ftp_parselist is a write callback function */ - size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr) { @@ -367,10 +365,6 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, unsigned long i = 0; CURLcode rc; - if(bufflen >= CURL_WRITEFUNC_PAUSE) - /* CURL_WRITEFUNC_PAUSE limits input size */ - return CURL_WRITEFUNC_OUT_OF_MEMORY; - if(parser->error) { /* error in previous call */ /* scenario: * 1. call => OK.. @@ -378,9 +372,6 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, * 3. (last) call => is skipped RIGHT HERE and the error is hadled later * in wc_statemach() */ - if(parser->error == CURLE_OUT_OF_MEMORY) - return CURL_WRITEFUNC_OUT_OF_MEMORY; - return bufflen; } @@ -397,12 +388,12 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->file_data = Curl_fileinfo_alloc(); if(!parser->file_data) { parser->error = CURLE_OUT_OF_MEMORY; - return CURL_WRITEFUNC_OUT_OF_MEMORY; + return bufflen; } parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE); if(!parser->file_data->b_data) { PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return CURL_WRITEFUNC_OUT_OF_MEMORY; + return bufflen; } parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE; parser->item_offset = 0; @@ -425,7 +416,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, parser->file_data = NULL; parser->error = CURLE_OUT_OF_MEMORY; PL_ERROR(conn, CURLE_OUT_OF_MEMORY); - return CURL_WRITEFUNC_OUT_OF_MEMORY; + return bufflen; } } -- cgit v1.2.1 From 05f6f2497a9cd238e3314ab60ebbd8d816780a73 Mon Sep 17 00:00:00 2001 From: Mark Salisbury Date: Mon, 18 Jun 2012 13:06:02 +0200 Subject: ftplistparser.c: do not compile if FTP protocol is not enabled --- lib/ftplistparser.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'lib/ftplistparser.c') diff --git a/lib/ftplistparser.c b/lib/ftplistparser.c index bbf6e9ef9..49ee4b6a6 100644 --- a/lib/ftplistparser.c +++ b/lib/ftplistparser.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2011, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2012, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -37,16 +37,18 @@ #include "setup.h" -#include "ftplistparser.h" -#include "curl_fnmatch.h" +#ifndef CURL_DISABLE_FTP + +#include #include "urldata.h" -#include "ftp.h" #include "fileinfo.h" #include "llist.h" #include "strtoofft.h" #include "rawstr.h" #include "ftp.h" +#include "ftplistparser.h" +#include "curl_fnmatch.h" #define _MPRINTF_REPLACE /* use our functions only */ #include @@ -1044,3 +1046,5 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, return bufflen; } + +#endif /* CURL_DISABLE_FTP */ -- cgit v1.2.1