1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2010, 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 http://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
42 #include "ftplistparser.h"
43 #include "curl_fnmatch.h"
49 #include "strtoofft.h"
53 #define _MPRINTF_REPLACE /* use our functions only */
54 #include <curl/mprintf.h>
56 #include "curl_memory.h"
57 /* The last #include file should be: */
60 /* allocs buffer which will contain one line of LIST command response */
61 #define FTP_BUFFER_ALLOCSIZE 160
77 PL_UNIX_HLINKS_PRESPACE = 0,
82 PL_UNIX_USER_PRESPACE = 0,
87 PL_UNIX_GROUP_PRESPACE = 0,
92 PL_UNIX_SIZE_PRESPACE = 0,
97 PL_UNIX_TIME_PREPART1 = 0,
99 PL_UNIX_TIME_PREPART2,
101 PL_UNIX_TIME_PREPART3,
106 PL_UNIX_FILENAME_PRESPACE = 0,
107 PL_UNIX_FILENAME_NAME,
108 PL_UNIX_FILENAME_WINDOWSEOL
112 PL_UNIX_SYMLINK_PRESPACE = 0,
113 PL_UNIX_SYMLINK_NAME,
114 PL_UNIX_SYMLINK_PRETARGET1,
115 PL_UNIX_SYMLINK_PRETARGET2,
116 PL_UNIX_SYMLINK_PRETARGET3,
117 PL_UNIX_SYMLINK_PRETARGET4,
118 PL_UNIX_SYMLINK_TARGET,
119 PL_UNIX_SYMLINK_WINDOWSEOL
128 } pl_winNT_mainstate;
132 PL_WINNT_TIME_PRESPACE = 0,
136 PL_WINNT_DIRORSIZE_PRESPACE = 0,
137 PL_WINNT_DIRORSIZE_CONTENT
140 PL_WINNT_FILENAME_PRESPACE = 0,
141 PL_WINNT_FILENAME_CONTENT,
142 PL_WINNT_FILENAME_WINEOL
146 /* This struct is used in wildcard downloading - for parsing LIST response */
147 struct ftp_parselist_data {
156 pl_unix_mainstate main;
157 pl_unix_substate sub;
161 pl_winNT_mainstate main;
162 pl_winNT_substate sub;
167 struct curl_fileinfo *file_data;
168 unsigned int item_length;
176 size_t symlink_target;
180 struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
182 return calloc(1, sizeof(struct ftp_parselist_data));
186 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 bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string)
282 * There could be possible parse timestamp from server. Leaving unimplemented
284 * If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to
285 * parser->file_data->flags
287 * Ftp servers are giving usually these formats:
288 * Apr 11 1998 (unknown time.. set it to 00:00:00?)
289 * Apr 11 12:21 (unknown year -> set it to NOW() time?)
290 * 08-05-09 02:49PM (ms-dos format)
291 * 20100421092538 -> for MLST/MLSD response
297 static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
298 struct curl_fileinfo *finfo)
300 curl_fnmatch_callback compare;
301 struct WildcardData *wc = &conn->data->wildcard;
302 struct ftp_wc_tmpdata *tmpdata = wc->tmp;
303 struct curl_llist *llist = wc->filelist;
304 struct ftp_parselist_data *parser = tmpdata->parser;
307 /* move finfo pointers to b_data */
308 char *str = finfo->b_data;
309 finfo->filename = str + parser->offsets.filename;
310 finfo->strings.group = parser->offsets.group ?
311 str + parser->offsets.group : NULL;
312 finfo->strings.perm = parser->offsets.perm ?
313 str + parser->offsets.perm : NULL;
314 finfo->strings.target = parser->offsets.symlink_target ?
315 str + parser->offsets.symlink_target : NULL;
316 finfo->strings.time = str + parser->offsets.time;
317 finfo->strings.user = parser->offsets.user ?
318 str + parser->offsets.user : NULL;
320 /* get correct fnmatch callback */
321 compare = conn->data->set.fnmatch;
323 compare = Curl_fnmatch;
325 /* filter pattern-corresponding filenames */
326 if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) {
327 /* discard symlink which is containing multiple " -> " */
328 if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
329 (strstr(finfo->strings.target, " -> "))) {
338 if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
339 Curl_fileinfo_dtor(NULL, finfo);
340 tmpdata->parser->file_data = NULL;
341 return CURLE_OUT_OF_MEMORY;
345 Curl_fileinfo_dtor(NULL, finfo);
348 tmpdata->parser->file_data = NULL;
352 size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
355 size_t bufflen = size*nmemb;
356 struct connectdata *conn = (struct connectdata *)connptr;
357 struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
358 struct ftp_parselist_data *parser = tmpdata->parser;
359 struct curl_fileinfo *finfo;
363 if(parser->error) { /* error in previous call */
366 * 2. call => OUT_OF_MEMORY (or other error)
367 * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
373 if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
374 /* considering info about FILE response format */
375 parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
376 OS_TYPE_WIN_NT : OS_TYPE_UNIX;
379 while(i < bufflen) { /* FSM */
382 if(!parser->file_data) { /* tmp file data is not allocated yet */
383 parser->file_data = Curl_fileinfo_alloc();
384 if(!parser->file_data) {
385 parser->error = CURLE_OUT_OF_MEMORY;
388 parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
389 if(!parser->file_data->b_data) {
390 PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
393 parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
394 parser->item_offset = 0;
395 parser->item_length = 0;
398 finfo = parser->file_data;
399 finfo->b_data[finfo->b_used++] = buffer[i];
401 if(finfo->b_used >= finfo->b_size - 1) {
402 /* if it is important, extend buffer space for file data */
403 char *tmp = realloc(finfo->b_data,
404 finfo->b_size + FTP_BUFFER_ALLOCSIZE);
406 finfo->b_size += FTP_BUFFER_ALLOCSIZE;
410 Curl_fileinfo_dtor(NULL, parser->file_data);
411 parser->file_data = NULL;
412 parser->error = CURLE_OUT_OF_MEMORY;
413 PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
418 switch (parser->os_type) {
420 switch (parser->state.UNIX.main) {
421 case PL_UNIX_FILETYPE:
424 finfo->filetype = CURLFILETYPE_FILE;
427 finfo->filetype = CURLFILETYPE_DIRECTORY;
430 finfo->filetype = CURLFILETYPE_SYMLINK;
433 finfo->filetype = CURLFILETYPE_NAMEDPIPE;
436 finfo->filetype = CURLFILETYPE_SOCKET;
439 finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
442 finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
445 finfo->filetype = CURLFILETYPE_DOOR;
448 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
451 parser->state.UNIX.main = PL_UNIX_PERMISSION;
452 parser->item_length = 0;
453 parser->item_offset = 1;
455 case PL_UNIX_PERMISSION:
456 parser->item_length++;
457 if(parser->item_length <= 9) {
458 if(!strchr("rwx-tTsS", c)) {
459 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
463 else if(parser->item_length == 10) {
466 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
469 finfo->b_data[10] = 0; /* terminate permissions */
470 perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
471 if(perm & FTP_LP_MALFORMATED_PERM) {
472 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
475 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
476 parser->file_data->perm = perm;
477 parser->offsets.perm = parser->item_offset;
479 parser->item_length = 0;
480 parser->state.UNIX.main = PL_UNIX_HLINKS;
481 parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
485 switch(parser->state.UNIX.sub.hlinks) {
486 case PL_UNIX_HLINKS_PRESPACE:
488 if(c >= '0' && c <= '9') {
489 parser->item_offset = finfo->b_used - 1;
490 parser->item_length = 1;
491 parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
494 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
499 case PL_UNIX_HLINKS_NUMBER:
500 parser->item_length ++;
504 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
505 hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
506 if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
507 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
508 parser->file_data->hardlinks = hlinks;
510 parser->item_length = 0;
511 parser->item_offset = 0;
512 parser->state.UNIX.main = PL_UNIX_USER;
513 parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
515 else if(c < '0' || c > '9') {
516 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
523 switch(parser->state.UNIX.sub.user) {
524 case PL_UNIX_USER_PRESPACE:
526 parser->item_offset = finfo->b_used - 1;
527 parser->item_length = 1;
528 parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
531 case PL_UNIX_USER_PARSING:
532 parser->item_length++;
534 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
535 parser->offsets.user = parser->item_offset;
536 parser->state.UNIX.main = PL_UNIX_GROUP;
537 parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
538 parser->item_offset = 0;
539 parser->item_length = 0;
545 switch(parser->state.UNIX.sub.group) {
546 case PL_UNIX_GROUP_PRESPACE:
548 parser->item_offset = finfo->b_used - 1;
549 parser->item_length = 1;
550 parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
553 case PL_UNIX_GROUP_NAME:
554 parser->item_length++;
556 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
557 parser->offsets.group = parser->item_offset;
558 parser->state.UNIX.main = PL_UNIX_SIZE;
559 parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
560 parser->item_offset = 0;
561 parser->item_length = 0;
567 switch(parser->state.UNIX.sub.size) {
568 case PL_UNIX_SIZE_PRESPACE:
570 if(c >= '0' && c <= '9') {
571 parser->item_offset = finfo->b_used - 1;
572 parser->item_length = 1;
573 parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
576 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
581 case PL_UNIX_SIZE_NUMBER:
582 parser->item_length++;
586 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
587 fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
588 if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
589 fsize != CURL_OFF_T_MIN) {
590 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
591 parser->file_data->size = fsize;
593 parser->item_length = 0;
594 parser->item_offset = 0;
595 parser->state.UNIX.main = PL_UNIX_TIME;
596 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
598 else if (!ISDIGIT(c)) {
599 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
606 switch(parser->state.UNIX.sub.time) {
607 case PL_UNIX_TIME_PREPART1:
610 parser->item_offset = finfo->b_used -1;
611 parser->item_length = 1;
612 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
615 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
620 case PL_UNIX_TIME_PART1:
621 parser->item_length++;
623 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
625 else if(!ISALNUM(c) && c != '.') {
626 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
630 case PL_UNIX_TIME_PREPART2:
631 parser->item_length++;
634 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
637 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
642 case PL_UNIX_TIME_PART2:
643 parser->item_length++;
645 parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
647 else if(!ISALNUM(c) && c != '.') {
648 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
652 case PL_UNIX_TIME_PREPART3:
653 parser->item_length++;
656 parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
659 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
664 case PL_UNIX_TIME_PART3:
665 parser->item_length++;
667 finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
668 parser->offsets.time = parser->item_offset;
669 if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
670 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
672 if(finfo->filetype == CURLFILETYPE_SYMLINK) {
673 parser->state.UNIX.main = PL_UNIX_SYMLINK;
674 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
677 parser->state.UNIX.main = PL_UNIX_FILENAME;
678 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
681 else if(!ISALNUM(c) && c != '.' && c != ':') {
682 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
688 case PL_UNIX_FILENAME:
689 switch(parser->state.UNIX.sub.filename) {
690 case PL_UNIX_FILENAME_PRESPACE:
692 parser->item_offset = finfo->b_used - 1;
693 parser->item_length = 1;
694 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
697 case PL_UNIX_FILENAME_NAME:
698 parser->item_length++;
700 parser->item_length--;
701 parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
704 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
705 parser->offsets.filename = parser->item_offset;
706 parser->state.UNIX.main = PL_UNIX_FILETYPE;
707 rc = ftp_pl_insert_finfo(conn, finfo);
714 case PL_UNIX_FILENAME_WINDOWSEOL:
716 finfo->b_data[parser->item_offset + parser->item_length] = 0;
717 parser->offsets.filename = parser->item_offset;
718 parser->state.UNIX.main = PL_UNIX_FILETYPE;
719 rc = ftp_pl_insert_finfo(conn, finfo);
726 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
732 case PL_UNIX_SYMLINK:
733 switch(parser->state.UNIX.sub.symlink) {
734 case PL_UNIX_SYMLINK_PRESPACE:
736 parser->item_offset = finfo->b_used - 1;
737 parser->item_length = 1;
738 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
741 case PL_UNIX_SYMLINK_NAME:
742 parser->item_length++;
744 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
746 else if(c == '\r' || c == '\n') {
747 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
751 case PL_UNIX_SYMLINK_PRETARGET1:
752 parser->item_length++;
754 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
756 else if(c == '\r' || c == '\n') {
757 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
761 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
764 case PL_UNIX_SYMLINK_PRETARGET2:
765 parser->item_length++;
767 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
769 else if(c == '\r' || c == '\n') {
770 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
774 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
777 case PL_UNIX_SYMLINK_PRETARGET3:
778 parser->item_length++;
780 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
781 /* now place where is symlink following */
782 finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
783 parser->offsets.filename = parser->item_offset;
784 parser->item_length = 0;
785 parser->item_offset = 0;
787 else if(c == '\r' || c == '\n') {
788 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
792 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
795 case PL_UNIX_SYMLINK_PRETARGET4:
796 if(c != '\r' && c != '\n') {
797 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
798 parser->item_offset = finfo->b_used - 1;
799 parser->item_length = 1;
802 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
806 case PL_UNIX_SYMLINK_TARGET:
807 parser->item_length ++;
809 parser->item_length --;
810 parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
813 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
814 parser->offsets.symlink_target = parser->item_offset;
815 rc = ftp_pl_insert_finfo(conn, finfo);
820 parser->state.UNIX.main = PL_UNIX_FILETYPE;
823 case PL_UNIX_SYMLINK_WINDOWSEOL:
825 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
826 parser->offsets.symlink_target = parser->item_offset;
827 rc = ftp_pl_insert_finfo(conn, finfo);
832 parser->state.UNIX.main = PL_UNIX_FILETYPE;
835 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
844 switch(parser->state.NT.main) {
846 parser->item_length++;
847 if(parser->item_length < 9) {
848 if(!strchr("0123456789-", c)) { /* only simple control */
849 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
853 else if(parser->item_length == 9) {
855 parser->state.NT.main = PL_WINNT_TIME;
856 parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
859 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
864 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
869 parser->item_length++;
870 switch(parser->state.NT.sub.time) {
871 case PL_WINNT_TIME_PRESPACE:
873 parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
876 case PL_WINNT_TIME_TIME:
878 parser->offsets.time = parser->item_offset;
879 finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
880 parser->state.NT.main = PL_WINNT_DIRORSIZE;
881 parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
882 parser->item_length = 0;
884 else if(!strchr("APM0123456789:", c)) {
885 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
891 case PL_WINNT_DIRORSIZE:
892 switch(parser->state.NT.sub.dirorsize) {
893 case PL_WINNT_DIRORSIZE_PRESPACE:
898 parser->item_offset = finfo->b_used - 1;
899 parser->item_length = 1;
900 parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
903 case PL_WINNT_DIRORSIZE_CONTENT:
904 parser->item_length ++;
906 finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
907 if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
908 finfo->filetype = CURLFILETYPE_DIRECTORY;
913 finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset,
916 if(finfo->size == CURL_OFF_T_MAX ||
917 finfo->size == CURL_OFF_T_MIN) {
918 if(errno == ERANGE) {
919 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
925 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
928 /* correct file type */
929 parser->file_data->filetype = CURLFILETYPE_FILE;
932 parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
933 parser->item_length = 0;
934 parser->state.NT.main = PL_WINNT_FILENAME;
935 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
940 case PL_WINNT_FILENAME:
941 switch (parser->state.NT.sub.filename) {
942 case PL_WINNT_FILENAME_PRESPACE:
944 parser->item_offset = finfo->b_used -1;
945 parser->item_length = 1;
946 parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
949 case PL_WINNT_FILENAME_CONTENT:
950 parser->item_length++;
952 parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
953 finfo->b_data[finfo->b_used - 1] = 0;
956 parser->offsets.filename = parser->item_offset;
957 finfo->b_data[finfo->b_used - 1] = 0;
958 parser->offsets.filename = parser->item_offset;
959 rc = ftp_pl_insert_finfo(conn, finfo);
964 parser->state.NT.main = PL_WINNT_DATE;
965 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
968 case PL_WINNT_FILENAME_WINEOL:
970 parser->offsets.filename = parser->item_offset;
971 rc = ftp_pl_insert_finfo(conn, finfo);
976 parser->state.NT.main = PL_WINNT_DATE;
977 parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
980 PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);