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