source: azure_iot_hub/trunk/curl-7.57.0/lib/ftplistparser.c@ 389

Last change on this file since 389 was 389, checked in by coas-nagasima, 5 years ago

ビルドが通るよう更新

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