113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci/** 2613498266Sopenharmony_ci * Now implemented: 2713498266Sopenharmony_ci * 2813498266Sopenharmony_ci * 1) Unix version 1 2913498266Sopenharmony_ci * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog 3013498266Sopenharmony_ci * 2) Unix version 2 3113498266Sopenharmony_ci * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog 3213498266Sopenharmony_ci * 3) Unix version 3 3313498266Sopenharmony_ci * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog 3413498266Sopenharmony_ci * 4) Unix symlink 3513498266Sopenharmony_ci * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000 3613498266Sopenharmony_ci * 5) DOS style 3713498266Sopenharmony_ci * 01-29-97 11:32PM <DIR> prog 3813498266Sopenharmony_ci */ 3913498266Sopenharmony_ci 4013498266Sopenharmony_ci#include "curl_setup.h" 4113498266Sopenharmony_ci 4213498266Sopenharmony_ci#ifndef CURL_DISABLE_FTP 4313498266Sopenharmony_ci 4413498266Sopenharmony_ci#include <curl/curl.h> 4513498266Sopenharmony_ci 4613498266Sopenharmony_ci#include "urldata.h" 4713498266Sopenharmony_ci#include "fileinfo.h" 4813498266Sopenharmony_ci#include "llist.h" 4913498266Sopenharmony_ci#include "strtoofft.h" 5013498266Sopenharmony_ci#include "ftp.h" 5113498266Sopenharmony_ci#include "ftplistparser.h" 5213498266Sopenharmony_ci#include "curl_fnmatch.h" 5313498266Sopenharmony_ci#include "curl_memory.h" 5413498266Sopenharmony_ci#include "multiif.h" 5513498266Sopenharmony_ci/* The last #include file should be: */ 5613498266Sopenharmony_ci#include "memdebug.h" 5713498266Sopenharmony_ci 5813498266Sopenharmony_citypedef enum { 5913498266Sopenharmony_ci PL_UNIX_TOTALSIZE = 0, 6013498266Sopenharmony_ci PL_UNIX_FILETYPE, 6113498266Sopenharmony_ci PL_UNIX_PERMISSION, 6213498266Sopenharmony_ci PL_UNIX_HLINKS, 6313498266Sopenharmony_ci PL_UNIX_USER, 6413498266Sopenharmony_ci PL_UNIX_GROUP, 6513498266Sopenharmony_ci PL_UNIX_SIZE, 6613498266Sopenharmony_ci PL_UNIX_TIME, 6713498266Sopenharmony_ci PL_UNIX_FILENAME, 6813498266Sopenharmony_ci PL_UNIX_SYMLINK 6913498266Sopenharmony_ci} pl_unix_mainstate; 7013498266Sopenharmony_ci 7113498266Sopenharmony_citypedef union { 7213498266Sopenharmony_ci enum { 7313498266Sopenharmony_ci PL_UNIX_TOTALSIZE_INIT = 0, 7413498266Sopenharmony_ci PL_UNIX_TOTALSIZE_READING 7513498266Sopenharmony_ci } total_dirsize; 7613498266Sopenharmony_ci 7713498266Sopenharmony_ci enum { 7813498266Sopenharmony_ci PL_UNIX_HLINKS_PRESPACE = 0, 7913498266Sopenharmony_ci PL_UNIX_HLINKS_NUMBER 8013498266Sopenharmony_ci } hlinks; 8113498266Sopenharmony_ci 8213498266Sopenharmony_ci enum { 8313498266Sopenharmony_ci PL_UNIX_USER_PRESPACE = 0, 8413498266Sopenharmony_ci PL_UNIX_USER_PARSING 8513498266Sopenharmony_ci } user; 8613498266Sopenharmony_ci 8713498266Sopenharmony_ci enum { 8813498266Sopenharmony_ci PL_UNIX_GROUP_PRESPACE = 0, 8913498266Sopenharmony_ci PL_UNIX_GROUP_NAME 9013498266Sopenharmony_ci } group; 9113498266Sopenharmony_ci 9213498266Sopenharmony_ci enum { 9313498266Sopenharmony_ci PL_UNIX_SIZE_PRESPACE = 0, 9413498266Sopenharmony_ci PL_UNIX_SIZE_NUMBER 9513498266Sopenharmony_ci } size; 9613498266Sopenharmony_ci 9713498266Sopenharmony_ci enum { 9813498266Sopenharmony_ci PL_UNIX_TIME_PREPART1 = 0, 9913498266Sopenharmony_ci PL_UNIX_TIME_PART1, 10013498266Sopenharmony_ci PL_UNIX_TIME_PREPART2, 10113498266Sopenharmony_ci PL_UNIX_TIME_PART2, 10213498266Sopenharmony_ci PL_UNIX_TIME_PREPART3, 10313498266Sopenharmony_ci PL_UNIX_TIME_PART3 10413498266Sopenharmony_ci } time; 10513498266Sopenharmony_ci 10613498266Sopenharmony_ci enum { 10713498266Sopenharmony_ci PL_UNIX_FILENAME_PRESPACE = 0, 10813498266Sopenharmony_ci PL_UNIX_FILENAME_NAME, 10913498266Sopenharmony_ci PL_UNIX_FILENAME_WINDOWSEOL 11013498266Sopenharmony_ci } filename; 11113498266Sopenharmony_ci 11213498266Sopenharmony_ci enum { 11313498266Sopenharmony_ci PL_UNIX_SYMLINK_PRESPACE = 0, 11413498266Sopenharmony_ci PL_UNIX_SYMLINK_NAME, 11513498266Sopenharmony_ci PL_UNIX_SYMLINK_PRETARGET1, 11613498266Sopenharmony_ci PL_UNIX_SYMLINK_PRETARGET2, 11713498266Sopenharmony_ci PL_UNIX_SYMLINK_PRETARGET3, 11813498266Sopenharmony_ci PL_UNIX_SYMLINK_PRETARGET4, 11913498266Sopenharmony_ci PL_UNIX_SYMLINK_TARGET, 12013498266Sopenharmony_ci PL_UNIX_SYMLINK_WINDOWSEOL 12113498266Sopenharmony_ci } symlink; 12213498266Sopenharmony_ci} pl_unix_substate; 12313498266Sopenharmony_ci 12413498266Sopenharmony_citypedef enum { 12513498266Sopenharmony_ci PL_WINNT_DATE = 0, 12613498266Sopenharmony_ci PL_WINNT_TIME, 12713498266Sopenharmony_ci PL_WINNT_DIRORSIZE, 12813498266Sopenharmony_ci PL_WINNT_FILENAME 12913498266Sopenharmony_ci} pl_winNT_mainstate; 13013498266Sopenharmony_ci 13113498266Sopenharmony_citypedef union { 13213498266Sopenharmony_ci enum { 13313498266Sopenharmony_ci PL_WINNT_TIME_PRESPACE = 0, 13413498266Sopenharmony_ci PL_WINNT_TIME_TIME 13513498266Sopenharmony_ci } time; 13613498266Sopenharmony_ci enum { 13713498266Sopenharmony_ci PL_WINNT_DIRORSIZE_PRESPACE = 0, 13813498266Sopenharmony_ci PL_WINNT_DIRORSIZE_CONTENT 13913498266Sopenharmony_ci } dirorsize; 14013498266Sopenharmony_ci enum { 14113498266Sopenharmony_ci PL_WINNT_FILENAME_PRESPACE = 0, 14213498266Sopenharmony_ci PL_WINNT_FILENAME_CONTENT, 14313498266Sopenharmony_ci PL_WINNT_FILENAME_WINEOL 14413498266Sopenharmony_ci } filename; 14513498266Sopenharmony_ci} pl_winNT_substate; 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci/* This struct is used in wildcard downloading - for parsing LIST response */ 14813498266Sopenharmony_cistruct ftp_parselist_data { 14913498266Sopenharmony_ci enum { 15013498266Sopenharmony_ci OS_TYPE_UNKNOWN = 0, 15113498266Sopenharmony_ci OS_TYPE_UNIX, 15213498266Sopenharmony_ci OS_TYPE_WIN_NT 15313498266Sopenharmony_ci } os_type; 15413498266Sopenharmony_ci 15513498266Sopenharmony_ci union { 15613498266Sopenharmony_ci struct { 15713498266Sopenharmony_ci pl_unix_mainstate main; 15813498266Sopenharmony_ci pl_unix_substate sub; 15913498266Sopenharmony_ci } UNIX; 16013498266Sopenharmony_ci 16113498266Sopenharmony_ci struct { 16213498266Sopenharmony_ci pl_winNT_mainstate main; 16313498266Sopenharmony_ci pl_winNT_substate sub; 16413498266Sopenharmony_ci } NT; 16513498266Sopenharmony_ci } state; 16613498266Sopenharmony_ci 16713498266Sopenharmony_ci CURLcode error; 16813498266Sopenharmony_ci struct fileinfo *file_data; 16913498266Sopenharmony_ci unsigned int item_length; 17013498266Sopenharmony_ci size_t item_offset; 17113498266Sopenharmony_ci struct { 17213498266Sopenharmony_ci size_t filename; 17313498266Sopenharmony_ci size_t user; 17413498266Sopenharmony_ci size_t group; 17513498266Sopenharmony_ci size_t time; 17613498266Sopenharmony_ci size_t perm; 17713498266Sopenharmony_ci size_t symlink_target; 17813498266Sopenharmony_ci } offsets; 17913498266Sopenharmony_ci}; 18013498266Sopenharmony_ci 18113498266Sopenharmony_cistatic void fileinfo_dtor(void *user, void *element) 18213498266Sopenharmony_ci{ 18313498266Sopenharmony_ci (void)user; 18413498266Sopenharmony_ci Curl_fileinfo_cleanup(element); 18513498266Sopenharmony_ci} 18613498266Sopenharmony_ci 18713498266Sopenharmony_ciCURLcode Curl_wildcard_init(struct WildcardData *wc) 18813498266Sopenharmony_ci{ 18913498266Sopenharmony_ci Curl_llist_init(&wc->filelist, fileinfo_dtor); 19013498266Sopenharmony_ci wc->state = CURLWC_INIT; 19113498266Sopenharmony_ci 19213498266Sopenharmony_ci return CURLE_OK; 19313498266Sopenharmony_ci} 19413498266Sopenharmony_ci 19513498266Sopenharmony_civoid Curl_wildcard_dtor(struct WildcardData **wcp) 19613498266Sopenharmony_ci{ 19713498266Sopenharmony_ci struct WildcardData *wc = *wcp; 19813498266Sopenharmony_ci if(!wc) 19913498266Sopenharmony_ci return; 20013498266Sopenharmony_ci 20113498266Sopenharmony_ci if(wc->dtor) { 20213498266Sopenharmony_ci wc->dtor(wc->ftpwc); 20313498266Sopenharmony_ci wc->dtor = ZERO_NULL; 20413498266Sopenharmony_ci wc->ftpwc = NULL; 20513498266Sopenharmony_ci } 20613498266Sopenharmony_ci DEBUGASSERT(wc->ftpwc == NULL); 20713498266Sopenharmony_ci 20813498266Sopenharmony_ci Curl_llist_destroy(&wc->filelist, NULL); 20913498266Sopenharmony_ci free(wc->path); 21013498266Sopenharmony_ci wc->path = NULL; 21113498266Sopenharmony_ci free(wc->pattern); 21213498266Sopenharmony_ci wc->pattern = NULL; 21313498266Sopenharmony_ci wc->state = CURLWC_INIT; 21413498266Sopenharmony_ci free(wc); 21513498266Sopenharmony_ci *wcp = NULL; 21613498266Sopenharmony_ci} 21713498266Sopenharmony_ci 21813498266Sopenharmony_cistruct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void) 21913498266Sopenharmony_ci{ 22013498266Sopenharmony_ci return calloc(1, sizeof(struct ftp_parselist_data)); 22113498266Sopenharmony_ci} 22213498266Sopenharmony_ci 22313498266Sopenharmony_ci 22413498266Sopenharmony_civoid Curl_ftp_parselist_data_free(struct ftp_parselist_data **parserp) 22513498266Sopenharmony_ci{ 22613498266Sopenharmony_ci struct ftp_parselist_data *parser = *parserp; 22713498266Sopenharmony_ci if(parser) 22813498266Sopenharmony_ci Curl_fileinfo_cleanup(parser->file_data); 22913498266Sopenharmony_ci free(parser); 23013498266Sopenharmony_ci *parserp = NULL; 23113498266Sopenharmony_ci} 23213498266Sopenharmony_ci 23313498266Sopenharmony_ci 23413498266Sopenharmony_ciCURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data) 23513498266Sopenharmony_ci{ 23613498266Sopenharmony_ci return pl_data->error; 23713498266Sopenharmony_ci} 23813498266Sopenharmony_ci 23913498266Sopenharmony_ci 24013498266Sopenharmony_ci#define FTP_LP_MALFORMATED_PERM 0x01000000 24113498266Sopenharmony_ci 24213498266Sopenharmony_cistatic unsigned int ftp_pl_get_permission(const char *str) 24313498266Sopenharmony_ci{ 24413498266Sopenharmony_ci unsigned int permissions = 0; 24513498266Sopenharmony_ci /* USER */ 24613498266Sopenharmony_ci if(str[0] == 'r') 24713498266Sopenharmony_ci permissions |= 1 << 8; 24813498266Sopenharmony_ci else if(str[0] != '-') 24913498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 25013498266Sopenharmony_ci if(str[1] == 'w') 25113498266Sopenharmony_ci permissions |= 1 << 7; 25213498266Sopenharmony_ci else if(str[1] != '-') 25313498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 25413498266Sopenharmony_ci 25513498266Sopenharmony_ci if(str[2] == 'x') 25613498266Sopenharmony_ci permissions |= 1 << 6; 25713498266Sopenharmony_ci else if(str[2] == 's') { 25813498266Sopenharmony_ci permissions |= 1 << 6; 25913498266Sopenharmony_ci permissions |= 1 << 11; 26013498266Sopenharmony_ci } 26113498266Sopenharmony_ci else if(str[2] == 'S') 26213498266Sopenharmony_ci permissions |= 1 << 11; 26313498266Sopenharmony_ci else if(str[2] != '-') 26413498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 26513498266Sopenharmony_ci /* GROUP */ 26613498266Sopenharmony_ci if(str[3] == 'r') 26713498266Sopenharmony_ci permissions |= 1 << 5; 26813498266Sopenharmony_ci else if(str[3] != '-') 26913498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 27013498266Sopenharmony_ci if(str[4] == 'w') 27113498266Sopenharmony_ci permissions |= 1 << 4; 27213498266Sopenharmony_ci else if(str[4] != '-') 27313498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 27413498266Sopenharmony_ci if(str[5] == 'x') 27513498266Sopenharmony_ci permissions |= 1 << 3; 27613498266Sopenharmony_ci else if(str[5] == 's') { 27713498266Sopenharmony_ci permissions |= 1 << 3; 27813498266Sopenharmony_ci permissions |= 1 << 10; 27913498266Sopenharmony_ci } 28013498266Sopenharmony_ci else if(str[5] == 'S') 28113498266Sopenharmony_ci permissions |= 1 << 10; 28213498266Sopenharmony_ci else if(str[5] != '-') 28313498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 28413498266Sopenharmony_ci /* others */ 28513498266Sopenharmony_ci if(str[6] == 'r') 28613498266Sopenharmony_ci permissions |= 1 << 2; 28713498266Sopenharmony_ci else if(str[6] != '-') 28813498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 28913498266Sopenharmony_ci if(str[7] == 'w') 29013498266Sopenharmony_ci permissions |= 1 << 1; 29113498266Sopenharmony_ci else if(str[7] != '-') 29213498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 29313498266Sopenharmony_ci if(str[8] == 'x') 29413498266Sopenharmony_ci permissions |= 1; 29513498266Sopenharmony_ci else if(str[8] == 't') { 29613498266Sopenharmony_ci permissions |= 1; 29713498266Sopenharmony_ci permissions |= 1 << 9; 29813498266Sopenharmony_ci } 29913498266Sopenharmony_ci else if(str[8] == 'T') 30013498266Sopenharmony_ci permissions |= 1 << 9; 30113498266Sopenharmony_ci else if(str[8] != '-') 30213498266Sopenharmony_ci permissions |= FTP_LP_MALFORMATED_PERM; 30313498266Sopenharmony_ci 30413498266Sopenharmony_ci return permissions; 30513498266Sopenharmony_ci} 30613498266Sopenharmony_ci 30713498266Sopenharmony_cistatic CURLcode ftp_pl_insert_finfo(struct Curl_easy *data, 30813498266Sopenharmony_ci struct fileinfo *infop) 30913498266Sopenharmony_ci{ 31013498266Sopenharmony_ci curl_fnmatch_callback compare; 31113498266Sopenharmony_ci struct WildcardData *wc = data->wildcard; 31213498266Sopenharmony_ci struct ftp_wc *ftpwc = wc->ftpwc; 31313498266Sopenharmony_ci struct Curl_llist *llist = &wc->filelist; 31413498266Sopenharmony_ci struct ftp_parselist_data *parser = ftpwc->parser; 31513498266Sopenharmony_ci bool add = TRUE; 31613498266Sopenharmony_ci struct curl_fileinfo *finfo = &infop->info; 31713498266Sopenharmony_ci 31813498266Sopenharmony_ci /* set the finfo pointers */ 31913498266Sopenharmony_ci char *str = Curl_dyn_ptr(&infop->buf); 32013498266Sopenharmony_ci finfo->filename = str + parser->offsets.filename; 32113498266Sopenharmony_ci finfo->strings.group = parser->offsets.group ? 32213498266Sopenharmony_ci str + parser->offsets.group : NULL; 32313498266Sopenharmony_ci finfo->strings.perm = parser->offsets.perm ? 32413498266Sopenharmony_ci str + parser->offsets.perm : NULL; 32513498266Sopenharmony_ci finfo->strings.target = parser->offsets.symlink_target ? 32613498266Sopenharmony_ci str + parser->offsets.symlink_target : NULL; 32713498266Sopenharmony_ci finfo->strings.time = str + parser->offsets.time; 32813498266Sopenharmony_ci finfo->strings.user = parser->offsets.user ? 32913498266Sopenharmony_ci str + parser->offsets.user : NULL; 33013498266Sopenharmony_ci 33113498266Sopenharmony_ci /* get correct fnmatch callback */ 33213498266Sopenharmony_ci compare = data->set.fnmatch; 33313498266Sopenharmony_ci if(!compare) 33413498266Sopenharmony_ci compare = Curl_fnmatch; 33513498266Sopenharmony_ci 33613498266Sopenharmony_ci /* filter pattern-corresponding filenames */ 33713498266Sopenharmony_ci Curl_set_in_callback(data, true); 33813498266Sopenharmony_ci if(compare(data->set.fnmatch_data, wc->pattern, 33913498266Sopenharmony_ci finfo->filename) == 0) { 34013498266Sopenharmony_ci /* discard symlink which is containing multiple " -> " */ 34113498266Sopenharmony_ci if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target && 34213498266Sopenharmony_ci (strstr(finfo->strings.target, " -> "))) { 34313498266Sopenharmony_ci add = FALSE; 34413498266Sopenharmony_ci } 34513498266Sopenharmony_ci } 34613498266Sopenharmony_ci else { 34713498266Sopenharmony_ci add = FALSE; 34813498266Sopenharmony_ci } 34913498266Sopenharmony_ci Curl_set_in_callback(data, false); 35013498266Sopenharmony_ci 35113498266Sopenharmony_ci if(add) { 35213498266Sopenharmony_ci Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list); 35313498266Sopenharmony_ci } 35413498266Sopenharmony_ci else { 35513498266Sopenharmony_ci Curl_fileinfo_cleanup(infop); 35613498266Sopenharmony_ci } 35713498266Sopenharmony_ci 35813498266Sopenharmony_ci ftpwc->parser->file_data = NULL; 35913498266Sopenharmony_ci return CURLE_OK; 36013498266Sopenharmony_ci} 36113498266Sopenharmony_ci 36213498266Sopenharmony_ci#define MAX_FTPLIST_BUFFER 10000 /* arbitrarily set */ 36313498266Sopenharmony_ci 36413498266Sopenharmony_cisize_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, 36513498266Sopenharmony_ci void *connptr) 36613498266Sopenharmony_ci{ 36713498266Sopenharmony_ci size_t bufflen = size*nmemb; 36813498266Sopenharmony_ci struct Curl_easy *data = (struct Curl_easy *)connptr; 36913498266Sopenharmony_ci struct ftp_wc *ftpwc = data->wildcard->ftpwc; 37013498266Sopenharmony_ci struct ftp_parselist_data *parser = ftpwc->parser; 37113498266Sopenharmony_ci size_t i = 0; 37213498266Sopenharmony_ci CURLcode result; 37313498266Sopenharmony_ci size_t retsize = bufflen; 37413498266Sopenharmony_ci 37513498266Sopenharmony_ci if(parser->error) { /* error in previous call */ 37613498266Sopenharmony_ci /* scenario: 37713498266Sopenharmony_ci * 1. call => OK.. 37813498266Sopenharmony_ci * 2. call => OUT_OF_MEMORY (or other error) 37913498266Sopenharmony_ci * 3. (last) call => is skipped RIGHT HERE and the error is handled later 38013498266Sopenharmony_ci * in wc_statemach() 38113498266Sopenharmony_ci */ 38213498266Sopenharmony_ci goto fail; 38313498266Sopenharmony_ci } 38413498266Sopenharmony_ci 38513498266Sopenharmony_ci if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) { 38613498266Sopenharmony_ci /* considering info about FILE response format */ 38713498266Sopenharmony_ci parser->os_type = ISDIGIT(buffer[0]) ? OS_TYPE_WIN_NT : OS_TYPE_UNIX; 38813498266Sopenharmony_ci } 38913498266Sopenharmony_ci 39013498266Sopenharmony_ci while(i < bufflen) { /* FSM */ 39113498266Sopenharmony_ci char *mem; 39213498266Sopenharmony_ci size_t len; /* number of bytes of data in the dynbuf */ 39313498266Sopenharmony_ci char c = buffer[i]; 39413498266Sopenharmony_ci struct fileinfo *infop; 39513498266Sopenharmony_ci struct curl_fileinfo *finfo; 39613498266Sopenharmony_ci if(!parser->file_data) { /* tmp file data is not allocated yet */ 39713498266Sopenharmony_ci parser->file_data = Curl_fileinfo_alloc(); 39813498266Sopenharmony_ci if(!parser->file_data) { 39913498266Sopenharmony_ci parser->error = CURLE_OUT_OF_MEMORY; 40013498266Sopenharmony_ci goto fail; 40113498266Sopenharmony_ci } 40213498266Sopenharmony_ci parser->item_offset = 0; 40313498266Sopenharmony_ci parser->item_length = 0; 40413498266Sopenharmony_ci Curl_dyn_init(&parser->file_data->buf, MAX_FTPLIST_BUFFER); 40513498266Sopenharmony_ci } 40613498266Sopenharmony_ci 40713498266Sopenharmony_ci infop = parser->file_data; 40813498266Sopenharmony_ci finfo = &infop->info; 40913498266Sopenharmony_ci 41013498266Sopenharmony_ci if(Curl_dyn_addn(&infop->buf, &c, 1)) { 41113498266Sopenharmony_ci parser->error = CURLE_OUT_OF_MEMORY; 41213498266Sopenharmony_ci goto fail; 41313498266Sopenharmony_ci } 41413498266Sopenharmony_ci len = Curl_dyn_len(&infop->buf); 41513498266Sopenharmony_ci mem = Curl_dyn_ptr(&infop->buf); 41613498266Sopenharmony_ci 41713498266Sopenharmony_ci switch(parser->os_type) { 41813498266Sopenharmony_ci case OS_TYPE_UNIX: 41913498266Sopenharmony_ci switch(parser->state.UNIX.main) { 42013498266Sopenharmony_ci case PL_UNIX_TOTALSIZE: 42113498266Sopenharmony_ci switch(parser->state.UNIX.sub.total_dirsize) { 42213498266Sopenharmony_ci case PL_UNIX_TOTALSIZE_INIT: 42313498266Sopenharmony_ci if(c == 't') { 42413498266Sopenharmony_ci parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING; 42513498266Sopenharmony_ci parser->item_length++; 42613498266Sopenharmony_ci } 42713498266Sopenharmony_ci else { 42813498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 42913498266Sopenharmony_ci /* start FSM again not considering size of directory */ 43013498266Sopenharmony_ci Curl_dyn_reset(&infop->buf); 43113498266Sopenharmony_ci continue; 43213498266Sopenharmony_ci } 43313498266Sopenharmony_ci break; 43413498266Sopenharmony_ci case PL_UNIX_TOTALSIZE_READING: 43513498266Sopenharmony_ci parser->item_length++; 43613498266Sopenharmony_ci if(c == '\r') { 43713498266Sopenharmony_ci parser->item_length--; 43813498266Sopenharmony_ci Curl_dyn_setlen(&infop->buf, --len); 43913498266Sopenharmony_ci } 44013498266Sopenharmony_ci else if(c == '\n') { 44113498266Sopenharmony_ci mem[parser->item_length - 1] = 0; 44213498266Sopenharmony_ci if(!strncmp("total ", mem, 6)) { 44313498266Sopenharmony_ci char *endptr = mem + 6; 44413498266Sopenharmony_ci /* here we can deal with directory size, pass the leading 44513498266Sopenharmony_ci whitespace and then the digits */ 44613498266Sopenharmony_ci while(ISBLANK(*endptr)) 44713498266Sopenharmony_ci endptr++; 44813498266Sopenharmony_ci while(ISDIGIT(*endptr)) 44913498266Sopenharmony_ci endptr++; 45013498266Sopenharmony_ci if(*endptr) { 45113498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 45213498266Sopenharmony_ci goto fail; 45313498266Sopenharmony_ci } 45413498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 45513498266Sopenharmony_ci Curl_dyn_reset(&infop->buf); 45613498266Sopenharmony_ci } 45713498266Sopenharmony_ci else { 45813498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 45913498266Sopenharmony_ci goto fail; 46013498266Sopenharmony_ci } 46113498266Sopenharmony_ci } 46213498266Sopenharmony_ci break; 46313498266Sopenharmony_ci } 46413498266Sopenharmony_ci break; 46513498266Sopenharmony_ci case PL_UNIX_FILETYPE: 46613498266Sopenharmony_ci switch(c) { 46713498266Sopenharmony_ci case '-': 46813498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_FILE; 46913498266Sopenharmony_ci break; 47013498266Sopenharmony_ci case 'd': 47113498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_DIRECTORY; 47213498266Sopenharmony_ci break; 47313498266Sopenharmony_ci case 'l': 47413498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_SYMLINK; 47513498266Sopenharmony_ci break; 47613498266Sopenharmony_ci case 'p': 47713498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_NAMEDPIPE; 47813498266Sopenharmony_ci break; 47913498266Sopenharmony_ci case 's': 48013498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_SOCKET; 48113498266Sopenharmony_ci break; 48213498266Sopenharmony_ci case 'c': 48313498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_DEVICE_CHAR; 48413498266Sopenharmony_ci break; 48513498266Sopenharmony_ci case 'b': 48613498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_DEVICE_BLOCK; 48713498266Sopenharmony_ci break; 48813498266Sopenharmony_ci case 'D': 48913498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_DOOR; 49013498266Sopenharmony_ci break; 49113498266Sopenharmony_ci default: 49213498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 49313498266Sopenharmony_ci goto fail; 49413498266Sopenharmony_ci } 49513498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_PERMISSION; 49613498266Sopenharmony_ci parser->item_length = 0; 49713498266Sopenharmony_ci parser->item_offset = 1; 49813498266Sopenharmony_ci break; 49913498266Sopenharmony_ci case PL_UNIX_PERMISSION: 50013498266Sopenharmony_ci parser->item_length++; 50113498266Sopenharmony_ci if(parser->item_length <= 9) { 50213498266Sopenharmony_ci if(!strchr("rwx-tTsS", c)) { 50313498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 50413498266Sopenharmony_ci goto fail; 50513498266Sopenharmony_ci } 50613498266Sopenharmony_ci } 50713498266Sopenharmony_ci else if(parser->item_length == 10) { 50813498266Sopenharmony_ci unsigned int perm; 50913498266Sopenharmony_ci if(c != ' ') { 51013498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 51113498266Sopenharmony_ci goto fail; 51213498266Sopenharmony_ci } 51313498266Sopenharmony_ci mem[10] = 0; /* terminate permissions */ 51413498266Sopenharmony_ci perm = ftp_pl_get_permission(mem + parser->item_offset); 51513498266Sopenharmony_ci if(perm & FTP_LP_MALFORMATED_PERM) { 51613498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 51713498266Sopenharmony_ci goto fail; 51813498266Sopenharmony_ci } 51913498266Sopenharmony_ci parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM; 52013498266Sopenharmony_ci parser->file_data->info.perm = perm; 52113498266Sopenharmony_ci parser->offsets.perm = parser->item_offset; 52213498266Sopenharmony_ci 52313498266Sopenharmony_ci parser->item_length = 0; 52413498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_HLINKS; 52513498266Sopenharmony_ci parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE; 52613498266Sopenharmony_ci } 52713498266Sopenharmony_ci break; 52813498266Sopenharmony_ci case PL_UNIX_HLINKS: 52913498266Sopenharmony_ci switch(parser->state.UNIX.sub.hlinks) { 53013498266Sopenharmony_ci case PL_UNIX_HLINKS_PRESPACE: 53113498266Sopenharmony_ci if(c != ' ') { 53213498266Sopenharmony_ci if(ISDIGIT(c)) { 53313498266Sopenharmony_ci parser->item_offset = len - 1; 53413498266Sopenharmony_ci parser->item_length = 1; 53513498266Sopenharmony_ci parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER; 53613498266Sopenharmony_ci } 53713498266Sopenharmony_ci else { 53813498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 53913498266Sopenharmony_ci goto fail; 54013498266Sopenharmony_ci } 54113498266Sopenharmony_ci } 54213498266Sopenharmony_ci break; 54313498266Sopenharmony_ci case PL_UNIX_HLINKS_NUMBER: 54413498266Sopenharmony_ci parser->item_length ++; 54513498266Sopenharmony_ci if(c == ' ') { 54613498266Sopenharmony_ci char *p; 54713498266Sopenharmony_ci long int hlinks; 54813498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 54913498266Sopenharmony_ci hlinks = strtol(mem + parser->item_offset, &p, 10); 55013498266Sopenharmony_ci if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) { 55113498266Sopenharmony_ci parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT; 55213498266Sopenharmony_ci parser->file_data->info.hardlinks = hlinks; 55313498266Sopenharmony_ci } 55413498266Sopenharmony_ci parser->item_length = 0; 55513498266Sopenharmony_ci parser->item_offset = 0; 55613498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_USER; 55713498266Sopenharmony_ci parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE; 55813498266Sopenharmony_ci } 55913498266Sopenharmony_ci else if(!ISDIGIT(c)) { 56013498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 56113498266Sopenharmony_ci goto fail; 56213498266Sopenharmony_ci } 56313498266Sopenharmony_ci break; 56413498266Sopenharmony_ci } 56513498266Sopenharmony_ci break; 56613498266Sopenharmony_ci case PL_UNIX_USER: 56713498266Sopenharmony_ci switch(parser->state.UNIX.sub.user) { 56813498266Sopenharmony_ci case PL_UNIX_USER_PRESPACE: 56913498266Sopenharmony_ci if(c != ' ') { 57013498266Sopenharmony_ci parser->item_offset = len - 1; 57113498266Sopenharmony_ci parser->item_length = 1; 57213498266Sopenharmony_ci parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING; 57313498266Sopenharmony_ci } 57413498266Sopenharmony_ci break; 57513498266Sopenharmony_ci case PL_UNIX_USER_PARSING: 57613498266Sopenharmony_ci parser->item_length++; 57713498266Sopenharmony_ci if(c == ' ') { 57813498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 57913498266Sopenharmony_ci parser->offsets.user = parser->item_offset; 58013498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_GROUP; 58113498266Sopenharmony_ci parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE; 58213498266Sopenharmony_ci parser->item_offset = 0; 58313498266Sopenharmony_ci parser->item_length = 0; 58413498266Sopenharmony_ci } 58513498266Sopenharmony_ci break; 58613498266Sopenharmony_ci } 58713498266Sopenharmony_ci break; 58813498266Sopenharmony_ci case PL_UNIX_GROUP: 58913498266Sopenharmony_ci switch(parser->state.UNIX.sub.group) { 59013498266Sopenharmony_ci case PL_UNIX_GROUP_PRESPACE: 59113498266Sopenharmony_ci if(c != ' ') { 59213498266Sopenharmony_ci parser->item_offset = len - 1; 59313498266Sopenharmony_ci parser->item_length = 1; 59413498266Sopenharmony_ci parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME; 59513498266Sopenharmony_ci } 59613498266Sopenharmony_ci break; 59713498266Sopenharmony_ci case PL_UNIX_GROUP_NAME: 59813498266Sopenharmony_ci parser->item_length++; 59913498266Sopenharmony_ci if(c == ' ') { 60013498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 60113498266Sopenharmony_ci parser->offsets.group = parser->item_offset; 60213498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_SIZE; 60313498266Sopenharmony_ci parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE; 60413498266Sopenharmony_ci parser->item_offset = 0; 60513498266Sopenharmony_ci parser->item_length = 0; 60613498266Sopenharmony_ci } 60713498266Sopenharmony_ci break; 60813498266Sopenharmony_ci } 60913498266Sopenharmony_ci break; 61013498266Sopenharmony_ci case PL_UNIX_SIZE: 61113498266Sopenharmony_ci switch(parser->state.UNIX.sub.size) { 61213498266Sopenharmony_ci case PL_UNIX_SIZE_PRESPACE: 61313498266Sopenharmony_ci if(c != ' ') { 61413498266Sopenharmony_ci if(ISDIGIT(c)) { 61513498266Sopenharmony_ci parser->item_offset = len - 1; 61613498266Sopenharmony_ci parser->item_length = 1; 61713498266Sopenharmony_ci parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER; 61813498266Sopenharmony_ci } 61913498266Sopenharmony_ci else { 62013498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 62113498266Sopenharmony_ci goto fail; 62213498266Sopenharmony_ci } 62313498266Sopenharmony_ci } 62413498266Sopenharmony_ci break; 62513498266Sopenharmony_ci case PL_UNIX_SIZE_NUMBER: 62613498266Sopenharmony_ci parser->item_length++; 62713498266Sopenharmony_ci if(c == ' ') { 62813498266Sopenharmony_ci char *p; 62913498266Sopenharmony_ci curl_off_t fsize; 63013498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 63113498266Sopenharmony_ci if(!curlx_strtoofft(mem + parser->item_offset, 63213498266Sopenharmony_ci &p, 10, &fsize)) { 63313498266Sopenharmony_ci if(p[0] == '\0' && fsize != CURL_OFF_T_MAX && 63413498266Sopenharmony_ci fsize != CURL_OFF_T_MIN) { 63513498266Sopenharmony_ci parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; 63613498266Sopenharmony_ci parser->file_data->info.size = fsize; 63713498266Sopenharmony_ci } 63813498266Sopenharmony_ci parser->item_length = 0; 63913498266Sopenharmony_ci parser->item_offset = 0; 64013498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_TIME; 64113498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1; 64213498266Sopenharmony_ci } 64313498266Sopenharmony_ci } 64413498266Sopenharmony_ci else if(!ISDIGIT(c)) { 64513498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 64613498266Sopenharmony_ci goto fail; 64713498266Sopenharmony_ci } 64813498266Sopenharmony_ci break; 64913498266Sopenharmony_ci } 65013498266Sopenharmony_ci break; 65113498266Sopenharmony_ci case PL_UNIX_TIME: 65213498266Sopenharmony_ci switch(parser->state.UNIX.sub.time) { 65313498266Sopenharmony_ci case PL_UNIX_TIME_PREPART1: 65413498266Sopenharmony_ci if(c != ' ') { 65513498266Sopenharmony_ci if(ISALNUM(c)) { 65613498266Sopenharmony_ci parser->item_offset = len -1; 65713498266Sopenharmony_ci parser->item_length = 1; 65813498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1; 65913498266Sopenharmony_ci } 66013498266Sopenharmony_ci else { 66113498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 66213498266Sopenharmony_ci goto fail; 66313498266Sopenharmony_ci } 66413498266Sopenharmony_ci } 66513498266Sopenharmony_ci break; 66613498266Sopenharmony_ci case PL_UNIX_TIME_PART1: 66713498266Sopenharmony_ci parser->item_length++; 66813498266Sopenharmony_ci if(c == ' ') { 66913498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2; 67013498266Sopenharmony_ci } 67113498266Sopenharmony_ci else if(!ISALNUM(c) && c != '.') { 67213498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 67313498266Sopenharmony_ci goto fail; 67413498266Sopenharmony_ci } 67513498266Sopenharmony_ci break; 67613498266Sopenharmony_ci case PL_UNIX_TIME_PREPART2: 67713498266Sopenharmony_ci parser->item_length++; 67813498266Sopenharmony_ci if(c != ' ') { 67913498266Sopenharmony_ci if(ISALNUM(c)) { 68013498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2; 68113498266Sopenharmony_ci } 68213498266Sopenharmony_ci else { 68313498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 68413498266Sopenharmony_ci goto fail; 68513498266Sopenharmony_ci } 68613498266Sopenharmony_ci } 68713498266Sopenharmony_ci break; 68813498266Sopenharmony_ci case PL_UNIX_TIME_PART2: 68913498266Sopenharmony_ci parser->item_length++; 69013498266Sopenharmony_ci if(c == ' ') { 69113498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3; 69213498266Sopenharmony_ci } 69313498266Sopenharmony_ci else if(!ISALNUM(c) && c != '.') { 69413498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 69513498266Sopenharmony_ci goto fail; 69613498266Sopenharmony_ci } 69713498266Sopenharmony_ci break; 69813498266Sopenharmony_ci case PL_UNIX_TIME_PREPART3: 69913498266Sopenharmony_ci parser->item_length++; 70013498266Sopenharmony_ci if(c != ' ') { 70113498266Sopenharmony_ci if(ISALNUM(c)) { 70213498266Sopenharmony_ci parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3; 70313498266Sopenharmony_ci } 70413498266Sopenharmony_ci else { 70513498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 70613498266Sopenharmony_ci goto fail; 70713498266Sopenharmony_ci } 70813498266Sopenharmony_ci } 70913498266Sopenharmony_ci break; 71013498266Sopenharmony_ci case PL_UNIX_TIME_PART3: 71113498266Sopenharmony_ci parser->item_length++; 71213498266Sopenharmony_ci if(c == ' ') { 71313498266Sopenharmony_ci mem[parser->item_offset + parser->item_length -1] = 0; 71413498266Sopenharmony_ci parser->offsets.time = parser->item_offset; 71513498266Sopenharmony_ci /* 71613498266Sopenharmony_ci if(ftp_pl_gettime(parser, finfo->mem + parser->item_offset)) { 71713498266Sopenharmony_ci parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME; 71813498266Sopenharmony_ci } 71913498266Sopenharmony_ci */ 72013498266Sopenharmony_ci if(finfo->filetype == CURLFILETYPE_SYMLINK) { 72113498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_SYMLINK; 72213498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE; 72313498266Sopenharmony_ci } 72413498266Sopenharmony_ci else { 72513498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILENAME; 72613498266Sopenharmony_ci parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE; 72713498266Sopenharmony_ci } 72813498266Sopenharmony_ci } 72913498266Sopenharmony_ci else if(!ISALNUM(c) && c != '.' && c != ':') { 73013498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 73113498266Sopenharmony_ci goto fail; 73213498266Sopenharmony_ci } 73313498266Sopenharmony_ci break; 73413498266Sopenharmony_ci } 73513498266Sopenharmony_ci break; 73613498266Sopenharmony_ci case PL_UNIX_FILENAME: 73713498266Sopenharmony_ci switch(parser->state.UNIX.sub.filename) { 73813498266Sopenharmony_ci case PL_UNIX_FILENAME_PRESPACE: 73913498266Sopenharmony_ci if(c != ' ') { 74013498266Sopenharmony_ci parser->item_offset = len - 1; 74113498266Sopenharmony_ci parser->item_length = 1; 74213498266Sopenharmony_ci parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME; 74313498266Sopenharmony_ci } 74413498266Sopenharmony_ci break; 74513498266Sopenharmony_ci case PL_UNIX_FILENAME_NAME: 74613498266Sopenharmony_ci parser->item_length++; 74713498266Sopenharmony_ci if(c == '\r') { 74813498266Sopenharmony_ci parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL; 74913498266Sopenharmony_ci } 75013498266Sopenharmony_ci else if(c == '\n') { 75113498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 75213498266Sopenharmony_ci parser->offsets.filename = parser->item_offset; 75313498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 75413498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 75513498266Sopenharmony_ci if(result) { 75613498266Sopenharmony_ci parser->error = result; 75713498266Sopenharmony_ci goto fail; 75813498266Sopenharmony_ci } 75913498266Sopenharmony_ci } 76013498266Sopenharmony_ci break; 76113498266Sopenharmony_ci case PL_UNIX_FILENAME_WINDOWSEOL: 76213498266Sopenharmony_ci if(c == '\n') { 76313498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 76413498266Sopenharmony_ci parser->offsets.filename = parser->item_offset; 76513498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 76613498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 76713498266Sopenharmony_ci if(result) { 76813498266Sopenharmony_ci parser->error = result; 76913498266Sopenharmony_ci goto fail; 77013498266Sopenharmony_ci } 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci else { 77313498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 77413498266Sopenharmony_ci goto fail; 77513498266Sopenharmony_ci } 77613498266Sopenharmony_ci break; 77713498266Sopenharmony_ci } 77813498266Sopenharmony_ci break; 77913498266Sopenharmony_ci case PL_UNIX_SYMLINK: 78013498266Sopenharmony_ci switch(parser->state.UNIX.sub.symlink) { 78113498266Sopenharmony_ci case PL_UNIX_SYMLINK_PRESPACE: 78213498266Sopenharmony_ci if(c != ' ') { 78313498266Sopenharmony_ci parser->item_offset = len - 1; 78413498266Sopenharmony_ci parser->item_length = 1; 78513498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; 78613498266Sopenharmony_ci } 78713498266Sopenharmony_ci break; 78813498266Sopenharmony_ci case PL_UNIX_SYMLINK_NAME: 78913498266Sopenharmony_ci parser->item_length++; 79013498266Sopenharmony_ci if(c == ' ') { 79113498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1; 79213498266Sopenharmony_ci } 79313498266Sopenharmony_ci else if(c == '\r' || c == '\n') { 79413498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 79513498266Sopenharmony_ci goto fail; 79613498266Sopenharmony_ci } 79713498266Sopenharmony_ci break; 79813498266Sopenharmony_ci case PL_UNIX_SYMLINK_PRETARGET1: 79913498266Sopenharmony_ci parser->item_length++; 80013498266Sopenharmony_ci if(c == '-') { 80113498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2; 80213498266Sopenharmony_ci } 80313498266Sopenharmony_ci else if(c == '\r' || c == '\n') { 80413498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 80513498266Sopenharmony_ci goto fail; 80613498266Sopenharmony_ci } 80713498266Sopenharmony_ci else { 80813498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; 80913498266Sopenharmony_ci } 81013498266Sopenharmony_ci break; 81113498266Sopenharmony_ci case PL_UNIX_SYMLINK_PRETARGET2: 81213498266Sopenharmony_ci parser->item_length++; 81313498266Sopenharmony_ci if(c == '>') { 81413498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3; 81513498266Sopenharmony_ci } 81613498266Sopenharmony_ci else if(c == '\r' || c == '\n') { 81713498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 81813498266Sopenharmony_ci goto fail; 81913498266Sopenharmony_ci } 82013498266Sopenharmony_ci else { 82113498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; 82213498266Sopenharmony_ci } 82313498266Sopenharmony_ci break; 82413498266Sopenharmony_ci case PL_UNIX_SYMLINK_PRETARGET3: 82513498266Sopenharmony_ci parser->item_length++; 82613498266Sopenharmony_ci if(c == ' ') { 82713498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4; 82813498266Sopenharmony_ci /* now place where is symlink following */ 82913498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 4] = 0; 83013498266Sopenharmony_ci parser->offsets.filename = parser->item_offset; 83113498266Sopenharmony_ci parser->item_length = 0; 83213498266Sopenharmony_ci parser->item_offset = 0; 83313498266Sopenharmony_ci } 83413498266Sopenharmony_ci else if(c == '\r' || c == '\n') { 83513498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 83613498266Sopenharmony_ci goto fail; 83713498266Sopenharmony_ci } 83813498266Sopenharmony_ci else { 83913498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME; 84013498266Sopenharmony_ci } 84113498266Sopenharmony_ci break; 84213498266Sopenharmony_ci case PL_UNIX_SYMLINK_PRETARGET4: 84313498266Sopenharmony_ci if(c != '\r' && c != '\n') { 84413498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET; 84513498266Sopenharmony_ci parser->item_offset = len - 1; 84613498266Sopenharmony_ci parser->item_length = 1; 84713498266Sopenharmony_ci } 84813498266Sopenharmony_ci else { 84913498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 85013498266Sopenharmony_ci goto fail; 85113498266Sopenharmony_ci } 85213498266Sopenharmony_ci break; 85313498266Sopenharmony_ci case PL_UNIX_SYMLINK_TARGET: 85413498266Sopenharmony_ci parser->item_length++; 85513498266Sopenharmony_ci if(c == '\r') { 85613498266Sopenharmony_ci parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL; 85713498266Sopenharmony_ci } 85813498266Sopenharmony_ci else if(c == '\n') { 85913498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 86013498266Sopenharmony_ci parser->offsets.symlink_target = parser->item_offset; 86113498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 86213498266Sopenharmony_ci if(result) { 86313498266Sopenharmony_ci parser->error = result; 86413498266Sopenharmony_ci goto fail; 86513498266Sopenharmony_ci } 86613498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 86713498266Sopenharmony_ci } 86813498266Sopenharmony_ci break; 86913498266Sopenharmony_ci case PL_UNIX_SYMLINK_WINDOWSEOL: 87013498266Sopenharmony_ci if(c == '\n') { 87113498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 87213498266Sopenharmony_ci parser->offsets.symlink_target = parser->item_offset; 87313498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 87413498266Sopenharmony_ci if(result) { 87513498266Sopenharmony_ci parser->error = result; 87613498266Sopenharmony_ci goto fail; 87713498266Sopenharmony_ci } 87813498266Sopenharmony_ci parser->state.UNIX.main = PL_UNIX_FILETYPE; 87913498266Sopenharmony_ci } 88013498266Sopenharmony_ci else { 88113498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 88213498266Sopenharmony_ci goto fail; 88313498266Sopenharmony_ci } 88413498266Sopenharmony_ci break; 88513498266Sopenharmony_ci } 88613498266Sopenharmony_ci break; 88713498266Sopenharmony_ci } 88813498266Sopenharmony_ci break; 88913498266Sopenharmony_ci case OS_TYPE_WIN_NT: 89013498266Sopenharmony_ci switch(parser->state.NT.main) { 89113498266Sopenharmony_ci case PL_WINNT_DATE: 89213498266Sopenharmony_ci parser->item_length++; 89313498266Sopenharmony_ci if(parser->item_length < 9) { 89413498266Sopenharmony_ci if(!strchr("0123456789-", c)) { /* only simple control */ 89513498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 89613498266Sopenharmony_ci goto fail; 89713498266Sopenharmony_ci } 89813498266Sopenharmony_ci } 89913498266Sopenharmony_ci else if(parser->item_length == 9) { 90013498266Sopenharmony_ci if(c == ' ') { 90113498266Sopenharmony_ci parser->state.NT.main = PL_WINNT_TIME; 90213498266Sopenharmony_ci parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE; 90313498266Sopenharmony_ci } 90413498266Sopenharmony_ci else { 90513498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 90613498266Sopenharmony_ci goto fail; 90713498266Sopenharmony_ci } 90813498266Sopenharmony_ci } 90913498266Sopenharmony_ci else { 91013498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 91113498266Sopenharmony_ci goto fail; 91213498266Sopenharmony_ci } 91313498266Sopenharmony_ci break; 91413498266Sopenharmony_ci case PL_WINNT_TIME: 91513498266Sopenharmony_ci parser->item_length++; 91613498266Sopenharmony_ci switch(parser->state.NT.sub.time) { 91713498266Sopenharmony_ci case PL_WINNT_TIME_PRESPACE: 91813498266Sopenharmony_ci if(!ISBLANK(c)) { 91913498266Sopenharmony_ci parser->state.NT.sub.time = PL_WINNT_TIME_TIME; 92013498266Sopenharmony_ci } 92113498266Sopenharmony_ci break; 92213498266Sopenharmony_ci case PL_WINNT_TIME_TIME: 92313498266Sopenharmony_ci if(c == ' ') { 92413498266Sopenharmony_ci parser->offsets.time = parser->item_offset; 92513498266Sopenharmony_ci mem[parser->item_offset + parser->item_length -1] = 0; 92613498266Sopenharmony_ci parser->state.NT.main = PL_WINNT_DIRORSIZE; 92713498266Sopenharmony_ci parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE; 92813498266Sopenharmony_ci parser->item_length = 0; 92913498266Sopenharmony_ci } 93013498266Sopenharmony_ci else if(!strchr("APM0123456789:", c)) { 93113498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 93213498266Sopenharmony_ci goto fail; 93313498266Sopenharmony_ci } 93413498266Sopenharmony_ci break; 93513498266Sopenharmony_ci } 93613498266Sopenharmony_ci break; 93713498266Sopenharmony_ci case PL_WINNT_DIRORSIZE: 93813498266Sopenharmony_ci switch(parser->state.NT.sub.dirorsize) { 93913498266Sopenharmony_ci case PL_WINNT_DIRORSIZE_PRESPACE: 94013498266Sopenharmony_ci if(c != ' ') { 94113498266Sopenharmony_ci parser->item_offset = len - 1; 94213498266Sopenharmony_ci parser->item_length = 1; 94313498266Sopenharmony_ci parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT; 94413498266Sopenharmony_ci } 94513498266Sopenharmony_ci break; 94613498266Sopenharmony_ci case PL_WINNT_DIRORSIZE_CONTENT: 94713498266Sopenharmony_ci parser->item_length ++; 94813498266Sopenharmony_ci if(c == ' ') { 94913498266Sopenharmony_ci mem[parser->item_offset + parser->item_length - 1] = 0; 95013498266Sopenharmony_ci if(strcmp("<DIR>", mem + parser->item_offset) == 0) { 95113498266Sopenharmony_ci finfo->filetype = CURLFILETYPE_DIRECTORY; 95213498266Sopenharmony_ci finfo->size = 0; 95313498266Sopenharmony_ci } 95413498266Sopenharmony_ci else { 95513498266Sopenharmony_ci char *endptr; 95613498266Sopenharmony_ci if(curlx_strtoofft(mem + 95713498266Sopenharmony_ci parser->item_offset, 95813498266Sopenharmony_ci &endptr, 10, &finfo->size)) { 95913498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 96013498266Sopenharmony_ci goto fail; 96113498266Sopenharmony_ci } 96213498266Sopenharmony_ci /* correct file type */ 96313498266Sopenharmony_ci parser->file_data->info.filetype = CURLFILETYPE_FILE; 96413498266Sopenharmony_ci } 96513498266Sopenharmony_ci 96613498266Sopenharmony_ci parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE; 96713498266Sopenharmony_ci parser->item_length = 0; 96813498266Sopenharmony_ci parser->state.NT.main = PL_WINNT_FILENAME; 96913498266Sopenharmony_ci parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; 97013498266Sopenharmony_ci } 97113498266Sopenharmony_ci break; 97213498266Sopenharmony_ci } 97313498266Sopenharmony_ci break; 97413498266Sopenharmony_ci case PL_WINNT_FILENAME: 97513498266Sopenharmony_ci switch(parser->state.NT.sub.filename) { 97613498266Sopenharmony_ci case PL_WINNT_FILENAME_PRESPACE: 97713498266Sopenharmony_ci if(c != ' ') { 97813498266Sopenharmony_ci parser->item_offset = len -1; 97913498266Sopenharmony_ci parser->item_length = 1; 98013498266Sopenharmony_ci parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT; 98113498266Sopenharmony_ci } 98213498266Sopenharmony_ci break; 98313498266Sopenharmony_ci case PL_WINNT_FILENAME_CONTENT: 98413498266Sopenharmony_ci parser->item_length++; 98513498266Sopenharmony_ci if(c == '\r') { 98613498266Sopenharmony_ci parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL; 98713498266Sopenharmony_ci mem[len - 1] = 0; 98813498266Sopenharmony_ci } 98913498266Sopenharmony_ci else if(c == '\n') { 99013498266Sopenharmony_ci parser->offsets.filename = parser->item_offset; 99113498266Sopenharmony_ci mem[len - 1] = 0; 99213498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 99313498266Sopenharmony_ci if(result) { 99413498266Sopenharmony_ci parser->error = result; 99513498266Sopenharmony_ci goto fail; 99613498266Sopenharmony_ci } 99713498266Sopenharmony_ci parser->state.NT.main = PL_WINNT_DATE; 99813498266Sopenharmony_ci parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; 99913498266Sopenharmony_ci } 100013498266Sopenharmony_ci break; 100113498266Sopenharmony_ci case PL_WINNT_FILENAME_WINEOL: 100213498266Sopenharmony_ci if(c == '\n') { 100313498266Sopenharmony_ci parser->offsets.filename = parser->item_offset; 100413498266Sopenharmony_ci result = ftp_pl_insert_finfo(data, infop); 100513498266Sopenharmony_ci if(result) { 100613498266Sopenharmony_ci parser->error = result; 100713498266Sopenharmony_ci goto fail; 100813498266Sopenharmony_ci } 100913498266Sopenharmony_ci parser->state.NT.main = PL_WINNT_DATE; 101013498266Sopenharmony_ci parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE; 101113498266Sopenharmony_ci } 101213498266Sopenharmony_ci else { 101313498266Sopenharmony_ci parser->error = CURLE_FTP_BAD_FILE_LIST; 101413498266Sopenharmony_ci goto fail; 101513498266Sopenharmony_ci } 101613498266Sopenharmony_ci break; 101713498266Sopenharmony_ci } 101813498266Sopenharmony_ci break; 101913498266Sopenharmony_ci } 102013498266Sopenharmony_ci break; 102113498266Sopenharmony_ci default: 102213498266Sopenharmony_ci retsize = bufflen + 1; 102313498266Sopenharmony_ci goto fail; 102413498266Sopenharmony_ci } 102513498266Sopenharmony_ci 102613498266Sopenharmony_ci i++; 102713498266Sopenharmony_ci } 102813498266Sopenharmony_ci return retsize; 102913498266Sopenharmony_ci 103013498266Sopenharmony_cifail: 103113498266Sopenharmony_ci 103213498266Sopenharmony_ci /* Clean up any allocated memory. */ 103313498266Sopenharmony_ci if(parser->file_data) { 103413498266Sopenharmony_ci Curl_fileinfo_cleanup(parser->file_data); 103513498266Sopenharmony_ci parser->file_data = NULL; 103613498266Sopenharmony_ci } 103713498266Sopenharmony_ci 103813498266Sopenharmony_ci return retsize; 103913498266Sopenharmony_ci} 104013498266Sopenharmony_ci 104113498266Sopenharmony_ci#endif /* CURL_DISABLE_FTP */ 1042