ftplistparser.c
Go to the documentation of this file.
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 
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 
58 typedef enum {
70 
71 typedef 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,
103  PL_UNIX_TIME_PART3
104  } time;
105 
106  enum {
107  PL_UNIX_FILENAME_PRESPACE = 0,
109  PL_UNIX_FILENAME_WINDOWSEOL
110  } filename;
111 
112  enum {
113  PL_UNIX_SYMLINK_PRESPACE = 0,
120  PL_UNIX_SYMLINK_WINDOWSEOL
121  } symlink;
123 
124 typedef enum {
130 
131 typedef 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,
143  PL_WINNT_FILENAME_WINEOL
144  } filename;
146 
147 /* This struct is used in wildcard downloading - for parsing LIST response */
149  enum {
150  OS_TYPE_UNKNOWN = 0,
152  OS_TYPE_WIN_NT
153  } os_type;
154 
155  union {
156  struct {
159  } UNIX;
160 
161  struct {
164  } NT;
165  } state;
166 
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;
178  } offsets;
179 };
180 
182 {
183  return calloc(1, sizeof(struct ftp_parselist_data));
184 }
185 
186 
188 {
189  free(*pl_data);
190  *pl_data = NULL;
191 }
192 
193 
195 {
196  return pl_data->error;
197 }
198 
199 
200 #define FTP_LP_MALFORMATED_PERM 0x01000000
201 
202 static 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 
267 static void PL_ERROR(struct connectdata *conn, CURLcode err)
268 {
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;
274  parser->error = err;
275 }
276 
278  struct fileinfo *infop)
279 {
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;
285  bool add = TRUE;
286  struct curl_fileinfo *finfo = &infop->info;
287 
288  /* move finfo pointers to b_data */
289  char *str = finfo->b_data;
290  finfo->filename = str + parser->offsets.filename;
291  finfo->strings.group = parser->offsets.group ?
292  str + parser->offsets.group : NULL;
293  finfo->strings.perm = parser->offsets.perm ?
294  str + parser->offsets.perm : NULL;
295  finfo->strings.target = parser->offsets.symlink_target ?
296  str + parser->offsets.symlink_target : NULL;
297  finfo->strings.time = str + parser->offsets.time;
298  finfo->strings.user = parser->offsets.user ?
299  str + parser->offsets.user : NULL;
300 
301  /* get correct fnmatch callback */
302  compare = conn->data->set.fnmatch;
303  if(!compare)
304  compare = Curl_fnmatch;
305 
306  /* filter pattern-corresponding filenames */
307  if(compare(conn->data->set.fnmatch_data, wc->pattern,
308  finfo->filename) == 0) {
309  /* discard symlink which is containing multiple " -> " */
310  if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
311  (strstr(finfo->strings.target, " -> "))) {
312  add = FALSE;
313  }
314  }
315  else {
316  add = FALSE;
317  }
318 
319  if(add) {
320  Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
321  }
322  else {
323  Curl_fileinfo_dtor(NULL, finfo);
324  }
325 
326  tmpdata->parser->file_data = NULL;
327  return CURLE_OK;
328 }
329 
330 size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
331  void *connptr)
332 {
333  size_t bufflen = size*nmemb;
334  struct connectdata *conn = (struct connectdata *)connptr;
335  struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
336  struct ftp_parselist_data *parser = tmpdata->parser;
337  struct fileinfo *infop;
338  struct curl_fileinfo *finfo;
339  unsigned long i = 0;
341 
342  if(parser->error) { /* error in previous call */
343  /* scenario:
344  * 1. call => OK..
345  * 2. call => OUT_OF_MEMORY (or other error)
346  * 3. (last) call => is skipped RIGHT HERE and the error is hadled later
347  * in wc_statemach()
348  */
349  return bufflen;
350  }
351 
352  if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
353  /* considering info about FILE response format */
354  parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
355  OS_TYPE_WIN_NT : OS_TYPE_UNIX;
356  }
357 
358  while(i < bufflen) { /* FSM */
359 
360  char c = buffer[i];
361  if(!parser->file_data) { /* tmp file data is not allocated yet */
362  parser->file_data = Curl_fileinfo_alloc();
363  if(!parser->file_data) {
364  parser->error = CURLE_OUT_OF_MEMORY;
365  return bufflen;
366  }
368  if(!parser->file_data->info.b_data) {
370  return bufflen;
371  }
373  parser->item_offset = 0;
374  parser->item_length = 0;
375  }
376 
377  infop = parser->file_data;
378  finfo = &infop->info;
379  finfo->b_data[finfo->b_used++] = c;
380 
381  if(finfo->b_used >= finfo->b_size - 1) {
382  /* if it is important, extend buffer space for file data */
383  char *tmp = realloc(finfo->b_data,
384  finfo->b_size + FTP_BUFFER_ALLOCSIZE);
385  if(tmp) {
386  finfo->b_size += FTP_BUFFER_ALLOCSIZE;
387  finfo->b_data = tmp;
388  }
389  else {
390  Curl_fileinfo_dtor(NULL, parser->file_data);
391  parser->file_data = NULL;
392  parser->error = CURLE_OUT_OF_MEMORY;
394  return bufflen;
395  }
396  }
397 
398  switch(parser->os_type) {
399  case OS_TYPE_UNIX:
400  switch(parser->state.UNIX.main) {
401  case PL_UNIX_TOTALSIZE:
402  switch(parser->state.UNIX.sub.total_dirsize) {
403  case PL_UNIX_TOTALSIZE_INIT:
404  if(c == 't') {
405  parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
406  parser->item_length++;
407  }
408  else {
409  parser->state.UNIX.main = PL_UNIX_FILETYPE;
410  /* start FSM again not considering size of directory */
411  finfo->b_used = 0;
412  i--;
413  }
414  break;
415  case PL_UNIX_TOTALSIZE_READING:
416  parser->item_length++;
417  if(c == '\r') {
418  parser->item_length--;
419  finfo->b_used--;
420  }
421  else if(c == '\n') {
422  finfo->b_data[parser->item_length - 1] = 0;
423  if(strncmp("total ", finfo->b_data, 6) == 0) {
424  char *endptr = finfo->b_data + 6;
425  /* here we can deal with directory size, pass the leading white
426  spaces and then the digits */
427  while(ISSPACE(*endptr))
428  endptr++;
429  while(ISDIGIT(*endptr))
430  endptr++;
431  if(*endptr != 0) {
433  return bufflen;
434  }
435  parser->state.UNIX.main = PL_UNIX_FILETYPE;
436  finfo->b_used = 0;
437  }
438  else {
440  return bufflen;
441  }
442  }
443  break;
444  }
445  break;
446  case PL_UNIX_FILETYPE:
447  switch(c) {
448  case '-':
449  finfo->filetype = CURLFILETYPE_FILE;
450  break;
451  case 'd':
453  break;
454  case 'l':
456  break;
457  case 'p':
459  break;
460  case 's':
461  finfo->filetype = CURLFILETYPE_SOCKET;
462  break;
463  case 'c':
465  break;
466  case 'b':
468  break;
469  case 'D':
470  finfo->filetype = CURLFILETYPE_DOOR;
471  break;
472  default:
474  return bufflen;
475  }
476  parser->state.UNIX.main = PL_UNIX_PERMISSION;
477  parser->item_length = 0;
478  parser->item_offset = 1;
479  break;
480  case PL_UNIX_PERMISSION:
481  parser->item_length++;
482  if(parser->item_length <= 9) {
483  if(!strchr("rwx-tTsS", c)) {
485  return bufflen;
486  }
487  }
488  else if(parser->item_length == 10) {
489  unsigned int perm;
490  if(c != ' ') {
492  return bufflen;
493  }
494  finfo->b_data[10] = 0; /* terminate permissions */
495  perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
496  if(perm & FTP_LP_MALFORMATED_PERM) {
498  return bufflen;
499  }
501  parser->file_data->info.perm = perm;
502  parser->offsets.perm = parser->item_offset;
503 
504  parser->item_length = 0;
505  parser->state.UNIX.main = PL_UNIX_HLINKS;
506  parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
507  }
508  break;
509  case PL_UNIX_HLINKS:
510  switch(parser->state.UNIX.sub.hlinks) {
511  case PL_UNIX_HLINKS_PRESPACE:
512  if(c != ' ') {
513  if(c >= '0' && c <= '9') {
514  parser->item_offset = finfo->b_used - 1;
515  parser->item_length = 1;
516  parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
517  }
518  else {
520  return bufflen;
521  }
522  }
523  break;
524  case PL_UNIX_HLINKS_NUMBER:
525  parser->item_length ++;
526  if(c == ' ') {
527  char *p;
528  long int hlinks;
529  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
530  hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
531  if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
533  parser->file_data->info.hardlinks = hlinks;
534  }
535  parser->item_length = 0;
536  parser->item_offset = 0;
537  parser->state.UNIX.main = PL_UNIX_USER;
538  parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
539  }
540  else if(c < '0' || c > '9') {
542  return bufflen;
543  }
544  break;
545  }
546  break;
547  case PL_UNIX_USER:
548  switch(parser->state.UNIX.sub.user) {
549  case PL_UNIX_USER_PRESPACE:
550  if(c != ' ') {
551  parser->item_offset = finfo->b_used - 1;
552  parser->item_length = 1;
553  parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
554  }
555  break;
556  case PL_UNIX_USER_PARSING:
557  parser->item_length++;
558  if(c == ' ') {
559  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
560  parser->offsets.user = parser->item_offset;
561  parser->state.UNIX.main = PL_UNIX_GROUP;
562  parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
563  parser->item_offset = 0;
564  parser->item_length = 0;
565  }
566  break;
567  }
568  break;
569  case PL_UNIX_GROUP:
570  switch(parser->state.UNIX.sub.group) {
571  case PL_UNIX_GROUP_PRESPACE:
572  if(c != ' ') {
573  parser->item_offset = finfo->b_used - 1;
574  parser->item_length = 1;
575  parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
576  }
577  break;
578  case PL_UNIX_GROUP_NAME:
579  parser->item_length++;
580  if(c == ' ') {
581  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
582  parser->offsets.group = parser->item_offset;
583  parser->state.UNIX.main = PL_UNIX_SIZE;
584  parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
585  parser->item_offset = 0;
586  parser->item_length = 0;
587  }
588  break;
589  }
590  break;
591  case PL_UNIX_SIZE:
592  switch(parser->state.UNIX.sub.size) {
593  case PL_UNIX_SIZE_PRESPACE:
594  if(c != ' ') {
595  if(c >= '0' && c <= '9') {
596  parser->item_offset = finfo->b_used - 1;
597  parser->item_length = 1;
598  parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
599  }
600  else {
602  return bufflen;
603  }
604  }
605  break;
606  case PL_UNIX_SIZE_NUMBER:
607  parser->item_length++;
608  if(c == ' ') {
609  char *p;
610  curl_off_t fsize;
611  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
612  if(!curlx_strtoofft(finfo->b_data + parser->item_offset,
613  &p, 10, &fsize)) {
614  if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
615  fsize != CURL_OFF_T_MIN) {
617  parser->file_data->info.size = fsize;
618  }
619  parser->item_length = 0;
620  parser->item_offset = 0;
621  parser->state.UNIX.main = PL_UNIX_TIME;
622  parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
623  }
624  }
625  else if(!ISDIGIT(c)) {
627  return bufflen;
628  }
629  break;
630  }
631  break;
632  case PL_UNIX_TIME:
633  switch(parser->state.UNIX.sub.time) {
634  case PL_UNIX_TIME_PREPART1:
635  if(c != ' ') {
636  if(ISALNUM(c)) {
637  parser->item_offset = finfo->b_used -1;
638  parser->item_length = 1;
639  parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
640  }
641  else {
643  return bufflen;
644  }
645  }
646  break;
647  case PL_UNIX_TIME_PART1:
648  parser->item_length++;
649  if(c == ' ') {
650  parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
651  }
652  else if(!ISALNUM(c) && c != '.') {
654  return bufflen;
655  }
656  break;
657  case PL_UNIX_TIME_PREPART2:
658  parser->item_length++;
659  if(c != ' ') {
660  if(ISALNUM(c)) {
661  parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
662  }
663  else {
665  return bufflen;
666  }
667  }
668  break;
669  case PL_UNIX_TIME_PART2:
670  parser->item_length++;
671  if(c == ' ') {
672  parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
673  }
674  else if(!ISALNUM(c) && c != '.') {
676  return bufflen;
677  }
678  break;
679  case PL_UNIX_TIME_PREPART3:
680  parser->item_length++;
681  if(c != ' ') {
682  if(ISALNUM(c)) {
683  parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
684  }
685  else {
687  return bufflen;
688  }
689  }
690  break;
691  case PL_UNIX_TIME_PART3:
692  parser->item_length++;
693  if(c == ' ') {
694  finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
695  parser->offsets.time = parser->item_offset;
696  /*
697  if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
698  parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
699  }
700  */
701  if(finfo->filetype == CURLFILETYPE_SYMLINK) {
702  parser->state.UNIX.main = PL_UNIX_SYMLINK;
703  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
704  }
705  else {
706  parser->state.UNIX.main = PL_UNIX_FILENAME;
707  parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
708  }
709  }
710  else if(!ISALNUM(c) && c != '.' && c != ':') {
712  return bufflen;
713  }
714  break;
715  }
716  break;
717  case PL_UNIX_FILENAME:
718  switch(parser->state.UNIX.sub.filename) {
719  case PL_UNIX_FILENAME_PRESPACE:
720  if(c != ' ') {
721  parser->item_offset = finfo->b_used - 1;
722  parser->item_length = 1;
723  parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
724  }
725  break;
726  case PL_UNIX_FILENAME_NAME:
727  parser->item_length++;
728  if(c == '\r') {
729  parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
730  }
731  else if(c == '\n') {
732  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
733  parser->offsets.filename = parser->item_offset;
734  parser->state.UNIX.main = PL_UNIX_FILETYPE;
735  result = ftp_pl_insert_finfo(conn, infop);
736  if(result) {
737  PL_ERROR(conn, result);
738  return bufflen;
739  }
740  }
741  break;
742  case PL_UNIX_FILENAME_WINDOWSEOL:
743  if(c == '\n') {
744  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
745  parser->offsets.filename = parser->item_offset;
746  parser->state.UNIX.main = PL_UNIX_FILETYPE;
747  result = ftp_pl_insert_finfo(conn, infop);
748  if(result) {
749  PL_ERROR(conn, result);
750  return bufflen;
751  }
752  }
753  else {
755  return bufflen;
756  }
757  break;
758  }
759  break;
760  case PL_UNIX_SYMLINK:
761  switch(parser->state.UNIX.sub.symlink) {
762  case PL_UNIX_SYMLINK_PRESPACE:
763  if(c != ' ') {
764  parser->item_offset = finfo->b_used - 1;
765  parser->item_length = 1;
766  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
767  }
768  break;
769  case PL_UNIX_SYMLINK_NAME:
770  parser->item_length++;
771  if(c == ' ') {
772  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
773  }
774  else if(c == '\r' || c == '\n') {
776  return bufflen;
777  }
778  break;
779  case PL_UNIX_SYMLINK_PRETARGET1:
780  parser->item_length++;
781  if(c == '-') {
782  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
783  }
784  else if(c == '\r' || c == '\n') {
786  return bufflen;
787  }
788  else {
789  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
790  }
791  break;
792  case PL_UNIX_SYMLINK_PRETARGET2:
793  parser->item_length++;
794  if(c == '>') {
795  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
796  }
797  else if(c == '\r' || c == '\n') {
799  return bufflen;
800  }
801  else {
802  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
803  }
804  break;
805  case PL_UNIX_SYMLINK_PRETARGET3:
806  parser->item_length++;
807  if(c == ' ') {
808  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
809  /* now place where is symlink following */
810  finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
811  parser->offsets.filename = parser->item_offset;
812  parser->item_length = 0;
813  parser->item_offset = 0;
814  }
815  else if(c == '\r' || c == '\n') {
817  return bufflen;
818  }
819  else {
820  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
821  }
822  break;
823  case PL_UNIX_SYMLINK_PRETARGET4:
824  if(c != '\r' && c != '\n') {
825  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
826  parser->item_offset = finfo->b_used - 1;
827  parser->item_length = 1;
828  }
829  else {
831  return bufflen;
832  }
833  break;
834  case PL_UNIX_SYMLINK_TARGET:
835  parser->item_length++;
836  if(c == '\r') {
837  parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
838  }
839  else if(c == '\n') {
840  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
841  parser->offsets.symlink_target = parser->item_offset;
842  result = ftp_pl_insert_finfo(conn, infop);
843  if(result) {
844  PL_ERROR(conn, result);
845  return bufflen;
846  }
847  parser->state.UNIX.main = PL_UNIX_FILETYPE;
848  }
849  break;
850  case PL_UNIX_SYMLINK_WINDOWSEOL:
851  if(c == '\n') {
852  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
853  parser->offsets.symlink_target = parser->item_offset;
854  result = ftp_pl_insert_finfo(conn, infop);
855  if(result) {
856  PL_ERROR(conn, result);
857  return bufflen;
858  }
859  parser->state.UNIX.main = PL_UNIX_FILETYPE;
860  }
861  else {
863  return bufflen;
864  }
865  break;
866  }
867  break;
868  }
869  break;
870  case OS_TYPE_WIN_NT:
871  switch(parser->state.NT.main) {
872  case PL_WINNT_DATE:
873  parser->item_length++;
874  if(parser->item_length < 9) {
875  if(!strchr("0123456789-", c)) { /* only simple control */
877  return bufflen;
878  }
879  }
880  else if(parser->item_length == 9) {
881  if(c == ' ') {
882  parser->state.NT.main = PL_WINNT_TIME;
883  parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
884  }
885  else {
887  return bufflen;
888  }
889  }
890  else {
892  return bufflen;
893  }
894  break;
895  case PL_WINNT_TIME:
896  parser->item_length++;
897  switch(parser->state.NT.sub.time) {
898  case PL_WINNT_TIME_PRESPACE:
899  if(!ISSPACE(c)) {
900  parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
901  }
902  break;
903  case PL_WINNT_TIME_TIME:
904  if(c == ' ') {
905  parser->offsets.time = parser->item_offset;
906  finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
907  parser->state.NT.main = PL_WINNT_DIRORSIZE;
908  parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
909  parser->item_length = 0;
910  }
911  else if(!strchr("APM0123456789:", c)) {
913  return bufflen;
914  }
915  break;
916  }
917  break;
918  case PL_WINNT_DIRORSIZE:
919  switch(parser->state.NT.sub.dirorsize) {
920  case PL_WINNT_DIRORSIZE_PRESPACE:
921  if(c == ' ') {
922 
923  }
924  else {
925  parser->item_offset = finfo->b_used - 1;
926  parser->item_length = 1;
927  parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
928  }
929  break;
930  case PL_WINNT_DIRORSIZE_CONTENT:
931  parser->item_length ++;
932  if(c == ' ') {
933  finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
934  if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
936  finfo->size = 0;
937  }
938  else {
939  char *endptr;
940  if(curlx_strtoofft(finfo->b_data +
941  parser->item_offset,
942  &endptr, 10, &finfo->size)) {
944  return bufflen;
945  }
946  /* correct file type */
948  }
949 
951  parser->item_length = 0;
952  parser->state.NT.main = PL_WINNT_FILENAME;
953  parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
954  }
955  break;
956  }
957  break;
958  case PL_WINNT_FILENAME:
959  switch(parser->state.NT.sub.filename) {
960  case PL_WINNT_FILENAME_PRESPACE:
961  if(c != ' ') {
962  parser->item_offset = finfo->b_used -1;
963  parser->item_length = 1;
964  parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
965  }
966  break;
967  case PL_WINNT_FILENAME_CONTENT:
968  parser->item_length++;
969  if(c == '\r') {
970  parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
971  finfo->b_data[finfo->b_used - 1] = 0;
972  }
973  else if(c == '\n') {
974  parser->offsets.filename = parser->item_offset;
975  finfo->b_data[finfo->b_used - 1] = 0;
976  parser->offsets.filename = parser->item_offset;
977  result = ftp_pl_insert_finfo(conn, infop);
978  if(result) {
979  PL_ERROR(conn, result);
980  return bufflen;
981  }
982  parser->state.NT.main = PL_WINNT_DATE;
983  parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
984  }
985  break;
986  case PL_WINNT_FILENAME_WINEOL:
987  if(c == '\n') {
988  parser->offsets.filename = parser->item_offset;
989  result = ftp_pl_insert_finfo(conn, infop);
990  if(result) {
991  PL_ERROR(conn, result);
992  return bufflen;
993  }
994  parser->state.NT.main = PL_WINNT_DATE;
995  parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
996  }
997  else {
999  return bufflen;
1000  }
1001  break;
1002  }
1003  break;
1004  }
1005  break;
1006  default:
1007  return bufflen + 1;
1008  }
1009 
1010  i++;
1011  }
1012 
1013  return bufflen;
1014 }
1015 
1016 #endif /* CURL_DISABLE_FTP */
#define free(ptr)
Definition: curl_memory.h:130
struct ftp_parselist_data::@24 offsets
unsigned int flags
Definition: curl.h:296
#define state(x, y)
Definition: ftp.c:100
int(* curl_fnmatch_callback)(void *ptr, const char *pattern, const char *string)
Definition: curl.h:335
struct ftp_parselist_data * parser
Definition: ftp.h:85
#define CURLFINFOFLAG_KNOWN_HLINKCOUNT
Definition: curl.h:271
unsigned int perm
Definition: curl.h:281
struct UserDefined set
Definition: urldata.h:1762
void * fnmatch_data
Definition: urldata.h:1682
#define CURLFINFOFLAG_KNOWN_PERM
Definition: curl.h:267
void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
size_t b_size
Definition: curl.h:300
struct curl_fileinfo::@5 strings
static void PL_ERROR(struct connectdata *conn, CURLcode err)
struct curl_llist_element * tail
Definition: llist.h:38
CURLcode
Definition: curl.h:454
struct ftp_parselist_data::@23::@25 UNIX
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
Definition: curl_fnmatch.c:416
struct fileinfo * file_data
#define ISALNUM(x)
char * target
Definition: curl.h:293
#define CURLFINFOFLAG_KNOWN_SIZE
Definition: curl.h:270
#define realloc(ptr, size)
Definition: curl_memory.h:128
char * user
Definition: curl.h:291
#define malloc(size)
Definition: curl_memory.h:124
curl_fnmatch_callback fnmatch
Definition: urldata.h:1680
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
struct fileinfo * Curl_fileinfo_alloc(void)
Definition: fileinfo.c:31
UNITTEST_START int result
Definition: unit1304.c:49
const char ** p
Definition: unit1394.c:76
char buffer[]
Definition: unit1308.c:48
unsigned int i
Definition: unit1303.c:79
pl_winNT_mainstate main
const char * str
Definition: unit1398.c:33
#define FALSE
static int ftp_pl_get_permission(const char *str)
pl_winNT_mainstate
#define compare(i, j)
Definition: splay.c:34
curl_off_t size
Definition: curl.h:284
#define ISDIGIT(x)
CURLofft curlx_strtoofft(const char *str, char **endp, int base, curl_off_t *num)
Definition: strtoofft.c:215
pl_winNT_substate sub
struct curl_llist filelist
Definition: wildcard.h:50
#define CURL_OFF_T_MIN
Definition: strtoofft.h:49
CURL_TYPEOF_CURL_OFF_T curl_off_t
Definition: system.h:420
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr)
pl_unix_mainstate
Definition: ftplistparser.c:58
struct curl_llist_element list
Definition: fileinfo.h:30
Definition: curl.h:455
curlfiletype filetype
Definition: curl.h:279
unsigned int item_length
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn, struct fileinfo *infop)
char * b_data
Definition: curl.h:299
#define ISSPACE(x)
pl_unix_substate sub
void * tmp
Definition: wildcard.h:51
size_t b_used
Definition: curl.h:301
char * group
Definition: curl.h:292
char * pattern
Definition: wildcard.h:49
union ftp_parselist_data::@23 state
long int hardlinks
Definition: curl.h:285
#define FTP_LP_MALFORMATED_PERM
time_t time
Definition: curl.h:280
#define CURL_OFF_T_MAX
Definition: strtoofft.h:47
parser
static struct curl_llist llist
testing Curl_llist_insert_next case 1: list is empty : 1: list size will be 1 2: list head will hold ...
Definition: unit1300.c:26
CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
#define FTP_BUFFER_ALLOCSIZE
Now implemented:
Definition: ftplistparser.c:56
void Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e, const void *p, struct curl_llist_element *ne)
Definition: llist.c:57
struct ftp_parselist_data::@23::@26 NT
enum ftp_parselist_data::@22 os_type
size_t size
Definition: unit1302.c:52
#define TRUE
struct WildcardData wildcard
Definition: urldata.h:1771
void Curl_fileinfo_dtor(void *user, void *element)
Definition: fileinfo.c:36
struct curl_fileinfo info
Definition: fileinfo.h:29
const char * filename
Definition: ftpget.c:32
pl_unix_mainstate main
#define calloc(nbelem, size)
Definition: curl_memory.h:126
struct ftp_parselist_data * Curl_ftp_parselist_data_alloc(void)
struct Curl_easy * data
Definition: urldata.h:791
char * filename
Definition: curl.h:278


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09