* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
/**
* Now implemented:
*
- * 1) UNIX version 1
+ * 1) Unix version 1
* drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
- * 2) UNIX version 2
+ * 2) Unix version 2
* drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
- * 3) UNIX version 3
+ * 3) Unix version 3
* drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
- * 4) UNIX symlink
+ * 4) Unix symlink
* lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
* 5) DOS style
* 01-29-97 11:32PM <DIR> prog
*/
-#include "setup.h"
+#include "curl_setup.h"
-#include <time.h>
+#ifndef CURL_DISABLE_FTP
-#include "ftplistparser.h"
-#include "curl_fnmatch.h"
+#include <curl/curl.h>
#include "urldata.h"
-#include "ftp.h"
#include "fileinfo.h"
#include "llist.h"
#include "strtoofft.h"
#include "rawstr.h"
#include "ftp.h"
+#include "ftplistparser.h"
+#include "curl_fnmatch.h"
+
+#define _MPRINTF_REPLACE /* use our functions only */
+#include <curl/mprintf.h>
+
+#include "curl_memory.h"
+/* The last #include file should be: */
+#include "memdebug.h"
/* allocs buffer which will contain one line of LIST command response */
#define FTP_BUFFER_ALLOCSIZE 160
typedef enum {
- PL_UNIX_FILETYPE = 0,
+ PL_UNIX_TOTALSIZE = 0,
+ PL_UNIX_FILETYPE,
PL_UNIX_PERMISSION,
PL_UNIX_HLINKS,
PL_UNIX_USER,
typedef union {
enum {
+ PL_UNIX_TOTALSIZE_INIT = 0,
+ PL_UNIX_TOTALSIZE_READING
+ } total_dirsize;
+
+ enum {
PL_UNIX_HLINKS_PRESPACE = 0,
PL_UNIX_HLINKS_NUMBER
} hlinks;
} NT;
} state;
- struct {
- char *buffer;
- size_t bufferlength; /* how many bytes is allocated at *buffer */
- size_t bufferin; /* how many bytes is in buffer */
- } tmpdata;
-
- struct {
- curl_write_callback old_fwritefunc;
- FILE *old_file_descriptor;
- } backup;
-
CURLcode error;
struct curl_fileinfo *file_data;
unsigned int item_length;
} offsets;
};
-struct ftp_parselist_data *ftp_parselist_data_alloc(void)
+struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
{
- struct ftp_parselist_data *parselist_data =
- malloc(sizeof(struct ftp_parselist_data));
- if(!parselist_data)
- return ZERO_NULL;
- memset(parselist_data, 0, sizeof(struct ftp_parselist_data));
- return parselist_data;
+ return calloc(1, sizeof(struct ftp_parselist_data));
}
-void ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
+void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
{
if(*pl_data)
free(*pl_data);
}
-CURLcode ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
+CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
{
return pl_data->error;
}
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
- if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) {
+ if(compare(conn->data->set.fnmatch_data, wc->pattern,
+ finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
- if((finfo->filetype == CURLFILETYPE_SYMLINK) &&
+ if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
(strstr(finfo->strings.target, " -> "))) {
add = FALSE;
}
return CURLE_OK;
}
-size_t ftp_parselist(char *buffer, size_t size, size_t nmemb, void *connptr)
+size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
+ void *connptr)
{
size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr;
struct ftp_parselist_data *parser = tmpdata->parser;
struct curl_fileinfo *finfo;
unsigned long i = 0;
- CURLcode rc;
+ CURLcode result;
if(parser->error) { /* error in previous call */
/* scenario:
}
finfo = parser->file_data;
- finfo->b_data[finfo->b_used++] = buffer[i];
+ finfo->b_data[finfo->b_used++] = c;
if(finfo->b_used >= finfo->b_size - 1) {
/* if it is important, extend buffer space for file data */
else {
Curl_fileinfo_dtor(NULL, parser->file_data);
parser->file_data = NULL;
+ parser->error = CURLE_OUT_OF_MEMORY;
+ PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
+ return bufflen;
}
}
switch (parser->os_type) {
case OS_TYPE_UNIX:
switch (parser->state.UNIX.main) {
+ case PL_UNIX_TOTALSIZE:
+ switch(parser->state.UNIX.sub.total_dirsize) {
+ case PL_UNIX_TOTALSIZE_INIT:
+ if(c == 't') {
+ parser->state.UNIX.sub.total_dirsize = PL_UNIX_TOTALSIZE_READING;
+ parser->item_length++;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ /* start FSM again not considering size of directory */
+ finfo->b_used = 0;
+ i--;
+ }
+ break;
+ case PL_UNIX_TOTALSIZE_READING:
+ parser->item_length++;
+ if(c == '\r') {
+ parser->item_length--;
+ finfo->b_used--;
+ }
+ else if(c == '\n') {
+ finfo->b_data[parser->item_length - 1] = 0;
+ if(strncmp("total ", finfo->b_data, 6) == 0) {
+ char *endptr = finfo->b_data+6;
+ /* here we can deal with directory size, pass the leading white
+ spaces and then the digits */
+ while(ISSPACE(*endptr))
+ endptr++;
+ while(ISDIGIT(*endptr))
+ endptr++;
+ if(*endptr != 0) {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ else {
+ parser->state.UNIX.main = PL_UNIX_FILETYPE;
+ finfo->b_used = 0;
+ }
+ }
+ else {
+ PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
+ return bufflen;
+ }
+ }
+ break;
+ }
+ break;
case PL_UNIX_FILETYPE:
switch (c) {
case '-':
default:
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
- break;
}
parser->state.UNIX.main = PL_UNIX_PERMISSION;
parser->item_length = 0;
curl_off_t fsize;
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
- if(p[0] == '\0' && fsize != CURL_LLONG_MAX &&
- fsize != CURL_LLONG_MIN) {
+ if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
+ fsize != CURL_OFF_T_MIN) {
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
parser->file_data->size = fsize;
}
parser->state.UNIX.main = PL_UNIX_TIME;
parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
}
- else if (!ISDIGIT(c)) {
+ else if(!ISDIGIT(c)) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
}
finfo->b_data[parser->item_offset + parser->item_length] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
}
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
parser->state.UNIX.main = PL_UNIX_FILETYPE;
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
parser->state.UNIX.main = PL_UNIX_FILETYPE;
}
else {
char *endptr;
- finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset,
+ finfo->size = curlx_strtoofft(finfo->b_data +
+ parser->item_offset,
&endptr, 10);
if(!*endptr) {
- if(finfo->size == CURL_LLONG_MAX ||
- finfo->size == CURL_LLONG_MIN) {
+ if(finfo->size == CURL_OFF_T_MAX ||
+ finfo->size == CURL_OFF_T_MIN) {
if(errno == ERANGE) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
- /* correct file size */
+ /* correct file type */
parser->file_data->filetype = CURLFILETYPE_FILE;
}
parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0;
parser->offsets.filename = parser->item_offset;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
parser->state.NT.main = PL_WINNT_DATE;
case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') {
parser->offsets.filename = parser->item_offset;
- rc = ftp_pl_insert_finfo(conn, finfo);
- if(rc) {
- PL_ERROR(conn, rc);
+ result = ftp_pl_insert_finfo(conn, finfo);
+ if(result) {
+ PL_ERROR(conn, result);
return bufflen;
}
parser->state.NT.main = PL_WINNT_DATE;
}
break;
default:
- return bufflen+1;
- break;
+ return bufflen + 1;
}
i++;
return bufflen;
}
+
+#endif /* CURL_DISABLE_FTP */