Newer
Older
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
Daniel Stenberg
committed
* Copyright (C) 1998 - 2007, 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
* are also available at http://curl.haxx.se/docs/copyright.html.
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
***************************************************************************/
#ifndef CURL_DISABLE_FTP
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifndef WIN32
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#include <inet.h>
#endif
#endif /* !WIN32 */
#if (defined(NETWARE) && defined(__NOVELL_LIBC__))
#undef in_addr_t
#define in_addr_t unsigned long
#endif
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#include "easyif.h" /* for Curl_convert_... prototypes */
#include "if2ip.h"
#include "hostip.h"
#include "progress.h"
Daniel Stenberg
committed
#include "transfer.h"
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "ftp.h"
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#include "krb4.h"
Daniel Stenberg
committed
#include "sslgen.h"
#include "memory.h"
Daniel Stenberg
committed
#include "inet_ntop.h"
#include "parsedate.h" /* for the week day and month names */
Daniel Stenberg
committed
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
Daniel Stenberg
committed
#include "multiif.h"
Daniel Stenberg
committed
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
Daniel Stenberg
committed
#ifdef CURLDEBUG
#ifdef HAVE_NI_WITHSCOPEID
Daniel Stenberg
committed
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID
#else
#define NIFLAGS NI_NUMERICHOST | NI_NUMERICSERV
#endif
#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define ftp_pasv_verbose(a,b,c,d) do { } while (0)
#endif
static CURLcode ftp_sendquote(struct connectdata *conn,
struct curl_slist *quote);
Daniel Stenberg
committed
static CURLcode ftp_quit(struct connectdata *conn);
Daniel Stenberg
committed
static CURLcode ftp_parse_url_path(struct connectdata *conn);
static CURLcode ftp_regular_transfer(struct connectdata *conn, bool *done);
static void ftp_pasv_verbose(struct connectdata *conn,
Curl_addrinfo *ai,
char *newhost, /* ascii version */
int port);
static CURLcode ftp_state_post_rest(struct connectdata *conn);
static CURLcode ftp_state_post_cwd(struct connectdata *conn);
static CURLcode ftp_state_quote(struct connectdata *conn,
bool init, ftpstate instate);
Daniel Stenberg
committed
static CURLcode ftp_nb_type(struct connectdata *conn,
bool ascii, ftpstate newstate);
Daniel Stenberg
committed
static int ftp_need_type(struct connectdata *conn,
bool ascii);
Patrick Monnerat
committed
static CURLcode Curl_ftp(struct connectdata *conn, bool *done);
static CURLcode Curl_ftp_done(struct connectdata *conn,
CURLcode, bool premature);
static CURLcode Curl_ftp_connect(struct connectdata *conn, bool *done);
static CURLcode Curl_ftp_disconnect(struct connectdata *conn);
static CURLcode Curl_ftp_nextconnect(struct connectdata *conn);
static CURLcode Curl_ftp_multi_statemach(struct connectdata *conn, bool *done);
static int Curl_ftp_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks);
static CURLcode Curl_ftp_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode Curl_ftp_setup_connection(struct connectdata * conn);
#ifdef USE_SSL
Patrick Monnerat
committed
static CURLcode Curl_ftps_setup_connection(struct connectdata * conn);
#endif
/* easy-to-use macro: */
Gisle Vanem
committed
#define FTPSENDF(x,y,z) if ((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
return result
#define NBFTPSENDF(x,y,z) if ((result = Curl_nbftpsendf(x,y,z)) != CURLE_OK) \
return result
Patrick Monnerat
committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
* FTP protocol handler.
*/
const struct Curl_handler Curl_handler_ftp = {
"FTP", /* scheme */
Curl_ftp_setup_connection, /* setup_connection */
Curl_ftp, /* do_it */
Curl_ftp_done, /* done */
Curl_ftp_nextconnect, /* do_more */
Curl_ftp_connect, /* connect_it */
Curl_ftp_multi_statemach, /* connecting */
Curl_ftp_doing, /* doing */
Curl_ftp_getsock, /* proto_getsock */
Curl_ftp_getsock, /* doing_getsock */
Curl_ftp_disconnect, /* disconnect */
PORT_FTP, /* defport */
PROT_FTP /* protocol */
};
#ifdef USE_SSL
/*
* FTPS protocol handler.
*/
const struct Curl_handler Curl_handler_ftps = {
"FTPS", /* scheme */
Curl_ftps_setup_connection, /* setup_connection */
Curl_ftp, /* do_it */
Curl_ftp_done, /* done */
Curl_ftp_nextconnect, /* do_more */
Curl_ftp_connect, /* connect_it */
Curl_ftp_multi_statemach, /* connecting */
Curl_ftp_doing, /* doing */
Curl_ftp_getsock, /* proto_getsock */
Curl_ftp_getsock, /* doing_getsock */
Curl_ftp_disconnect, /* disconnect */
PORT_FTPS, /* defport */
PROT_FTP | PROT_FTPS | PROT_SSL /* protocol */
Patrick Monnerat
committed
};
#endif
#ifndef CURL_DISABLE_HTTP
/*
* HTTP-proxyed FTP protocol handler.
*/
const struct Curl_handler Curl_handler_ftp_proxy = {
"FTP", /* scheme */
ZERO_NULL, /* setup_connection */
Patrick Monnerat
committed
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* disconnect */
Patrick Monnerat
committed
PORT_FTP, /* defport */
PROT_HTTP /* protocol */
};
Patrick Monnerat
committed
/*
* HTTP-proxyed FTPS protocol handler.
*/
const struct Curl_handler Curl_handler_ftps_proxy = {
"FTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Patrick Monnerat
committed
Curl_http, /* do_it */
Curl_http_done, /* done */
ZERO_NULL, /* do_more */
ZERO_NULL, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* disconnect */
Patrick Monnerat
committed
PORT_FTPS, /* defport */
PROT_HTTP /* protocol */
};
Patrick Monnerat
committed
#endif
/*
* NOTE: back in the old days, we added code in the FTP code that made NOBODY
* requests on files respond with headers passed to the client/stdout that
* looked like HTTP ones.
*
* This approach is not very elegant, it causes confusion and is error-prone.
* It is subject for removal at the next (or at least a future) soname bump.
* Until then you can test the effects of the removal by undefining the
* following define named CURL_FTP_HTTPSTYLE_HEAD.
*/
#define CURL_FTP_HTTPSTYLE_HEAD 1
Daniel Stenberg
committed
static void freedirs(struct ftp_conn *ftpc)
{
int i;
if(ftpc->dirs) {
for (i=0; i < ftpc->dirdepth; i++){
if(ftpc->dirs[i]) {
free(ftpc->dirs[i]);
ftpc->dirs[i]=NULL;
free(ftpc->dirs);
ftpc->dirs = NULL;
if(ftpc->file) {
free(ftpc->file);
ftpc->file = NULL;
}
}
/* Returns non-zero if the given string contains CR (\r) or LF (\n),
which
Loading
Loading full blame...