1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
27 * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
29 * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
31 * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
33 * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
35 * 01-29-97 11:32PM <DIR> prog
38 #include "curl_setup.h"
40 #ifndef CURL_DISABLE_FTP
42 #include <curl/curl.h>
47 #include "strtoofft.h"
49 #include "ftplistparser.h"
50 #include "curl_fnmatch.h"
51 #include "curl_memory.h"
52 /* The last #include file should be: */
55 /* allocs buffer which will contain one line of LIST command response */
56 #define FTP_BUFFER_ALLOCSIZE 160
59 PL_UNIX_TOTALSIZE = 0,
73 PL_UNIX_TOTALSIZE_INIT = 0,
74 PL_UNIX_TOTALSIZE_READING
78 PL_UNIX_HLINKS_PRESPACE = 0,
83 PL_UNIX_USER_PRESPACE = 0,
88 PL_UNIX_GROUP_PRESPACE = 0,
93 PL_UNIX_SIZE_PRESPACE = 0,
98 PL_UNIX_TIME_PREPART1 = 0,
100 PL_UNIX_TIME_PREPART2,
102 PL_UNIX_TIME_PREPART3,
107 PL_UNIX_FILENAME_PRESPACE = 0,
108 PL_UNIX_FILENAME_NAME,
109 PL_UNIX_FILENAME_WINDOWSEOL
113 PL_UNIX_SYMLINK_PRESPACE = 0,
114 PL_UNIX_SYMLINK_NAME,
115 PL_UNIX_SYMLINK_PRETARGET1,
116 PL_UNIX_SYMLINK_PRETARGET2,
117 PL_UNIX_SYMLINK_PRETARGET3,
118 PL_UNIX_SYMLINK_PRETARGET4,
119 PL_UNIX_SYMLINK_TARGET,
120 PL_UNIX_SYMLINK_WINDOWSEOL
129 } pl_winNT_mainstate;
133 PL_WINNT_TIME_PRESPACE = 0,
137 PL_WINNT_DIRORSIZE_PRESPACE = 0,
138 PL_WINNT_DIRORSIZE_CONTENT
141 PL_WINNT_FILENAME_PRESPACE = 0,
142 PL_WINNT_FILENAME_CONTENT,
143 PL_WINNT_FILENAME_WINEOL
147 /* This struct is used in wildcard downloading - for parsing LIST response */
148 struct ftp_parselist_data {
157 pl_unix_mainstate main;
158 pl_unix_substate sub;
162 pl_winNT_mainstate main;
163 pl_winNT_substate sub;
168 struct curl_fileinfo *file_data;
169 unsigned int item_length;
177 size_t symlink_target;
181 struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
183 return calloc(1, sizeof(struct ftp_parselist_data));
187 void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
194 CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
196 return pl_data->error;
200 #define FTP_LP_MALFORMATED_PERM 0x01000000
202 static int ftp_pl_get_permission(const char *str)
207 permissions |= 1 << 8;
208 else if(str[0] != '-')
209 permissions |= FTP_LP_MALFORMATED_PERM;
211 permissions |= 1 << 7;
212 else if(str[1] != '-')
213 permissions |= FTP_LP_MALFORMATED_PERM;
216 permissions |= 1 << 6;
217 else if(str[2] == 's') {
218 permissions |= 1 << 6;
219 permissions |= 1 << 11;
221 else if(str[2] == 'S')
222 permissions |= 1 << 11;
223 else if(str[2] != '-')
224 permissions |= FTP_LP_MALFORMATED_PERM;
227 permissions |= 1 << 5;
228 else if(str[3] != '-')
229 permissions |= FTP_LP_MALFORMATED_PERM;
231 permissions |= 1 << 4;
232 else if(str[4] != '-')
233 permissions |= FTP_LP_MALFORMATED_PERM;
235 permissions |= 1 << 3;
236 else if(str[5] == 's') {
237 permissions |= 1 << 3;
238 permissions |= 1 << 10;
240 else if(str[5] == 'S')
241 permissions |= 1 << 10;
242 else if(str[5] != '-')
243 permissions |= FTP_LP_MALFORMATED_PERM;
246 permissions |= 1 << 2;
247 else if(str[6] != '-')
248 permissions |= FTP_LP_MALFORMATED_PERM;
250 permissions |= 1 << 1;
251 else if(str[7] != '-')
252 permissions |= FTP_LP_MALFORMATED_PERM;
255 else if(str[8] == 't') {
257 permissions |= 1 << 9;
259 else if(str[8] == 'T')
260 permissions |= 1 << 9;
261 else if(str[8] != '-')
262 permissions |= FTP_LP_MALFORMATED_PERM;
267 static void PL_ERROR(struct connectdata *conn, CURLcode err)
269 struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
270 struct ftp_parselist_data *parser = tmpdata->parser;
271 if(parser->file_data)
272 Curl_fileinfo_dtor(NULL, parser->file_data);
273 parser->file_data = NULL;
277 static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
278 struct curl_fileinfo *finfo)
280 curl_fnmatch_callback compare;
281 struct WildcardData *wc = &conn->data->wildcard;
282 struct ftp_wc_tmpdata *tmpdata = wc->tmp;
283 struct curl_llist *llist = wc->filelist;
284 struct ftp_parselist_data *parser = tmpdata->parser;
287 /* move finfo pointers to b_data */
288 char *str = finfo->b_data;
289 finfo->filename = str + parser->offsets.filename;
290 finfo->strings.group = parser->offsets.group ?
291 str + parser->offsets.group : NULL;
292 finfo->strings.perm = parser->offsets.perm ?
293 str + parser->offsets.perm : NULL;
294 finfo->strings.target = parser->offsets.symlink_target ?
295 str + parser->offsets.symlink_target : NULL;
296 finfo->strings.time = str + parser->offsets.time;
297 finfo->strings.user = parser->offsets.user ?
298 str + parser->offsets.user : NULL;
300 /* get correct fnmatch callback */
301 compare = conn->data->set.fnmatch;
303 compare = Curl_fnmatch;
305 /* filter pattern-corresponding filenames */
306 if(compare(conn->data->set.fnmatch_data, wc->pattern,
307 finfo->filename) == 0) {
308 /* discard symlink which is containing multiple " -> " */
309 if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
310 (strstr(finfo->strings.target, " -> "))) {
319 if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
320 Curl_fileinfo_dtor(NULL, finfo);
321 tmpdata->parser->file_data = NULL;
322 return CURLE_OUT_OF_MEMORY;
326 Curl_fileinfo_dtor(NULL, finfo);
329 tmpdata->parser->file_data = NULL;
333 size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
336 size_t bufflen = size*nmemb;
337 struct connectdata *conn = (struct connectdata *)connptr;
338 struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
339 struct ftp_parselist_data *parser = tmpdata->parser;
340 struct curl_fileinfo *finfo;
344 if(parser->error) { /* error in previous call */
347 * 2. call => OUT_OF_MEMORY (or other error)
348 * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
354 if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
355 /* considering info about FILE response format */
356 parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
357 OS_TYPE_WIN_NT : OS_TYPE_UNIX;
360 while(i < bufflen) { /* FSM */
363 if(!parser->file_data) { /* tmp file data is not allocated yet */
364 parser->file_data = Curl_fileinfo_alloc();
365 if(!parser->file_data) {
366 parser->error = CURLE_OUT_OF_MEMORY;
369 parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
370 if(!parser->file_data->b_data) {
371 PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
374 parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
375 parser->item_offset = 0;
376 parser->item_length = 0;
379 finfo = parser->file_data;
380 finfo->b_data[finfo->b_used++] = c;
382 if(finfo->b_used >= finfo->b_size - 1) {
383 /* if it is important, extend buffer space for file data */
384 char *tmp = realloc(finfo->b_data,
385 finfo->b_size + FTP_BUFFER_ALLOCSIZE);
387 finfo->b_size += FTP_BUFFER_ALLOCSIZE;
391 Curl_fileinfo_dtor(NULL, parser->file_data);
392 parser->file_data = NULL;
393 parser->error = CURLE_OUT_OF_MEMORY;
394 PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
399 switch(parser->os_type) {
401 switch(parser->state.UNIX.main) {
402 case PL_UNIX_TOTALSIZE:
403 switch(parser->state.UNIX.sub.total_dirsize) {
404 case PL_UNIX_TOTALSIZE_INIT:
406 parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
407 parser->item_length++;
410 parser->state.UNIX.main = PL_UNIX_FILETYPE;
411 /* start FSM again not considering size of directory */
416 case PL_UNIX_TOTALSIZE_READING:
417 parser->item_length++;
419 parser->item_length--;
423 finfo->b_data[parser->item_length - 1] = 0;
424 if(strncmp("total ", finfo->b_data, 6) == 0) {
425 char *endptr = finfo->b_data+6;
426 /* here we can deal with directory size, pass the leading white
427 spaces and then the digits */
428 while(ISSPACE(*endptr))
430 while(ISDIGIT(*endptr))
433 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
437 parser->state.UNIX.main = PL_UNIX_FILETYPE;
442 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
449 case PL_UNIX_FILETYPE:
452 finfo->filetype = CURLFILETYPE_FILE;
455 finfo->filetype = CURLFILETYPE_DIRECTORY;
458 finfo->filetype = CURLFILETYPE_SYMLINK;
461 finfo->filetype = CURLFILETYPE_NAMEDPIPE;
464 finfo->filetype = CURLFILETYPE_SOCKET;
467 finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
470 finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
473 finfo->filetype = CURLFILETYPE_DOOR;
476 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
479 parser->state.UNIX.main = PL_UNIX_PERMISSION;
480 parser->item_length = 0;
481 parser->item_offset = 1;
483 case PL_UNIX_PERMISSION:
484 parser->item_length++;
485 if(parser->item_length <= 9) {
486 if(!strchr("rwx-tTsS", c)) {
487 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
491 else if(parser->item_length == 10) {
494 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
497 finfo->b_data[10] = 0; /* terminate permissions */
498 perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
499 if(perm & FTP_LP_MALFORMATED_PERM) {
500 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
503 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
504 parser->file_data->perm = perm;
505 parser->offsets.perm = parser->item_offset;
507 parser->item_length = 0;
508 parser->state.UNIX.main = PL_UNIX_HLINKS;
509 parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
513 switch(parser->state.UNIX.sub.hlinks) {
514 case PL_UNIX_HLINKS_PRESPACE:
516 if(c >= '0' && c <= '9') {
517 parser->item_offset = finfo->b_used - 1;
518 parser->item_length = 1;
519 parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
522 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
527 case PL_UNIX_HLINKS_NUMBER:
528 parser->item_length ++;
532 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
533 hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
534 if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
535 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
536 parser->file_data->hardlinks = hlinks;
538 parser->item_length = 0;
539 parser->item_offset = 0;
540 parser->state.UNIX.main = PL_UNIX_USER;
541 parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
543 else if(c < '0' || c > '9') {
544 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
551 switch(parser->state.UNIX.sub.user) {
552 case PL_UNIX_USER_PRESPACE:
554 parser->item_offset = finfo->b_used - 1;
555 parser->item_length = 1;
556 parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
559 case PL_UNIX_USER_PARSING:
560 parser->item_length++;
562 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
563 parser->offsets.user = parser->item_offset;
564 parser->state.UNIX.main = PL_UNIX_GROUP;
565 parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
566 parser->item_offset = 0;
567 parser->item_length = 0;
573 switch(parser->state.UNIX.sub.group) {
574 case PL_UNIX_GROUP_PRESPACE:
576 parser->item_offset = finfo->b_used - 1;
577 parser->item_length = 1;
578 parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
581 case PL_UNIX_GROUP_NAME:
582 parser->item_length++;
584 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
585 parser->offsets.group = parser->item_offset;
586 parser->state.UNIX.main = PL_UNIX_SIZE;
587 parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
588 parser->item_offset = 0;
589 parser->item_length = 0;
595 switch(parser->state.UNIX.sub.size) {
596 case PL_UNIX_SIZE_PRESPACE:
598 if(c >= '0' && c <= '9') {
599 parser->item_offset = finfo->b_used - 1;
600 parser->item_length = 1;
601 parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
604 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
609 case PL_UNIX_SIZE_NUMBER:
610 parser->item_length++;
614 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
615 fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
616 if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
617 fsize != CURL_OFF_T_MIN) {
618 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
619 parser->file_data->size = fsize;
621 parser->item_length = 0;
622 parser->item_offset = 0;
623 parser->state.UNIX.main = PL_UNIX_TIME;
624 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
626 else if(!ISDIGIT(c)) {
627 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
634 switch(parser->state.UNIX.sub.time) {
635 case PL_UNIX_TIME_PREPART1:
638 parser->item_offset = finfo->b_used -1;
639 parser->item_length = 1;
640 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
643 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
648 case PL_UNIX_TIME_PART1:
649 parser->item_length++;
651 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
653 else if(!ISALNUM(c) && c != '.') {
654 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
658 case PL_UNIX_TIME_PREPART2:
659 parser->item_length++;
662 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
665 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
670 case PL_UNIX_TIME_PART2:
671 parser->item_length++;
673 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
675 else if(!ISALNUM(c) && c != '.') {
676 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
680 case PL_UNIX_TIME_PREPART3:
681 parser->item_length++;
684 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
687 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
692 case PL_UNIX_TIME_PART3:
693 parser->item_length++;
695 finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
696 parser->offsets.time = parser->item_offset;
698 if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
699 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
702 if(finfo->filetype == CURLFILETYPE_SYMLINK) {
703 parser->state.UNIX.main = PL_UNIX_SYMLINK;
704 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
707 parser->state.UNIX.main = PL_UNIX_FILENAME;
708 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
711 else if(!ISALNUM(c) && c != '.' && c != ':') {
712 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
718 case PL_UNIX_FILENAME:
719 switch(parser->state.UNIX.sub.filename) {
720 case PL_UNIX_FILENAME_PRESPACE:
722 parser->item_offset = finfo->b_used - 1;
723 parser->item_length = 1;
724 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
727 case PL_UNIX_FILENAME_NAME:
728 parser->item_length++;
730 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
733 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
734 parser->offsets.filename = parser->item_offset;
735 parser->state.UNIX.main = PL_UNIX_FILETYPE;
736 result = ftp_pl_insert_finfo(conn, finfo);
738 PL_ERROR(conn, result);
743 case PL_UNIX_FILENAME_WINDOWSEOL:
745 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
746 parser->offsets.filename = parser->item_offset;
747 parser->state.UNIX.main = PL_UNIX_FILETYPE;
748 result = ftp_pl_insert_finfo(conn, finfo);
750 PL_ERROR(conn, result);
755 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
761 case PL_UNIX_SYMLINK:
762 switch(parser->state.UNIX.sub.symlink) {
763 case PL_UNIX_SYMLINK_PRESPACE:
765 parser->item_offset = finfo->b_used - 1;
766 parser->item_length = 1;
767 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
770 case PL_UNIX_SYMLINK_NAME:
771 parser->item_length++;
773 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
775 else if(c == '\r' || c == '\n') {
776 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
780 case PL_UNIX_SYMLINK_PRETARGET1:
781 parser->item_length++;
783 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
785 else if(c == '\r' || c == '\n') {
786 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
790 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
793 case PL_UNIX_SYMLINK_PRETARGET2:
794 parser->item_length++;
796 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
798 else if(c == '\r' || c == '\n') {
799 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
803 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
806 case PL_UNIX_SYMLINK_PRETARGET3:
807 parser->item_length++;
809 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
810 /* now place where is symlink following */
811 finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
812 parser->offsets.filename = parser->item_offset;
813 parser->item_length = 0;
814 parser->item_offset = 0;
816 else if(c == '\r' || c == '\n') {
817 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
821 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
824 case PL_UNIX_SYMLINK_PRETARGET4:
825 if(c != '\r' && c != '\n') {
826 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
827 parser->item_offset = finfo->b_used - 1;
828 parser->item_length = 1;
831 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
835 case PL_UNIX_SYMLINK_TARGET:
836 parser->item_length++;
838 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
841 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
842 parser->offsets.symlink_target = parser->item_offset;
843 result = ftp_pl_insert_finfo(conn, finfo);
845 PL_ERROR(conn, result);
848 parser->state.UNIX.main = PL_UNIX_FILETYPE;
851 case PL_UNIX_SYMLINK_WINDOWSEOL:
853 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
854 parser->offsets.symlink_target = parser->item_offset;
855 result = ftp_pl_insert_finfo(conn, finfo);
857 PL_ERROR(conn, result);
860 parser->state.UNIX.main = PL_UNIX_FILETYPE;
863 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
872 switch(parser->state.NT.main) {
874 parser->item_length++;
875 if(parser->item_length < 9) {
876 if(!strchr("0123456789-", c)) { /* only simple control */
877 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
881 else if(parser->item_length == 9) {
883 parser->state.NT.main = PL_WINNT_TIME;
884 parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
887 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
892 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
897 parser->item_length++;
898 switch(parser->state.NT.sub.time) {
899 case PL_WINNT_TIME_PRESPACE:
901 parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
904 case PL_WINNT_TIME_TIME:
906 parser->offsets.time = parser->item_offset;
907 finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
908 parser->state.NT.main = PL_WINNT_DIRORSIZE;
909 parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
910 parser->item_length = 0;
912 else if(!strchr("APM0123456789:", c)) {
913 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
919 case PL_WINNT_DIRORSIZE:
920 switch(parser->state.NT.sub.dirorsize) {
921 case PL_WINNT_DIRORSIZE_PRESPACE:
926 parser->item_offset = finfo->b_used - 1;
927 parser->item_length = 1;
928 parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
931 case PL_WINNT_DIRORSIZE_CONTENT:
932 parser->item_length ++;
934 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
935 if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
936 finfo->filetype = CURLFILETYPE_DIRECTORY;
941 finfo->size = curlx_strtoofft(finfo->b_data +
945 if(finfo->size == CURL_OFF_T_MAX ||
946 finfo->size == CURL_OFF_T_MIN) {
947 if(errno == ERANGE) {
948 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
954 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
957 /* correct file type */
958 parser->file_data->filetype = CURLFILETYPE_FILE;
961 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
962 parser->item_length = 0;
963 parser->state.NT.main = PL_WINNT_FILENAME;
964 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
969 case PL_WINNT_FILENAME:
970 switch(parser->state.NT.sub.filename) {
971 case PL_WINNT_FILENAME_PRESPACE:
973 parser->item_offset = finfo->b_used -1;
974 parser->item_length = 1;
975 parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
978 case PL_WINNT_FILENAME_CONTENT:
979 parser->item_length++;
981 parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
982 finfo->b_data[finfo->b_used - 1] = 0;
985 parser->offsets.filename = parser->item_offset;
986 finfo->b_data[finfo->b_used - 1] = 0;
987 parser->offsets.filename = parser->item_offset;
988 result = ftp_pl_insert_finfo(conn, finfo);
990 PL_ERROR(conn, result);
993 parser->state.NT.main = PL_WINNT_DATE;
994 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
997 case PL_WINNT_FILENAME_WINEOL:
999 parser->offsets.filename = parser->item_offset;
1000 result = ftp_pl_insert_finfo(conn, finfo);
1002 PL_ERROR(conn, result);
1005 parser->state.NT.main = PL_WINNT_DATE;
1006 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
1009 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
1027 #endif /* CURL_DISABLE_FTP */