diff options
Diffstat (limited to 'libs/libcurl/src/ftplistparser.c')
-rw-r--r-- | libs/libcurl/src/ftplistparser.c | 1193 |
1 files changed, 582 insertions, 611 deletions
diff --git a/libs/libcurl/src/ftplistparser.c b/libs/libcurl/src/ftplistparser.c index 166f6771b5..67470bd55f 100644 --- a/libs/libcurl/src/ftplistparser.c +++ b/libs/libcurl/src/ftplistparser.c @@ -46,13 +46,15 @@ #include "urldata.h"
#include "fileinfo.h"
#include "llist.h"
-#include "strtoofft.h"
#include "ftp.h"
#include "ftplistparser.h"
#include "curl_fnmatch.h"
-#include "curl_memory.h"
#include "multiif.h"
-/* The last #include file should be: */
+#include "curlx/strparse.h"
+
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
+#include "curl_memory.h"
#include "memdebug.h"
typedef enum {
@@ -316,7 +318,7 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data, struct curl_fileinfo *finfo = &infop->info;
/* set the finfo pointers */
- char *str = Curl_dyn_ptr(&infop->buf);
+ char *str = curlx_dyn_ptr(&infop->buf);
finfo->filename = str + parser->offsets.filename;
finfo->strings.group = parser->offsets.group ?
str + parser->offsets.group : NULL;
@@ -361,6 +363,574 @@ static CURLcode ftp_pl_insert_finfo(struct Curl_easy *data, #define MAX_FTPLIST_BUFFER 10000 /* arbitrarily set */
+static CURLcode unix_filetype(const char c, curlfiletype *t)
+{
+ switch(c) {
+ case '-':
+ *t = CURLFILETYPE_FILE;
+ break;
+ case 'd':
+ *t = CURLFILETYPE_DIRECTORY;
+ break;
+ case 'l':
+ *t = CURLFILETYPE_SYMLINK;
+ break;
+ case 'p':
+ *t = CURLFILETYPE_NAMEDPIPE;
+ break;
+ case 's':
+ *t = CURLFILETYPE_SOCKET;
+ break;
+ case 'c':
+ *t = CURLFILETYPE_DEVICE_CHAR;
+ break;
+ case 'b':
+ *t = CURLFILETYPE_DEVICE_BLOCK;
+ break;
+ case 'D':
+ *t = CURLFILETYPE_DOOR;
+ break;
+ default:
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode parse_unix(struct Curl_easy *data,
+ struct ftp_parselist_data *parser,
+ struct fileinfo *infop,
+ const char c)
+{
+ struct curl_fileinfo *finfo = &infop->info;
+ size_t len = curlx_dyn_len(&infop->buf);
+ char *mem = curlx_dyn_ptr(&infop->buf);
+ CURLcode result = CURLE_OK;
+
+ 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;
+ /* continue to fall through */
+ }
+ break;
+ case PL_UNIX_TOTALSIZE_READING:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ if(len)
+ curlx_dyn_setlen(&infop->buf, --len);
+ }
+ else if(c == '\n') {
+ mem[parser->item_length - 1] = 0;
+ if(!strncmp("total ", mem, 6)) {
+ const char *endptr = mem + 6;
+ /* here we can deal with directory size, pass the leading
+ whitespace and then the digits */
+ curlx_str_passblanks(&endptr);
+ while(ISDIGIT(*endptr))
+ endptr++;
+ if(*endptr) {
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ curlx_dyn_reset(&infop->buf);
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ }
+ break;
+ }
+ if(parser->state.UNIX.main != PL_UNIX_FILETYPE)
+ break;
+ FALLTHROUGH();
+ case PL_UNIX_FILETYPE:
+ result = unix_filetype(c, &finfo->filetype);
+ if(result)
+ return result;
+ 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) && !strchr("rwx-tTsS", c))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ else if(parser->item_length == 10) {
+ unsigned int perm;
+ if(c != ' ')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ mem[10] = 0; /* terminate permissions */
+ perm = ftp_pl_get_permission(mem + parser->item_offset);
+ if(perm & FTP_LP_MALFORMATED_PERM)
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
+ parser->file_data->info.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(ISDIGIT(c) && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_HLINKS_NUMBER:
+ parser->item_length ++;
+ if(c == ' ') {
+ const char *p = &mem[parser->item_offset];
+ curl_off_t hlinks;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+
+ if(!curlx_str_number(&p, &hlinks, LONG_MAX)) {
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+ parser->file_data->info.hardlinks = (long)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(!ISDIGIT(c))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_USER:
+ switch(parser->state.UNIX.sub.user) {
+ case PL_UNIX_USER_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 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 == ' ') {
+ mem[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 != ' ' && len) {
+ parser->item_offset = len - 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 == ' ') {
+ mem[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.size = 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(ISDIGIT(c) && len) {
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_SIZE_NUMBER:
+ parser->item_length++;
+ if(c == ' ') {
+ const char *p = mem + parser->item_offset;
+ curl_off_t fsize;
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(!curlx_str_numblanks(&p, &fsize)) {
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX) {
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->info.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))
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_TIME:
+ switch(parser->state.UNIX.sub.time) {
+ case PL_UNIX_TIME_PREPART1:
+ if(c != ' ') {
+ if(ISALNUM(c) && len) {
+ parser->item_offset = len -1;
+ parser->item_length = 1;
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART1:
+ parser->item_length++;
+ if(c == ' ')
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
+
+ else if(!ISALNUM(c) && c != '.')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ case PL_UNIX_TIME_PREPART2:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c))
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART2:
+ parser->item_length++;
+ if(c == ' ')
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
+ else if(!ISALNUM(c) && c != '.')
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ case PL_UNIX_TIME_PREPART3:
+ parser->item_length++;
+ if(c != ' ') {
+ if(ISALNUM(c))
+ parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ break;
+ case PL_UNIX_TIME_PART3:
+ parser->item_length++;
+ if(c == ' ') {
+ mem[parser->item_offset + parser->item_length -1] = 0;
+ parser->offsets.time = parser->item_offset;
+ 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 != ':')
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ }
+ break;
+ case PL_UNIX_FILENAME:
+ switch(parser->state.UNIX.sub.filename) {
+ case PL_UNIX_FILENAME_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 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->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
+
+ else if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+ }
+ break;
+ case PL_UNIX_FILENAME_WINDOWSEOL:
+ if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.filename = parser->item_offset;
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ case PL_UNIX_SYMLINK:
+ switch(parser->state.UNIX.sub.symlink) {
+ case PL_UNIX_SYMLINK_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 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')
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ 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')
+ return CURLE_FTP_BAD_FILE_LIST;
+ 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')
+ return CURLE_FTP_BAD_FILE_LIST;
+ 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 */
+ mem[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')
+ return CURLE_FTP_BAD_FILE_LIST;
+ else
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
+ break;
+ case PL_UNIX_SYMLINK_PRETARGET4:
+ if(c != '\r' && c != '\n' && len) {
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
+ parser->item_offset = len - 1;
+ parser->item_length = 1;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ case PL_UNIX_SYMLINK_TARGET:
+ parser->item_length++;
+ if(c == '\r')
+ parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
+
+ else if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ break;
+ case PL_UNIX_SYMLINK_WINDOWSEOL:
+ if(c == '\n') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ parser->offsets.symlink_target = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ }
+ return CURLE_OK;
+}
+
+static CURLcode parse_winnt(struct Curl_easy *data,
+ struct ftp_parselist_data *parser,
+ struct fileinfo *infop,
+ const char c)
+{
+ struct curl_fileinfo *finfo = &infop->info;
+ size_t len = curlx_dyn_len(&infop->buf);
+ char *mem = curlx_dyn_ptr(&infop->buf);
+ CURLcode result = CURLE_OK;
+
+ switch(parser->state.NT.main) {
+ case PL_WINNT_DATE:
+ parser->item_length++;
+ if(parser->item_length < 9) {
+ if(!strchr("0123456789-", c)) { /* only simple control */
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ }
+ 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
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ case PL_WINNT_TIME:
+ parser->item_length++;
+ switch(parser->state.NT.sub.time) {
+ case PL_WINNT_TIME_PRESPACE:
+ if(!ISBLANK(c))
+ parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
+ break;
+ case PL_WINNT_TIME_TIME:
+ if(c == ' ') {
+ parser->offsets.time = parser->item_offset;
+ mem[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))
+ return CURLE_FTP_BAD_FILE_LIST;
+ break;
+ }
+ break;
+ case PL_WINNT_DIRORSIZE:
+ switch(parser->state.NT.sub.dirorsize) {
+ case PL_WINNT_DIRORSIZE_PRESPACE:
+ if(c != ' ' && len) {
+ parser->item_offset = len - 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 == ' ') {
+ mem[parser->item_offset + parser->item_length - 1] = 0;
+ if(strcmp("<DIR>", mem + parser->item_offset) == 0) {
+ finfo->filetype = CURLFILETYPE_DIRECTORY;
+ finfo->size = 0;
+ }
+ else {
+ const char *p = mem + parser->item_offset;
+ if(curlx_str_numblanks(&p, &finfo->size)) {
+ return CURLE_FTP_BAD_FILE_LIST;
+ }
+ /* correct file type */
+ parser->file_data->info.filetype = CURLFILETYPE_FILE;
+ }
+
+ parser->file_data->info.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 != ' ' && len) {
+ parser->item_offset = len -1;
+ parser->item_length = 1;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
+ }
+ break;
+ case PL_WINNT_FILENAME_CONTENT:
+ parser->item_length++;
+ if(!len)
+ return CURLE_FTP_BAD_FILE_LIST;
+ if(c == '\r') {
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
+ mem[len - 1] = 0;
+ }
+ else if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ mem[len - 1] = 0;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ break;
+ case PL_WINNT_FILENAME_WINEOL:
+ if(c == '\n') {
+ parser->offsets.filename = parser->item_offset;
+ result = ftp_pl_insert_finfo(data, infop);
+ if(result)
+ return result;
+
+ parser->state.NT.main = PL_WINNT_DATE;
+ parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
+ }
+ else
+ return CURLE_FTP_BAD_FILE_LIST;
+
+ break;
+ }
+ break;
+ }
+
+ return CURLE_OK;
+}
+
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
@@ -388,11 +958,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, }
while(i < bufflen) { /* FSM */
- char *mem;
- size_t len; /* number of bytes of data in the dynbuf */
char c = buffer[i];
struct fileinfo *infop;
- struct curl_fileinfo *finfo;
if(!parser->file_data) { /* tmp file data is not allocated yet */
parser->file_data = Curl_fileinfo_alloc();
if(!parser->file_data) {
@@ -401,627 +968,31 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, }
parser->item_offset = 0;
parser->item_length = 0;
- Curl_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER);
+ curlx_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER);
}
infop = parser->file_data;
- finfo = &infop->info;
- if(Curl_dyn_addn(&infop->buf, &c, 1)) {
+ if(curlx_dyn_addn(&infop->buf, &c, 1)) {
parser->error = CURLE_OUT_OF_MEMORY;
goto fail;
}
- len = Curl_dyn_len(&infop->buf);
- mem = Curl_dyn_ptr(&infop->buf);
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 */
- Curl_dyn_reset(&infop->buf);
- continue;
- }
- break;
- case PL_UNIX_TOTALSIZE_READING:
- parser->item_length++;
- if(c == '\r') {
- parser->item_length--;
- Curl_dyn_setlen(&infop->buf, --len);
- }
- else if(c == '\n') {
- mem[parser->item_length - 1] = 0;
- if(!strncmp("total ", mem, 6)) {
- char *endptr = mem + 6;
- /* here we can deal with directory size, pass the leading
- whitespace and then the digits */
- while(ISBLANK(*endptr))
- endptr++;
- while(ISDIGIT(*endptr))
- endptr++;
- if(*endptr) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- Curl_dyn_reset(&infop->buf);
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- }
- break;
- 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:
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- else if(parser->item_length == 10) {
- unsigned int perm;
- if(c != ' ') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- mem[10] = 0; /* terminate permissions */
- perm = ftp_pl_get_permission(mem + parser->item_offset);
- if(perm & FTP_LP_MALFORMATED_PERM) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
- parser->file_data->info.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(ISDIGIT(c)) {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_HLINKS_NUMBER:
- parser->item_length ++;
- if(c == ' ') {
- char *p;
- long int hlinks;
- mem[parser->item_offset + parser->item_length - 1] = 0;
- hlinks = strtol(mem + parser->item_offset, &p, 10);
- if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
- parser->file_data->info.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(!ISDIGIT(c)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_USER:
- switch(parser->state.UNIX.sub.user) {
- case PL_UNIX_USER_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 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 == ' ') {
- mem[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 = len - 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 == ' ') {
- mem[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.size = 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(ISDIGIT(c)) {
- parser->item_offset = len - 1;
- parser->item_length = 1;
- parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_SIZE_NUMBER:
- parser->item_length++;
- if(c == ' ') {
- char *p;
- curl_off_t fsize;
- mem[parser->item_offset + parser->item_length - 1] = 0;
- if(!curlx_strtoofft(mem + parser->item_offset,
- &p, 10, &fsize)) {
- if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
- fsize != CURL_OFF_T_MIN) {
- parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
- parser->file_data->info.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)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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 = len -1;
- parser->item_length = 1;
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART1:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
- }
- else if(!ISALNUM(c) && c != '.') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_TIME_PREPART2:
- parser->item_length++;
- if(c != ' ') {
- if(ISALNUM(c)) {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART2:
- parser->item_length++;
- if(c == ' ') {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
- }
- else if(!ISALNUM(c) && c != '.') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_TIME_PREPART3:
- parser->item_length++;
- if(c != ' ') {
- if(ISALNUM(c)) {
- parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- break;
- case PL_UNIX_TIME_PART3:
- parser->item_length++;
- if(c == ' ') {
- mem[parser->item_offset + parser->item_length -1] = 0;
- parser->offsets.time = parser->item_offset;
- /*
- if(ftp_pl_gettime(parser, finfo->mem + 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 != ':') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_FILENAME:
- switch(parser->state.UNIX.sub.filename) {
- case PL_UNIX_FILENAME_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 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->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
- }
- else if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.filename = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- }
- break;
- case PL_UNIX_FILENAME_WINDOWSEOL:
- if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.filename = parser->item_offset;
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_UNIX_SYMLINK:
- switch(parser->state.UNIX.sub.symlink) {
- case PL_UNIX_SYMLINK_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 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') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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 */
- mem[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') {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- 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 = len - 1;
- parser->item_length = 1;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_UNIX_SYMLINK_TARGET:
- parser->item_length++;
- if(c == '\r') {
- parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
- }
- else if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- }
- break;
- case PL_UNIX_SYMLINK_WINDOWSEOL:
- if(c == '\n') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.UNIX.main = PL_UNIX_FILETYPE;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- }
+ result = parse_unix(data, parser, infop, c);
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 */
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- 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 {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- case PL_WINNT_TIME:
- parser->item_length++;
- switch(parser->state.NT.sub.time) {
- case PL_WINNT_TIME_PRESPACE:
- if(!ISBLANK(c)) {
- parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
- }
- break;
- case PL_WINNT_TIME_TIME:
- if(c == ' ') {
- parser->offsets.time = parser->item_offset;
- mem[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)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- case PL_WINNT_DIRORSIZE:
- switch(parser->state.NT.sub.dirorsize) {
- case PL_WINNT_DIRORSIZE_PRESPACE:
- if(c != ' ') {
- parser->item_offset = len - 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 == ' ') {
- mem[parser->item_offset + parser->item_length - 1] = 0;
- if(strcmp("<DIR>", mem + parser->item_offset) == 0) {
- finfo->filetype = CURLFILETYPE_DIRECTORY;
- finfo->size = 0;
- }
- else {
- char *endptr;
- if(curlx_strtoofft(mem +
- parser->item_offset,
- &endptr, 10, &finfo->size)) {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- /* correct file type */
- parser->file_data->info.filetype = CURLFILETYPE_FILE;
- }
-
- parser->file_data->info.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 = len -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;
- mem[len - 1] = 0;
- }
- else if(c == '\n') {
- parser->offsets.filename = parser->item_offset;
- mem[len - 1] = 0;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.NT.main = PL_WINNT_DATE;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
- }
- break;
- case PL_WINNT_FILENAME_WINEOL:
- if(c == '\n') {
- parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(data, infop);
- if(result) {
- parser->error = result;
- goto fail;
- }
- parser->state.NT.main = PL_WINNT_DATE;
- parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
- }
- else {
- parser->error = CURLE_FTP_BAD_FILE_LIST;
- goto fail;
- }
- break;
- }
- break;
- }
+ result = parse_winnt(data, parser, infop, c);
break;
default:
retsize = bufflen + 1;
goto fail;
}
+ if(result) {
+ parser->error = result;
+ goto fail;
+ }
i++;
}
|