1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker * nanoftp.c: basic FTP client support
3*6777b538SAndroid Build Coastguard Worker *
4*6777b538SAndroid Build Coastguard Worker * Reference: RFC 959
5*6777b538SAndroid Build Coastguard Worker */
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #ifdef TESTING
8*6777b538SAndroid Build Coastguard Worker #define STANDALONE
9*6777b538SAndroid Build Coastguard Worker #define HAVE_UNISTD_H
10*6777b538SAndroid Build Coastguard Worker #define HAVE_SYS_SOCKET_H
11*6777b538SAndroid Build Coastguard Worker #define HAVE_NETINET_IN_H
12*6777b538SAndroid Build Coastguard Worker #define HAVE_NETDB_H
13*6777b538SAndroid Build Coastguard Worker #define HAVE_SYS_TIME_H
14*6777b538SAndroid Build Coastguard Worker #endif /* TESTING */
15*6777b538SAndroid Build Coastguard Worker
16*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
17*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_FTP_ENABLED
20*6777b538SAndroid Build Coastguard Worker #include <string.h>
21*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
22*6777b538SAndroid Build Coastguard Worker #include <errno.h>
23*6777b538SAndroid Build Coastguard Worker
24*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_UNISTD_H
25*6777b538SAndroid Build Coastguard Worker #include <unistd.h>
26*6777b538SAndroid Build Coastguard Worker #elif defined (_WIN32)
27*6777b538SAndroid Build Coastguard Worker #include <io.h>
28*6777b538SAndroid Build Coastguard Worker #endif
29*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SOCKET_H
30*6777b538SAndroid Build Coastguard Worker #include <sys/socket.h>
31*6777b538SAndroid Build Coastguard Worker #endif
32*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_NETINET_IN_H
33*6777b538SAndroid Build Coastguard Worker #include <netinet/in.h>
34*6777b538SAndroid Build Coastguard Worker #endif
35*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_ARPA_INET_H
36*6777b538SAndroid Build Coastguard Worker #include <arpa/inet.h>
37*6777b538SAndroid Build Coastguard Worker #endif
38*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_NETDB_H
39*6777b538SAndroid Build Coastguard Worker #include <netdb.h>
40*6777b538SAndroid Build Coastguard Worker #endif
41*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_FCNTL_H
42*6777b538SAndroid Build Coastguard Worker #include <fcntl.h>
43*6777b538SAndroid Build Coastguard Worker #endif
44*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_TIME_H
45*6777b538SAndroid Build Coastguard Worker #include <sys/time.h>
46*6777b538SAndroid Build Coastguard Worker #endif
47*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SELECT_H
48*6777b538SAndroid Build Coastguard Worker #include <sys/select.h>
49*6777b538SAndroid Build Coastguard Worker #endif
50*6777b538SAndroid Build Coastguard Worker #ifdef HAVE_SYS_SOCKET_H
51*6777b538SAndroid Build Coastguard Worker #include <sys/socket.h>
52*6777b538SAndroid Build Coastguard Worker #endif
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
55*6777b538SAndroid Build Coastguard Worker #include <libxml/parser.h>
56*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
57*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
58*6777b538SAndroid Build Coastguard Worker #include <libxml/nanoftp.h>
59*6777b538SAndroid Build Coastguard Worker
60*6777b538SAndroid Build Coastguard Worker #include "private/error.h"
61*6777b538SAndroid Build Coastguard Worker #include "private/io.h"
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Worker #if defined(_WIN32)
64*6777b538SAndroid Build Coastguard Worker #include <wsockcompat.h>
65*6777b538SAndroid Build Coastguard Worker #endif
66*6777b538SAndroid Build Coastguard Worker
67*6777b538SAndroid Build Coastguard Worker /**
68*6777b538SAndroid Build Coastguard Worker * A couple portability macros
69*6777b538SAndroid Build Coastguard Worker */
70*6777b538SAndroid Build Coastguard Worker #ifndef _WINSOCKAPI_
71*6777b538SAndroid Build Coastguard Worker #define closesocket(s) close(s)
72*6777b538SAndroid Build Coastguard Worker #endif
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker #ifndef XML_SOCKLEN_T
75*6777b538SAndroid Build Coastguard Worker #define XML_SOCKLEN_T unsigned int
76*6777b538SAndroid Build Coastguard Worker #endif
77*6777b538SAndroid Build Coastguard Worker
78*6777b538SAndroid Build Coastguard Worker #define GETHOSTBYNAME_ARG_CAST (char *)
79*6777b538SAndroid Build Coastguard Worker #define SEND_ARG2_CAST (char *)
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker #define FTP_COMMAND_OK 200
82*6777b538SAndroid Build Coastguard Worker #define FTP_SYNTAX_ERROR 500
83*6777b538SAndroid Build Coastguard Worker #define FTP_GET_PASSWD 331
84*6777b538SAndroid Build Coastguard Worker #define FTP_BUF_SIZE 1024
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker #define XML_NANO_MAX_URLBUF 4096
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker typedef struct xmlNanoFTPCtxt {
89*6777b538SAndroid Build Coastguard Worker char *protocol; /* the protocol name */
90*6777b538SAndroid Build Coastguard Worker char *hostname; /* the host name */
91*6777b538SAndroid Build Coastguard Worker int port; /* the port */
92*6777b538SAndroid Build Coastguard Worker char *path; /* the path within the URL */
93*6777b538SAndroid Build Coastguard Worker char *user; /* user string */
94*6777b538SAndroid Build Coastguard Worker char *passwd; /* passwd string */
95*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
96*6777b538SAndroid Build Coastguard Worker struct sockaddr_storage ftpAddr; /* this is large enough to hold IPv6 address*/
97*6777b538SAndroid Build Coastguard Worker #else
98*6777b538SAndroid Build Coastguard Worker struct sockaddr_in ftpAddr; /* the socket address struct */
99*6777b538SAndroid Build Coastguard Worker #endif
100*6777b538SAndroid Build Coastguard Worker int passive; /* currently we support only passive !!! */
101*6777b538SAndroid Build Coastguard Worker SOCKET controlFd; /* the file descriptor for the control socket */
102*6777b538SAndroid Build Coastguard Worker SOCKET dataFd; /* the file descriptor for the data socket */
103*6777b538SAndroid Build Coastguard Worker int state; /* WRITE / READ / CLOSED */
104*6777b538SAndroid Build Coastguard Worker int returnValue; /* the protocol return value */
105*6777b538SAndroid Build Coastguard Worker /* buffer for data received from the control connection */
106*6777b538SAndroid Build Coastguard Worker char controlBuf[FTP_BUF_SIZE + 1];
107*6777b538SAndroid Build Coastguard Worker int controlBufIndex;
108*6777b538SAndroid Build Coastguard Worker int controlBufUsed;
109*6777b538SAndroid Build Coastguard Worker int controlBufAnswer;
110*6777b538SAndroid Build Coastguard Worker } xmlNanoFTPCtxt, *xmlNanoFTPCtxtPtr;
111*6777b538SAndroid Build Coastguard Worker
112*6777b538SAndroid Build Coastguard Worker static int initialized = 0;
113*6777b538SAndroid Build Coastguard Worker static char *proxy = NULL; /* the proxy name if any */
114*6777b538SAndroid Build Coastguard Worker static int proxyPort = 0; /* the proxy port if any */
115*6777b538SAndroid Build Coastguard Worker static char *proxyUser = NULL; /* user for proxy authentication */
116*6777b538SAndroid Build Coastguard Worker static char *proxyPasswd = NULL;/* passwd for proxy authentication */
117*6777b538SAndroid Build Coastguard Worker static int proxyType = 0; /* uses TYPE or a@b ? */
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
120*6777b538SAndroid Build Coastguard Worker static
have_ipv6(void)121*6777b538SAndroid Build Coastguard Worker int have_ipv6(void) {
122*6777b538SAndroid Build Coastguard Worker int s;
123*6777b538SAndroid Build Coastguard Worker
124*6777b538SAndroid Build Coastguard Worker s = socket (AF_INET6, SOCK_STREAM, 0);
125*6777b538SAndroid Build Coastguard Worker if (s != -1) {
126*6777b538SAndroid Build Coastguard Worker close (s);
127*6777b538SAndroid Build Coastguard Worker return (1);
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker return (0);
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker #endif
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker /**
134*6777b538SAndroid Build Coastguard Worker * xmlFTPErrMemory:
135*6777b538SAndroid Build Coastguard Worker * @extra: extra information
136*6777b538SAndroid Build Coastguard Worker *
137*6777b538SAndroid Build Coastguard Worker * Handle an out of memory condition
138*6777b538SAndroid Build Coastguard Worker */
139*6777b538SAndroid Build Coastguard Worker static void
xmlFTPErrMemory(const char * extra ATTRIBUTE_UNUSED)140*6777b538SAndroid Build Coastguard Worker xmlFTPErrMemory(const char *extra ATTRIBUTE_UNUSED)
141*6777b538SAndroid Build Coastguard Worker {
142*6777b538SAndroid Build Coastguard Worker xmlRaiseMemoryError(NULL, NULL, NULL, XML_FROM_FTP, NULL);
143*6777b538SAndroid Build Coastguard Worker }
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker /**
146*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPInit:
147*6777b538SAndroid Build Coastguard Worker *
148*6777b538SAndroid Build Coastguard Worker * Initialize the FTP protocol layer.
149*6777b538SAndroid Build Coastguard Worker * Currently it just checks for proxy information,
150*6777b538SAndroid Build Coastguard Worker * and get the hostname
151*6777b538SAndroid Build Coastguard Worker */
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker void
xmlNanoFTPInit(void)154*6777b538SAndroid Build Coastguard Worker xmlNanoFTPInit(void) {
155*6777b538SAndroid Build Coastguard Worker const char *env;
156*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
157*6777b538SAndroid Build Coastguard Worker WSADATA wsaData;
158*6777b538SAndroid Build Coastguard Worker #endif
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker if (initialized)
161*6777b538SAndroid Build Coastguard Worker return;
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
164*6777b538SAndroid Build Coastguard Worker if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
165*6777b538SAndroid Build Coastguard Worker return;
166*6777b538SAndroid Build Coastguard Worker #endif
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker proxyPort = 21;
169*6777b538SAndroid Build Coastguard Worker env = getenv("no_proxy");
170*6777b538SAndroid Build Coastguard Worker if (env && ((env[0] == '*' ) && (env[1] == 0)))
171*6777b538SAndroid Build Coastguard Worker return;
172*6777b538SAndroid Build Coastguard Worker env = getenv("ftp_proxy");
173*6777b538SAndroid Build Coastguard Worker if (env != NULL) {
174*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanProxy(env);
175*6777b538SAndroid Build Coastguard Worker } else {
176*6777b538SAndroid Build Coastguard Worker env = getenv("FTP_PROXY");
177*6777b538SAndroid Build Coastguard Worker if (env != NULL) {
178*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanProxy(env);
179*6777b538SAndroid Build Coastguard Worker }
180*6777b538SAndroid Build Coastguard Worker }
181*6777b538SAndroid Build Coastguard Worker env = getenv("ftp_proxy_user");
182*6777b538SAndroid Build Coastguard Worker if (env != NULL) {
183*6777b538SAndroid Build Coastguard Worker proxyUser = xmlMemStrdup(env);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker env = getenv("ftp_proxy_password");
186*6777b538SAndroid Build Coastguard Worker if (env != NULL) {
187*6777b538SAndroid Build Coastguard Worker proxyPasswd = xmlMemStrdup(env);
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker initialized = 1;
190*6777b538SAndroid Build Coastguard Worker }
191*6777b538SAndroid Build Coastguard Worker
192*6777b538SAndroid Build Coastguard Worker /**
193*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPCleanup:
194*6777b538SAndroid Build Coastguard Worker *
195*6777b538SAndroid Build Coastguard Worker * Cleanup the FTP protocol layer. This cleanup proxy information.
196*6777b538SAndroid Build Coastguard Worker */
197*6777b538SAndroid Build Coastguard Worker
198*6777b538SAndroid Build Coastguard Worker void
xmlNanoFTPCleanup(void)199*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCleanup(void) {
200*6777b538SAndroid Build Coastguard Worker if (proxy != NULL) {
201*6777b538SAndroid Build Coastguard Worker xmlFree(proxy);
202*6777b538SAndroid Build Coastguard Worker proxy = NULL;
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker if (proxyUser != NULL) {
205*6777b538SAndroid Build Coastguard Worker xmlFree(proxyUser);
206*6777b538SAndroid Build Coastguard Worker proxyUser = NULL;
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker if (proxyPasswd != NULL) {
209*6777b538SAndroid Build Coastguard Worker xmlFree(proxyPasswd);
210*6777b538SAndroid Build Coastguard Worker proxyPasswd = NULL;
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker #ifdef _WINSOCKAPI_
213*6777b538SAndroid Build Coastguard Worker if (initialized)
214*6777b538SAndroid Build Coastguard Worker WSACleanup();
215*6777b538SAndroid Build Coastguard Worker #endif
216*6777b538SAndroid Build Coastguard Worker initialized = 0;
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker
219*6777b538SAndroid Build Coastguard Worker /**
220*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPProxy:
221*6777b538SAndroid Build Coastguard Worker * @host: the proxy host name
222*6777b538SAndroid Build Coastguard Worker * @port: the proxy port
223*6777b538SAndroid Build Coastguard Worker * @user: the proxy user name
224*6777b538SAndroid Build Coastguard Worker * @passwd: the proxy password
225*6777b538SAndroid Build Coastguard Worker * @type: the type of proxy 1 for using SITE, 2 for USER a@b
226*6777b538SAndroid Build Coastguard Worker *
227*6777b538SAndroid Build Coastguard Worker * Setup the FTP proxy information.
228*6777b538SAndroid Build Coastguard Worker * This can also be done by using ftp_proxy ftp_proxy_user and
229*6777b538SAndroid Build Coastguard Worker * ftp_proxy_password environment variables.
230*6777b538SAndroid Build Coastguard Worker */
231*6777b538SAndroid Build Coastguard Worker
232*6777b538SAndroid Build Coastguard Worker void
xmlNanoFTPProxy(const char * host,int port,const char * user,const char * passwd,int type)233*6777b538SAndroid Build Coastguard Worker xmlNanoFTPProxy(const char *host, int port, const char *user,
234*6777b538SAndroid Build Coastguard Worker const char *passwd, int type) {
235*6777b538SAndroid Build Coastguard Worker if (proxy != NULL) {
236*6777b538SAndroid Build Coastguard Worker xmlFree(proxy);
237*6777b538SAndroid Build Coastguard Worker proxy = NULL;
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker if (proxyUser != NULL) {
240*6777b538SAndroid Build Coastguard Worker xmlFree(proxyUser);
241*6777b538SAndroid Build Coastguard Worker proxyUser = NULL;
242*6777b538SAndroid Build Coastguard Worker }
243*6777b538SAndroid Build Coastguard Worker if (proxyPasswd != NULL) {
244*6777b538SAndroid Build Coastguard Worker xmlFree(proxyPasswd);
245*6777b538SAndroid Build Coastguard Worker proxyPasswd = NULL;
246*6777b538SAndroid Build Coastguard Worker }
247*6777b538SAndroid Build Coastguard Worker if (host)
248*6777b538SAndroid Build Coastguard Worker proxy = xmlMemStrdup(host);
249*6777b538SAndroid Build Coastguard Worker if (user)
250*6777b538SAndroid Build Coastguard Worker proxyUser = xmlMemStrdup(user);
251*6777b538SAndroid Build Coastguard Worker if (passwd)
252*6777b538SAndroid Build Coastguard Worker proxyPasswd = xmlMemStrdup(passwd);
253*6777b538SAndroid Build Coastguard Worker proxyPort = port;
254*6777b538SAndroid Build Coastguard Worker proxyType = type;
255*6777b538SAndroid Build Coastguard Worker }
256*6777b538SAndroid Build Coastguard Worker
257*6777b538SAndroid Build Coastguard Worker /**
258*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPScanURL:
259*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
260*6777b538SAndroid Build Coastguard Worker * @URL: The URL used to initialize the context
261*6777b538SAndroid Build Coastguard Worker *
262*6777b538SAndroid Build Coastguard Worker * (Re)Initialize an FTP context by parsing the URL and finding
263*6777b538SAndroid Build Coastguard Worker * the protocol host port and path it indicates.
264*6777b538SAndroid Build Coastguard Worker */
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Worker static void
xmlNanoFTPScanURL(void * ctx,const char * URL)267*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanURL(void *ctx, const char *URL) {
268*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
269*6777b538SAndroid Build Coastguard Worker xmlURIPtr uri;
270*6777b538SAndroid Build Coastguard Worker
271*6777b538SAndroid Build Coastguard Worker /*
272*6777b538SAndroid Build Coastguard Worker * Clear any existing data from the context
273*6777b538SAndroid Build Coastguard Worker */
274*6777b538SAndroid Build Coastguard Worker if (ctxt->protocol != NULL) {
275*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->protocol);
276*6777b538SAndroid Build Coastguard Worker ctxt->protocol = NULL;
277*6777b538SAndroid Build Coastguard Worker }
278*6777b538SAndroid Build Coastguard Worker if (ctxt->hostname != NULL) {
279*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->hostname);
280*6777b538SAndroid Build Coastguard Worker ctxt->hostname = NULL;
281*6777b538SAndroid Build Coastguard Worker }
282*6777b538SAndroid Build Coastguard Worker if (ctxt->path != NULL) {
283*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->path);
284*6777b538SAndroid Build Coastguard Worker ctxt->path = NULL;
285*6777b538SAndroid Build Coastguard Worker }
286*6777b538SAndroid Build Coastguard Worker if (URL == NULL) return;
287*6777b538SAndroid Build Coastguard Worker
288*6777b538SAndroid Build Coastguard Worker uri = xmlParseURIRaw(URL, 1);
289*6777b538SAndroid Build Coastguard Worker if (uri == NULL)
290*6777b538SAndroid Build Coastguard Worker return;
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Worker if ((uri->scheme == NULL) || (uri->server == NULL)) {
293*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
294*6777b538SAndroid Build Coastguard Worker return;
295*6777b538SAndroid Build Coastguard Worker }
296*6777b538SAndroid Build Coastguard Worker
297*6777b538SAndroid Build Coastguard Worker ctxt->protocol = xmlMemStrdup(uri->scheme);
298*6777b538SAndroid Build Coastguard Worker ctxt->hostname = xmlMemStrdup(uri->server);
299*6777b538SAndroid Build Coastguard Worker if (uri->path != NULL)
300*6777b538SAndroid Build Coastguard Worker ctxt->path = xmlMemStrdup(uri->path);
301*6777b538SAndroid Build Coastguard Worker else
302*6777b538SAndroid Build Coastguard Worker ctxt->path = xmlMemStrdup("/");
303*6777b538SAndroid Build Coastguard Worker if (uri->port != 0)
304*6777b538SAndroid Build Coastguard Worker ctxt->port = uri->port;
305*6777b538SAndroid Build Coastguard Worker
306*6777b538SAndroid Build Coastguard Worker if (uri->user != NULL) {
307*6777b538SAndroid Build Coastguard Worker char *cptr;
308*6777b538SAndroid Build Coastguard Worker if ((cptr=strchr(uri->user, ':')) == NULL)
309*6777b538SAndroid Build Coastguard Worker ctxt->user = xmlMemStrdup(uri->user);
310*6777b538SAndroid Build Coastguard Worker else {
311*6777b538SAndroid Build Coastguard Worker ctxt->user = (char *)xmlStrndup((xmlChar *)uri->user,
312*6777b538SAndroid Build Coastguard Worker (cptr - uri->user));
313*6777b538SAndroid Build Coastguard Worker ctxt->passwd = xmlMemStrdup(cptr+1);
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker }
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
318*6777b538SAndroid Build Coastguard Worker
319*6777b538SAndroid Build Coastguard Worker }
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker /**
322*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPUpdateURL:
323*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
324*6777b538SAndroid Build Coastguard Worker * @URL: The URL used to update the context
325*6777b538SAndroid Build Coastguard Worker *
326*6777b538SAndroid Build Coastguard Worker * Update an FTP context by parsing the URL and finding
327*6777b538SAndroid Build Coastguard Worker * new path it indicates. If there is an error in the
328*6777b538SAndroid Build Coastguard Worker * protocol, hostname, port or other information, the
329*6777b538SAndroid Build Coastguard Worker * error is raised. It indicates a new connection has to
330*6777b538SAndroid Build Coastguard Worker * be established.
331*6777b538SAndroid Build Coastguard Worker *
332*6777b538SAndroid Build Coastguard Worker * Returns 0 if Ok, -1 in case of error (other host).
333*6777b538SAndroid Build Coastguard Worker */
334*6777b538SAndroid Build Coastguard Worker
335*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPUpdateURL(void * ctx,const char * URL)336*6777b538SAndroid Build Coastguard Worker xmlNanoFTPUpdateURL(void *ctx, const char *URL) {
337*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
338*6777b538SAndroid Build Coastguard Worker xmlURIPtr uri;
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker if (URL == NULL)
341*6777b538SAndroid Build Coastguard Worker return(-1);
342*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
343*6777b538SAndroid Build Coastguard Worker return(-1);
344*6777b538SAndroid Build Coastguard Worker if (ctxt->protocol == NULL)
345*6777b538SAndroid Build Coastguard Worker return(-1);
346*6777b538SAndroid Build Coastguard Worker if (ctxt->hostname == NULL)
347*6777b538SAndroid Build Coastguard Worker return(-1);
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker uri = xmlParseURIRaw(URL, 1);
350*6777b538SAndroid Build Coastguard Worker if (uri == NULL)
351*6777b538SAndroid Build Coastguard Worker return(-1);
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker if ((uri->scheme == NULL) || (uri->server == NULL)) {
354*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
355*6777b538SAndroid Build Coastguard Worker return(-1);
356*6777b538SAndroid Build Coastguard Worker }
357*6777b538SAndroid Build Coastguard Worker if ((strcmp(ctxt->protocol, uri->scheme)) ||
358*6777b538SAndroid Build Coastguard Worker (strcmp(ctxt->hostname, uri->server)) ||
359*6777b538SAndroid Build Coastguard Worker ((uri->port != 0) && (ctxt->port != uri->port))) {
360*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
361*6777b538SAndroid Build Coastguard Worker return(-1);
362*6777b538SAndroid Build Coastguard Worker }
363*6777b538SAndroid Build Coastguard Worker
364*6777b538SAndroid Build Coastguard Worker if (uri->port != 0)
365*6777b538SAndroid Build Coastguard Worker ctxt->port = uri->port;
366*6777b538SAndroid Build Coastguard Worker
367*6777b538SAndroid Build Coastguard Worker if (ctxt->path != NULL) {
368*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->path);
369*6777b538SAndroid Build Coastguard Worker ctxt->path = NULL;
370*6777b538SAndroid Build Coastguard Worker }
371*6777b538SAndroid Build Coastguard Worker
372*6777b538SAndroid Build Coastguard Worker if (uri->path == NULL)
373*6777b538SAndroid Build Coastguard Worker ctxt->path = xmlMemStrdup("/");
374*6777b538SAndroid Build Coastguard Worker else
375*6777b538SAndroid Build Coastguard Worker ctxt->path = xmlMemStrdup(uri->path);
376*6777b538SAndroid Build Coastguard Worker
377*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
378*6777b538SAndroid Build Coastguard Worker
379*6777b538SAndroid Build Coastguard Worker return(0);
380*6777b538SAndroid Build Coastguard Worker }
381*6777b538SAndroid Build Coastguard Worker
382*6777b538SAndroid Build Coastguard Worker /**
383*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPScanProxy:
384*6777b538SAndroid Build Coastguard Worker * @URL: The proxy URL used to initialize the proxy context
385*6777b538SAndroid Build Coastguard Worker *
386*6777b538SAndroid Build Coastguard Worker * (Re)Initialize the FTP Proxy context by parsing the URL and finding
387*6777b538SAndroid Build Coastguard Worker * the protocol host port it indicates.
388*6777b538SAndroid Build Coastguard Worker * Should be like ftp://myproxy/ or ftp://myproxy:3128/
389*6777b538SAndroid Build Coastguard Worker * A NULL URL cleans up proxy information.
390*6777b538SAndroid Build Coastguard Worker */
391*6777b538SAndroid Build Coastguard Worker
392*6777b538SAndroid Build Coastguard Worker void
xmlNanoFTPScanProxy(const char * URL)393*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanProxy(const char *URL) {
394*6777b538SAndroid Build Coastguard Worker xmlURIPtr uri;
395*6777b538SAndroid Build Coastguard Worker
396*6777b538SAndroid Build Coastguard Worker if (proxy != NULL) {
397*6777b538SAndroid Build Coastguard Worker xmlFree(proxy);
398*6777b538SAndroid Build Coastguard Worker proxy = NULL;
399*6777b538SAndroid Build Coastguard Worker }
400*6777b538SAndroid Build Coastguard Worker proxyPort = 0;
401*6777b538SAndroid Build Coastguard Worker
402*6777b538SAndroid Build Coastguard Worker if (URL == NULL) return;
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker uri = xmlParseURIRaw(URL, 1);
405*6777b538SAndroid Build Coastguard Worker if ((uri == NULL) || (uri->scheme == NULL) ||
406*6777b538SAndroid Build Coastguard Worker (strcmp(uri->scheme, "ftp")) || (uri->server == NULL)) {
407*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, XML_FTP_URL_SYNTAX, "Syntax Error\n");
408*6777b538SAndroid Build Coastguard Worker if (uri != NULL)
409*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
410*6777b538SAndroid Build Coastguard Worker return;
411*6777b538SAndroid Build Coastguard Worker }
412*6777b538SAndroid Build Coastguard Worker
413*6777b538SAndroid Build Coastguard Worker proxy = xmlMemStrdup(uri->server);
414*6777b538SAndroid Build Coastguard Worker if (uri->port != 0)
415*6777b538SAndroid Build Coastguard Worker proxyPort = uri->port;
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker xmlFreeURI(uri);
418*6777b538SAndroid Build Coastguard Worker }
419*6777b538SAndroid Build Coastguard Worker
420*6777b538SAndroid Build Coastguard Worker /**
421*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPNewCtxt:
422*6777b538SAndroid Build Coastguard Worker * @URL: The URL used to initialize the context
423*6777b538SAndroid Build Coastguard Worker *
424*6777b538SAndroid Build Coastguard Worker * Allocate and initialize a new FTP context.
425*6777b538SAndroid Build Coastguard Worker *
426*6777b538SAndroid Build Coastguard Worker * Returns an FTP context or NULL in case of error.
427*6777b538SAndroid Build Coastguard Worker */
428*6777b538SAndroid Build Coastguard Worker
429*6777b538SAndroid Build Coastguard Worker void*
xmlNanoFTPNewCtxt(const char * URL)430*6777b538SAndroid Build Coastguard Worker xmlNanoFTPNewCtxt(const char *URL) {
431*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ret;
432*6777b538SAndroid Build Coastguard Worker char *unescaped;
433*6777b538SAndroid Build Coastguard Worker
434*6777b538SAndroid Build Coastguard Worker ret = (xmlNanoFTPCtxtPtr) xmlMalloc(sizeof(xmlNanoFTPCtxt));
435*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
436*6777b538SAndroid Build Coastguard Worker xmlFTPErrMemory("allocating FTP context");
437*6777b538SAndroid Build Coastguard Worker return(NULL);
438*6777b538SAndroid Build Coastguard Worker }
439*6777b538SAndroid Build Coastguard Worker
440*6777b538SAndroid Build Coastguard Worker memset(ret, 0, sizeof(xmlNanoFTPCtxt));
441*6777b538SAndroid Build Coastguard Worker ret->port = 21;
442*6777b538SAndroid Build Coastguard Worker ret->passive = 1;
443*6777b538SAndroid Build Coastguard Worker ret->returnValue = 0;
444*6777b538SAndroid Build Coastguard Worker ret->controlBufIndex = 0;
445*6777b538SAndroid Build Coastguard Worker ret->controlBufUsed = 0;
446*6777b538SAndroid Build Coastguard Worker ret->controlFd = INVALID_SOCKET;
447*6777b538SAndroid Build Coastguard Worker
448*6777b538SAndroid Build Coastguard Worker unescaped = xmlURIUnescapeString(URL, 0, NULL);
449*6777b538SAndroid Build Coastguard Worker if (unescaped != NULL) {
450*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanURL(ret, unescaped);
451*6777b538SAndroid Build Coastguard Worker xmlFree(unescaped);
452*6777b538SAndroid Build Coastguard Worker } else if (URL != NULL)
453*6777b538SAndroid Build Coastguard Worker xmlNanoFTPScanURL(ret, URL);
454*6777b538SAndroid Build Coastguard Worker
455*6777b538SAndroid Build Coastguard Worker return(ret);
456*6777b538SAndroid Build Coastguard Worker }
457*6777b538SAndroid Build Coastguard Worker
458*6777b538SAndroid Build Coastguard Worker /**
459*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPFreeCtxt:
460*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
461*6777b538SAndroid Build Coastguard Worker *
462*6777b538SAndroid Build Coastguard Worker * Frees the context after closing the connection.
463*6777b538SAndroid Build Coastguard Worker */
464*6777b538SAndroid Build Coastguard Worker
465*6777b538SAndroid Build Coastguard Worker void
xmlNanoFTPFreeCtxt(void * ctx)466*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(void * ctx) {
467*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
468*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
469*6777b538SAndroid Build Coastguard Worker if (ctxt->hostname != NULL) xmlFree(ctxt->hostname);
470*6777b538SAndroid Build Coastguard Worker if (ctxt->protocol != NULL) xmlFree(ctxt->protocol);
471*6777b538SAndroid Build Coastguard Worker if (ctxt->path != NULL) xmlFree(ctxt->path);
472*6777b538SAndroid Build Coastguard Worker if (ctxt->user != NULL) xmlFree(ctxt->user);
473*6777b538SAndroid Build Coastguard Worker if (ctxt->passwd != NULL) xmlFree(ctxt->passwd);
474*6777b538SAndroid Build Coastguard Worker ctxt->passive = 1;
475*6777b538SAndroid Build Coastguard Worker if (ctxt->controlFd != INVALID_SOCKET) closesocket(ctxt->controlFd);
476*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
477*6777b538SAndroid Build Coastguard Worker ctxt->controlBufIndex = -1;
478*6777b538SAndroid Build Coastguard Worker ctxt->controlBufUsed = -1;
479*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt);
480*6777b538SAndroid Build Coastguard Worker }
481*6777b538SAndroid Build Coastguard Worker
482*6777b538SAndroid Build Coastguard Worker /**
483*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPParseResponse:
484*6777b538SAndroid Build Coastguard Worker * @buf: the buffer containing the response
485*6777b538SAndroid Build Coastguard Worker * @len: the buffer length
486*6777b538SAndroid Build Coastguard Worker *
487*6777b538SAndroid Build Coastguard Worker * Parsing of the server answer, we just extract the code.
488*6777b538SAndroid Build Coastguard Worker *
489*6777b538SAndroid Build Coastguard Worker * returns 0 for errors
490*6777b538SAndroid Build Coastguard Worker * +XXX for last line of response
491*6777b538SAndroid Build Coastguard Worker * -XXX for response to be continued
492*6777b538SAndroid Build Coastguard Worker */
493*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPParseResponse(char * buf,int len)494*6777b538SAndroid Build Coastguard Worker xmlNanoFTPParseResponse(char *buf, int len) {
495*6777b538SAndroid Build Coastguard Worker int val = 0;
496*6777b538SAndroid Build Coastguard Worker
497*6777b538SAndroid Build Coastguard Worker if (len < 3) return(-1);
498*6777b538SAndroid Build Coastguard Worker if ((*buf >= '0') && (*buf <= '9'))
499*6777b538SAndroid Build Coastguard Worker val = val * 10 + (*buf - '0');
500*6777b538SAndroid Build Coastguard Worker else
501*6777b538SAndroid Build Coastguard Worker return(0);
502*6777b538SAndroid Build Coastguard Worker buf++;
503*6777b538SAndroid Build Coastguard Worker if ((*buf >= '0') && (*buf <= '9'))
504*6777b538SAndroid Build Coastguard Worker val = val * 10 + (*buf - '0');
505*6777b538SAndroid Build Coastguard Worker else
506*6777b538SAndroid Build Coastguard Worker return(0);
507*6777b538SAndroid Build Coastguard Worker buf++;
508*6777b538SAndroid Build Coastguard Worker if ((*buf >= '0') && (*buf <= '9'))
509*6777b538SAndroid Build Coastguard Worker val = val * 10 + (*buf - '0');
510*6777b538SAndroid Build Coastguard Worker else
511*6777b538SAndroid Build Coastguard Worker return(0);
512*6777b538SAndroid Build Coastguard Worker buf++;
513*6777b538SAndroid Build Coastguard Worker if (*buf == '-')
514*6777b538SAndroid Build Coastguard Worker return(-val);
515*6777b538SAndroid Build Coastguard Worker return(val);
516*6777b538SAndroid Build Coastguard Worker }
517*6777b538SAndroid Build Coastguard Worker
518*6777b538SAndroid Build Coastguard Worker /**
519*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPGetMore:
520*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
521*6777b538SAndroid Build Coastguard Worker *
522*6777b538SAndroid Build Coastguard Worker * Read more information from the FTP control connection
523*6777b538SAndroid Build Coastguard Worker * Returns the number of bytes read, < 0 indicates an error
524*6777b538SAndroid Build Coastguard Worker */
525*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPGetMore(void * ctx)526*6777b538SAndroid Build Coastguard Worker xmlNanoFTPGetMore(void *ctx) {
527*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
528*6777b538SAndroid Build Coastguard Worker int len;
529*6777b538SAndroid Build Coastguard Worker int size;
530*6777b538SAndroid Build Coastguard Worker
531*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
532*6777b538SAndroid Build Coastguard Worker
533*6777b538SAndroid Build Coastguard Worker if ((ctxt->controlBufIndex < 0) || (ctxt->controlBufIndex > FTP_BUF_SIZE)) {
534*6777b538SAndroid Build Coastguard Worker return(-1);
535*6777b538SAndroid Build Coastguard Worker }
536*6777b538SAndroid Build Coastguard Worker
537*6777b538SAndroid Build Coastguard Worker if ((ctxt->controlBufUsed < 0) || (ctxt->controlBufUsed > FTP_BUF_SIZE)) {
538*6777b538SAndroid Build Coastguard Worker return(-1);
539*6777b538SAndroid Build Coastguard Worker }
540*6777b538SAndroid Build Coastguard Worker if (ctxt->controlBufIndex > ctxt->controlBufUsed) {
541*6777b538SAndroid Build Coastguard Worker return(-1);
542*6777b538SAndroid Build Coastguard Worker }
543*6777b538SAndroid Build Coastguard Worker
544*6777b538SAndroid Build Coastguard Worker /*
545*6777b538SAndroid Build Coastguard Worker * First pack the control buffer
546*6777b538SAndroid Build Coastguard Worker */
547*6777b538SAndroid Build Coastguard Worker if (ctxt->controlBufIndex > 0) {
548*6777b538SAndroid Build Coastguard Worker memmove(&ctxt->controlBuf[0], &ctxt->controlBuf[ctxt->controlBufIndex],
549*6777b538SAndroid Build Coastguard Worker ctxt->controlBufUsed - ctxt->controlBufIndex);
550*6777b538SAndroid Build Coastguard Worker ctxt->controlBufUsed -= ctxt->controlBufIndex;
551*6777b538SAndroid Build Coastguard Worker ctxt->controlBufIndex = 0;
552*6777b538SAndroid Build Coastguard Worker }
553*6777b538SAndroid Build Coastguard Worker size = FTP_BUF_SIZE - ctxt->controlBufUsed;
554*6777b538SAndroid Build Coastguard Worker if (size == 0) {
555*6777b538SAndroid Build Coastguard Worker return(0);
556*6777b538SAndroid Build Coastguard Worker }
557*6777b538SAndroid Build Coastguard Worker
558*6777b538SAndroid Build Coastguard Worker /*
559*6777b538SAndroid Build Coastguard Worker * Read the amount left on the control connection
560*6777b538SAndroid Build Coastguard Worker */
561*6777b538SAndroid Build Coastguard Worker if ((len = recv(ctxt->controlFd, &ctxt->controlBuf[ctxt->controlBufIndex],
562*6777b538SAndroid Build Coastguard Worker size, 0)) < 0) {
563*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
564*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
565*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
566*6777b538SAndroid Build Coastguard Worker return(-1);
567*6777b538SAndroid Build Coastguard Worker }
568*6777b538SAndroid Build Coastguard Worker ctxt->controlBufUsed += len;
569*6777b538SAndroid Build Coastguard Worker ctxt->controlBuf[ctxt->controlBufUsed] = 0;
570*6777b538SAndroid Build Coastguard Worker
571*6777b538SAndroid Build Coastguard Worker return(len);
572*6777b538SAndroid Build Coastguard Worker }
573*6777b538SAndroid Build Coastguard Worker
574*6777b538SAndroid Build Coastguard Worker /**
575*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPReadResponse:
576*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
577*6777b538SAndroid Build Coastguard Worker *
578*6777b538SAndroid Build Coastguard Worker * Read the response from the FTP server after a command.
579*6777b538SAndroid Build Coastguard Worker * Returns the code number
580*6777b538SAndroid Build Coastguard Worker */
581*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPReadResponse(void * ctx)582*6777b538SAndroid Build Coastguard Worker xmlNanoFTPReadResponse(void *ctx) {
583*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
584*6777b538SAndroid Build Coastguard Worker char *ptr, *end;
585*6777b538SAndroid Build Coastguard Worker int len;
586*6777b538SAndroid Build Coastguard Worker int res = -1, cur = -1;
587*6777b538SAndroid Build Coastguard Worker
588*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
589*6777b538SAndroid Build Coastguard Worker
590*6777b538SAndroid Build Coastguard Worker get_more:
591*6777b538SAndroid Build Coastguard Worker /*
592*6777b538SAndroid Build Coastguard Worker * Assumes everything up to controlBuf[controlBufIndex] has been read
593*6777b538SAndroid Build Coastguard Worker * and analyzed.
594*6777b538SAndroid Build Coastguard Worker */
595*6777b538SAndroid Build Coastguard Worker len = xmlNanoFTPGetMore(ctx);
596*6777b538SAndroid Build Coastguard Worker if (len < 0) {
597*6777b538SAndroid Build Coastguard Worker return(-1);
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker if ((ctxt->controlBufUsed == 0) && (len == 0)) {
600*6777b538SAndroid Build Coastguard Worker return(-1);
601*6777b538SAndroid Build Coastguard Worker }
602*6777b538SAndroid Build Coastguard Worker ptr = &ctxt->controlBuf[ctxt->controlBufIndex];
603*6777b538SAndroid Build Coastguard Worker end = &ctxt->controlBuf[ctxt->controlBufUsed];
604*6777b538SAndroid Build Coastguard Worker
605*6777b538SAndroid Build Coastguard Worker while (ptr < end) {
606*6777b538SAndroid Build Coastguard Worker cur = xmlNanoFTPParseResponse(ptr, end - ptr);
607*6777b538SAndroid Build Coastguard Worker if (cur > 0) {
608*6777b538SAndroid Build Coastguard Worker /*
609*6777b538SAndroid Build Coastguard Worker * Successfully scanned the control code, scratch
610*6777b538SAndroid Build Coastguard Worker * till the end of the line, but keep the index to be
611*6777b538SAndroid Build Coastguard Worker * able to analyze the result if needed.
612*6777b538SAndroid Build Coastguard Worker */
613*6777b538SAndroid Build Coastguard Worker res = cur;
614*6777b538SAndroid Build Coastguard Worker ptr += 3;
615*6777b538SAndroid Build Coastguard Worker ctxt->controlBufAnswer = ptr - ctxt->controlBuf;
616*6777b538SAndroid Build Coastguard Worker while ((ptr < end) && (*ptr != '\n')) ptr++;
617*6777b538SAndroid Build Coastguard Worker if (*ptr == '\n') ptr++;
618*6777b538SAndroid Build Coastguard Worker if (*ptr == '\r') ptr++;
619*6777b538SAndroid Build Coastguard Worker break;
620*6777b538SAndroid Build Coastguard Worker }
621*6777b538SAndroid Build Coastguard Worker while ((ptr < end) && (*ptr != '\n')) ptr++;
622*6777b538SAndroid Build Coastguard Worker if (ptr >= end) {
623*6777b538SAndroid Build Coastguard Worker ctxt->controlBufIndex = ctxt->controlBufUsed;
624*6777b538SAndroid Build Coastguard Worker goto get_more;
625*6777b538SAndroid Build Coastguard Worker }
626*6777b538SAndroid Build Coastguard Worker if (*ptr != '\r') ptr++;
627*6777b538SAndroid Build Coastguard Worker }
628*6777b538SAndroid Build Coastguard Worker
629*6777b538SAndroid Build Coastguard Worker if (res < 0) goto get_more;
630*6777b538SAndroid Build Coastguard Worker ctxt->controlBufIndex = ptr - ctxt->controlBuf;
631*6777b538SAndroid Build Coastguard Worker
632*6777b538SAndroid Build Coastguard Worker return(res / 100);
633*6777b538SAndroid Build Coastguard Worker }
634*6777b538SAndroid Build Coastguard Worker
635*6777b538SAndroid Build Coastguard Worker /**
636*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPGetResponse:
637*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
638*6777b538SAndroid Build Coastguard Worker *
639*6777b538SAndroid Build Coastguard Worker * Get the response from the FTP server after a command.
640*6777b538SAndroid Build Coastguard Worker * Returns the code number
641*6777b538SAndroid Build Coastguard Worker */
642*6777b538SAndroid Build Coastguard Worker
643*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPGetResponse(void * ctx)644*6777b538SAndroid Build Coastguard Worker xmlNanoFTPGetResponse(void *ctx) {
645*6777b538SAndroid Build Coastguard Worker int res;
646*6777b538SAndroid Build Coastguard Worker
647*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPReadResponse(ctx);
648*6777b538SAndroid Build Coastguard Worker
649*6777b538SAndroid Build Coastguard Worker return(res);
650*6777b538SAndroid Build Coastguard Worker }
651*6777b538SAndroid Build Coastguard Worker
652*6777b538SAndroid Build Coastguard Worker /**
653*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPCheckResponse:
654*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
655*6777b538SAndroid Build Coastguard Worker *
656*6777b538SAndroid Build Coastguard Worker * Check if there is a response from the FTP server after a command.
657*6777b538SAndroid Build Coastguard Worker * Returns the code number, or 0
658*6777b538SAndroid Build Coastguard Worker */
659*6777b538SAndroid Build Coastguard Worker
660*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPCheckResponse(void * ctx)661*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCheckResponse(void *ctx) {
662*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
663*6777b538SAndroid Build Coastguard Worker fd_set rfd;
664*6777b538SAndroid Build Coastguard Worker struct timeval tv;
665*6777b538SAndroid Build Coastguard Worker
666*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
667*6777b538SAndroid Build Coastguard Worker tv.tv_sec = 0;
668*6777b538SAndroid Build Coastguard Worker tv.tv_usec = 0;
669*6777b538SAndroid Build Coastguard Worker FD_ZERO(&rfd);
670*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->controlFd, &rfd);
671*6777b538SAndroid Build Coastguard Worker switch(select(ctxt->controlFd + 1, &rfd, NULL, NULL, &tv)) {
672*6777b538SAndroid Build Coastguard Worker case 0:
673*6777b538SAndroid Build Coastguard Worker return(0);
674*6777b538SAndroid Build Coastguard Worker case -1:
675*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "select");
676*6777b538SAndroid Build Coastguard Worker return(-1);
677*6777b538SAndroid Build Coastguard Worker
678*6777b538SAndroid Build Coastguard Worker }
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker return(xmlNanoFTPReadResponse(ctx));
681*6777b538SAndroid Build Coastguard Worker }
682*6777b538SAndroid Build Coastguard Worker
683*6777b538SAndroid Build Coastguard Worker /**
684*6777b538SAndroid Build Coastguard Worker * Send the user authentication
685*6777b538SAndroid Build Coastguard Worker */
686*6777b538SAndroid Build Coastguard Worker
687*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPSendUser(void * ctx)688*6777b538SAndroid Build Coastguard Worker xmlNanoFTPSendUser(void *ctx) {
689*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
690*6777b538SAndroid Build Coastguard Worker char buf[200];
691*6777b538SAndroid Build Coastguard Worker int len;
692*6777b538SAndroid Build Coastguard Worker int res;
693*6777b538SAndroid Build Coastguard Worker
694*6777b538SAndroid Build Coastguard Worker if (ctxt->user == NULL)
695*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "USER anonymous\r\n");
696*6777b538SAndroid Build Coastguard Worker else
697*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "USER %s\r\n", ctxt->user);
698*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
699*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
700*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
701*6777b538SAndroid Build Coastguard Worker if (res < 0) {
702*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
703*6777b538SAndroid Build Coastguard Worker return(res);
704*6777b538SAndroid Build Coastguard Worker }
705*6777b538SAndroid Build Coastguard Worker return(0);
706*6777b538SAndroid Build Coastguard Worker }
707*6777b538SAndroid Build Coastguard Worker
708*6777b538SAndroid Build Coastguard Worker /**
709*6777b538SAndroid Build Coastguard Worker * Send the password authentication
710*6777b538SAndroid Build Coastguard Worker */
711*6777b538SAndroid Build Coastguard Worker
712*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPSendPasswd(void * ctx)713*6777b538SAndroid Build Coastguard Worker xmlNanoFTPSendPasswd(void *ctx) {
714*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
715*6777b538SAndroid Build Coastguard Worker char buf[200];
716*6777b538SAndroid Build Coastguard Worker int len;
717*6777b538SAndroid Build Coastguard Worker int res;
718*6777b538SAndroid Build Coastguard Worker
719*6777b538SAndroid Build Coastguard Worker if (ctxt->passwd == NULL)
720*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
721*6777b538SAndroid Build Coastguard Worker else
722*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
723*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
724*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
725*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
726*6777b538SAndroid Build Coastguard Worker if (res < 0) {
727*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
728*6777b538SAndroid Build Coastguard Worker return(res);
729*6777b538SAndroid Build Coastguard Worker }
730*6777b538SAndroid Build Coastguard Worker return(0);
731*6777b538SAndroid Build Coastguard Worker }
732*6777b538SAndroid Build Coastguard Worker
733*6777b538SAndroid Build Coastguard Worker /**
734*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPQuit:
735*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
736*6777b538SAndroid Build Coastguard Worker *
737*6777b538SAndroid Build Coastguard Worker * Send a QUIT command to the server
738*6777b538SAndroid Build Coastguard Worker *
739*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
740*6777b538SAndroid Build Coastguard Worker */
741*6777b538SAndroid Build Coastguard Worker
742*6777b538SAndroid Build Coastguard Worker
743*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPQuit(void * ctx)744*6777b538SAndroid Build Coastguard Worker xmlNanoFTPQuit(void *ctx) {
745*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
746*6777b538SAndroid Build Coastguard Worker char buf[200];
747*6777b538SAndroid Build Coastguard Worker int len, res;
748*6777b538SAndroid Build Coastguard Worker
749*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
750*6777b538SAndroid Build Coastguard Worker
751*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "QUIT\r\n");
752*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
753*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
754*6777b538SAndroid Build Coastguard Worker if (res < 0) {
755*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
756*6777b538SAndroid Build Coastguard Worker return(res);
757*6777b538SAndroid Build Coastguard Worker }
758*6777b538SAndroid Build Coastguard Worker return(0);
759*6777b538SAndroid Build Coastguard Worker }
760*6777b538SAndroid Build Coastguard Worker
761*6777b538SAndroid Build Coastguard Worker /**
762*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPConnect:
763*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
764*6777b538SAndroid Build Coastguard Worker *
765*6777b538SAndroid Build Coastguard Worker * Tries to open a control connection
766*6777b538SAndroid Build Coastguard Worker *
767*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
768*6777b538SAndroid Build Coastguard Worker */
769*6777b538SAndroid Build Coastguard Worker
770*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPConnect(void * ctx)771*6777b538SAndroid Build Coastguard Worker xmlNanoFTPConnect(void *ctx) {
772*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
773*6777b538SAndroid Build Coastguard Worker struct hostent *hp;
774*6777b538SAndroid Build Coastguard Worker int port;
775*6777b538SAndroid Build Coastguard Worker int res;
776*6777b538SAndroid Build Coastguard Worker int addrlen = sizeof (struct sockaddr_in);
777*6777b538SAndroid Build Coastguard Worker
778*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
779*6777b538SAndroid Build Coastguard Worker return(-1);
780*6777b538SAndroid Build Coastguard Worker if (ctxt->hostname == NULL)
781*6777b538SAndroid Build Coastguard Worker return(-1);
782*6777b538SAndroid Build Coastguard Worker
783*6777b538SAndroid Build Coastguard Worker /*
784*6777b538SAndroid Build Coastguard Worker * do the blocking DNS query.
785*6777b538SAndroid Build Coastguard Worker */
786*6777b538SAndroid Build Coastguard Worker if (proxy) {
787*6777b538SAndroid Build Coastguard Worker port = proxyPort;
788*6777b538SAndroid Build Coastguard Worker } else {
789*6777b538SAndroid Build Coastguard Worker port = ctxt->port;
790*6777b538SAndroid Build Coastguard Worker }
791*6777b538SAndroid Build Coastguard Worker if (port == 0)
792*6777b538SAndroid Build Coastguard Worker port = 21;
793*6777b538SAndroid Build Coastguard Worker
794*6777b538SAndroid Build Coastguard Worker memset (&ctxt->ftpAddr, 0, sizeof(ctxt->ftpAddr));
795*6777b538SAndroid Build Coastguard Worker
796*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
797*6777b538SAndroid Build Coastguard Worker if (have_ipv6 ()) {
798*6777b538SAndroid Build Coastguard Worker struct addrinfo hints, *tmp, *result;
799*6777b538SAndroid Build Coastguard Worker
800*6777b538SAndroid Build Coastguard Worker result = NULL;
801*6777b538SAndroid Build Coastguard Worker memset (&hints, 0, sizeof(hints));
802*6777b538SAndroid Build Coastguard Worker hints.ai_socktype = SOCK_STREAM;
803*6777b538SAndroid Build Coastguard Worker
804*6777b538SAndroid Build Coastguard Worker if (proxy) {
805*6777b538SAndroid Build Coastguard Worker if (getaddrinfo (proxy, NULL, &hints, &result) != 0) {
806*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
807*6777b538SAndroid Build Coastguard Worker return (-1);
808*6777b538SAndroid Build Coastguard Worker }
809*6777b538SAndroid Build Coastguard Worker }
810*6777b538SAndroid Build Coastguard Worker else
811*6777b538SAndroid Build Coastguard Worker if (getaddrinfo (ctxt->hostname, NULL, &hints, &result) != 0) {
812*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
813*6777b538SAndroid Build Coastguard Worker return (-1);
814*6777b538SAndroid Build Coastguard Worker }
815*6777b538SAndroid Build Coastguard Worker
816*6777b538SAndroid Build Coastguard Worker for (tmp = result; tmp; tmp = tmp->ai_next)
817*6777b538SAndroid Build Coastguard Worker if (tmp->ai_family == AF_INET || tmp->ai_family == AF_INET6)
818*6777b538SAndroid Build Coastguard Worker break;
819*6777b538SAndroid Build Coastguard Worker
820*6777b538SAndroid Build Coastguard Worker if (!tmp) {
821*6777b538SAndroid Build Coastguard Worker if (result)
822*6777b538SAndroid Build Coastguard Worker freeaddrinfo (result);
823*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "getaddrinfo failed");
824*6777b538SAndroid Build Coastguard Worker return (-1);
825*6777b538SAndroid Build Coastguard Worker }
826*6777b538SAndroid Build Coastguard Worker if ((size_t)tmp->ai_addrlen > sizeof(ctxt->ftpAddr)) {
827*6777b538SAndroid Build Coastguard Worker if (result)
828*6777b538SAndroid Build Coastguard Worker freeaddrinfo (result);
829*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch");
830*6777b538SAndroid Build Coastguard Worker return (-1);
831*6777b538SAndroid Build Coastguard Worker }
832*6777b538SAndroid Build Coastguard Worker if (tmp->ai_family == AF_INET6) {
833*6777b538SAndroid Build Coastguard Worker memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen);
834*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in6 *) &ctxt->ftpAddr)->sin6_port = htons (port);
835*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = socket (AF_INET6, SOCK_STREAM, 0);
836*6777b538SAndroid Build Coastguard Worker }
837*6777b538SAndroid Build Coastguard Worker else {
838*6777b538SAndroid Build Coastguard Worker memcpy (&ctxt->ftpAddr, tmp->ai_addr, tmp->ai_addrlen);
839*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in *) &ctxt->ftpAddr)->sin_port = htons (port);
840*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
841*6777b538SAndroid Build Coastguard Worker }
842*6777b538SAndroid Build Coastguard Worker addrlen = tmp->ai_addrlen;
843*6777b538SAndroid Build Coastguard Worker freeaddrinfo (result);
844*6777b538SAndroid Build Coastguard Worker }
845*6777b538SAndroid Build Coastguard Worker else
846*6777b538SAndroid Build Coastguard Worker #endif
847*6777b538SAndroid Build Coastguard Worker {
848*6777b538SAndroid Build Coastguard Worker if (proxy)
849*6777b538SAndroid Build Coastguard Worker hp = gethostbyname (GETHOSTBYNAME_ARG_CAST proxy);
850*6777b538SAndroid Build Coastguard Worker else
851*6777b538SAndroid Build Coastguard Worker hp = gethostbyname (GETHOSTBYNAME_ARG_CAST ctxt->hostname);
852*6777b538SAndroid Build Coastguard Worker if (hp == NULL) {
853*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname failed");
854*6777b538SAndroid Build Coastguard Worker return (-1);
855*6777b538SAndroid Build Coastguard Worker }
856*6777b538SAndroid Build Coastguard Worker if ((unsigned int) hp->h_length >
857*6777b538SAndroid Build Coastguard Worker sizeof(((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr)) {
858*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "gethostbyname address mismatch");
859*6777b538SAndroid Build Coastguard Worker return (-1);
860*6777b538SAndroid Build Coastguard Worker }
861*6777b538SAndroid Build Coastguard Worker
862*6777b538SAndroid Build Coastguard Worker /*
863*6777b538SAndroid Build Coastguard Worker * Prepare the socket
864*6777b538SAndroid Build Coastguard Worker */
865*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_family = AF_INET;
866*6777b538SAndroid Build Coastguard Worker memcpy (&((struct sockaddr_in *)&ctxt->ftpAddr)->sin_addr,
867*6777b538SAndroid Build Coastguard Worker hp->h_addr_list[0], hp->h_length);
868*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in *)&ctxt->ftpAddr)->sin_port =
869*6777b538SAndroid Build Coastguard Worker (unsigned short)htons ((unsigned short)port);
870*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = socket (AF_INET, SOCK_STREAM, 0);
871*6777b538SAndroid Build Coastguard Worker addrlen = sizeof (struct sockaddr_in);
872*6777b538SAndroid Build Coastguard Worker }
873*6777b538SAndroid Build Coastguard Worker
874*6777b538SAndroid Build Coastguard Worker if (ctxt->controlFd == INVALID_SOCKET) {
875*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "socket failed");
876*6777b538SAndroid Build Coastguard Worker return(-1);
877*6777b538SAndroid Build Coastguard Worker }
878*6777b538SAndroid Build Coastguard Worker
879*6777b538SAndroid Build Coastguard Worker /*
880*6777b538SAndroid Build Coastguard Worker * Do the connect.
881*6777b538SAndroid Build Coastguard Worker */
882*6777b538SAndroid Build Coastguard Worker if (connect(ctxt->controlFd, (struct sockaddr *) &ctxt->ftpAddr,
883*6777b538SAndroid Build Coastguard Worker addrlen) < 0) {
884*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a connection");
885*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
886*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
887*6777b538SAndroid Build Coastguard Worker return(-1);
888*6777b538SAndroid Build Coastguard Worker }
889*6777b538SAndroid Build Coastguard Worker
890*6777b538SAndroid Build Coastguard Worker /*
891*6777b538SAndroid Build Coastguard Worker * Wait for the HELLO from the server.
892*6777b538SAndroid Build Coastguard Worker */
893*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
894*6777b538SAndroid Build Coastguard Worker if (res != 2) {
895*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
896*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
897*6777b538SAndroid Build Coastguard Worker return(-1);
898*6777b538SAndroid Build Coastguard Worker }
899*6777b538SAndroid Build Coastguard Worker
900*6777b538SAndroid Build Coastguard Worker /*
901*6777b538SAndroid Build Coastguard Worker * State diagram for the login operation on the FTP server
902*6777b538SAndroid Build Coastguard Worker *
903*6777b538SAndroid Build Coastguard Worker * Reference: RFC 959
904*6777b538SAndroid Build Coastguard Worker *
905*6777b538SAndroid Build Coastguard Worker * 1
906*6777b538SAndroid Build Coastguard Worker * +---+ USER +---+------------->+---+
907*6777b538SAndroid Build Coastguard Worker * | B |---------->| W | 2 ---->| E |
908*6777b538SAndroid Build Coastguard Worker * +---+ +---+------ | -->+---+
909*6777b538SAndroid Build Coastguard Worker * | | | | |
910*6777b538SAndroid Build Coastguard Worker * 3 | | 4,5 | | |
911*6777b538SAndroid Build Coastguard Worker * -------------- ----- | | |
912*6777b538SAndroid Build Coastguard Worker * | | | | |
913*6777b538SAndroid Build Coastguard Worker * | | | | |
914*6777b538SAndroid Build Coastguard Worker * | --------- |
915*6777b538SAndroid Build Coastguard Worker * | 1| | | |
916*6777b538SAndroid Build Coastguard Worker * V | | | |
917*6777b538SAndroid Build Coastguard Worker * +---+ PASS +---+ 2 | ------>+---+
918*6777b538SAndroid Build Coastguard Worker * | |---------->| W |------------->| S |
919*6777b538SAndroid Build Coastguard Worker * +---+ +---+ ---------->+---+
920*6777b538SAndroid Build Coastguard Worker * | | | | |
921*6777b538SAndroid Build Coastguard Worker * 3 | |4,5| | |
922*6777b538SAndroid Build Coastguard Worker * -------------- -------- |
923*6777b538SAndroid Build Coastguard Worker * | | | | |
924*6777b538SAndroid Build Coastguard Worker * | | | | |
925*6777b538SAndroid Build Coastguard Worker * | -----------
926*6777b538SAndroid Build Coastguard Worker * | 1,3| | | |
927*6777b538SAndroid Build Coastguard Worker * V | 2| | |
928*6777b538SAndroid Build Coastguard Worker * +---+ ACCT +---+-- | ----->+---+
929*6777b538SAndroid Build Coastguard Worker * | |---------->| W | 4,5 -------->| F |
930*6777b538SAndroid Build Coastguard Worker * +---+ +---+------------->+---+
931*6777b538SAndroid Build Coastguard Worker *
932*6777b538SAndroid Build Coastguard Worker * Of course in case of using a proxy this get really nasty and is not
933*6777b538SAndroid Build Coastguard Worker * standardized at all :-(
934*6777b538SAndroid Build Coastguard Worker */
935*6777b538SAndroid Build Coastguard Worker if (proxy) {
936*6777b538SAndroid Build Coastguard Worker int len;
937*6777b538SAndroid Build Coastguard Worker char buf[400];
938*6777b538SAndroid Build Coastguard Worker
939*6777b538SAndroid Build Coastguard Worker if (proxyUser != NULL) {
940*6777b538SAndroid Build Coastguard Worker /*
941*6777b538SAndroid Build Coastguard Worker * We need proxy auth
942*6777b538SAndroid Build Coastguard Worker */
943*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "USER %s\r\n", proxyUser);
944*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
945*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
946*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
947*6777b538SAndroid Build Coastguard Worker if (res < 0) {
948*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
949*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd);
950*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
951*6777b538SAndroid Build Coastguard Worker return(res);
952*6777b538SAndroid Build Coastguard Worker }
953*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
954*6777b538SAndroid Build Coastguard Worker switch (res) {
955*6777b538SAndroid Build Coastguard Worker case 2:
956*6777b538SAndroid Build Coastguard Worker if (proxyPasswd == NULL)
957*6777b538SAndroid Build Coastguard Worker break;
958*6777b538SAndroid Build Coastguard Worker /* Falls through. */
959*6777b538SAndroid Build Coastguard Worker case 3:
960*6777b538SAndroid Build Coastguard Worker if (proxyPasswd != NULL)
961*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS %s\r\n", proxyPasswd);
962*6777b538SAndroid Build Coastguard Worker else
963*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
964*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
965*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
966*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
967*6777b538SAndroid Build Coastguard Worker if (res < 0) {
968*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
969*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd);
970*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
971*6777b538SAndroid Build Coastguard Worker return(res);
972*6777b538SAndroid Build Coastguard Worker }
973*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
974*6777b538SAndroid Build Coastguard Worker if (res > 3) {
975*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd);
976*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
977*6777b538SAndroid Build Coastguard Worker return(-1);
978*6777b538SAndroid Build Coastguard Worker }
979*6777b538SAndroid Build Coastguard Worker break;
980*6777b538SAndroid Build Coastguard Worker case 1:
981*6777b538SAndroid Build Coastguard Worker break;
982*6777b538SAndroid Build Coastguard Worker case 4:
983*6777b538SAndroid Build Coastguard Worker case 5:
984*6777b538SAndroid Build Coastguard Worker case -1:
985*6777b538SAndroid Build Coastguard Worker default:
986*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd);
987*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
988*6777b538SAndroid Build Coastguard Worker return(-1);
989*6777b538SAndroid Build Coastguard Worker }
990*6777b538SAndroid Build Coastguard Worker }
991*6777b538SAndroid Build Coastguard Worker
992*6777b538SAndroid Build Coastguard Worker /*
993*6777b538SAndroid Build Coastguard Worker * We assume we don't need more authentication to the proxy
994*6777b538SAndroid Build Coastguard Worker * and that it succeeded :-\
995*6777b538SAndroid Build Coastguard Worker */
996*6777b538SAndroid Build Coastguard Worker switch (proxyType) {
997*6777b538SAndroid Build Coastguard Worker case 0:
998*6777b538SAndroid Build Coastguard Worker /* we will try in sequence */
999*6777b538SAndroid Build Coastguard Worker case 1:
1000*6777b538SAndroid Build Coastguard Worker /* Using SITE command */
1001*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "SITE %s\r\n", ctxt->hostname);
1002*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1003*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1004*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1005*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1006*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1007*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1008*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1009*6777b538SAndroid Build Coastguard Worker return(res);
1010*6777b538SAndroid Build Coastguard Worker }
1011*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1012*6777b538SAndroid Build Coastguard Worker if (res == 2) {
1013*6777b538SAndroid Build Coastguard Worker /* we assume it worked :-\ 1 is error for SITE command */
1014*6777b538SAndroid Build Coastguard Worker proxyType = 1;
1015*6777b538SAndroid Build Coastguard Worker break;
1016*6777b538SAndroid Build Coastguard Worker }
1017*6777b538SAndroid Build Coastguard Worker if (proxyType == 1) {
1018*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1019*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1020*6777b538SAndroid Build Coastguard Worker return(-1);
1021*6777b538SAndroid Build Coastguard Worker }
1022*6777b538SAndroid Build Coastguard Worker /* Falls through. */
1023*6777b538SAndroid Build Coastguard Worker case 2:
1024*6777b538SAndroid Build Coastguard Worker /* USER user@host command */
1025*6777b538SAndroid Build Coastguard Worker if (ctxt->user == NULL)
1026*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "USER anonymous@%s\r\n",
1027*6777b538SAndroid Build Coastguard Worker ctxt->hostname);
1028*6777b538SAndroid Build Coastguard Worker else
1029*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "USER %s@%s\r\n",
1030*6777b538SAndroid Build Coastguard Worker ctxt->user, ctxt->hostname);
1031*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1032*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1033*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1034*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1035*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1036*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1037*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1038*6777b538SAndroid Build Coastguard Worker return(res);
1039*6777b538SAndroid Build Coastguard Worker }
1040*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1041*6777b538SAndroid Build Coastguard Worker if ((res == 1) || (res == 2)) {
1042*6777b538SAndroid Build Coastguard Worker /* we assume it worked :-\ */
1043*6777b538SAndroid Build Coastguard Worker proxyType = 2;
1044*6777b538SAndroid Build Coastguard Worker return(0);
1045*6777b538SAndroid Build Coastguard Worker }
1046*6777b538SAndroid Build Coastguard Worker if (ctxt->passwd == NULL)
1047*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS anonymous@\r\n");
1048*6777b538SAndroid Build Coastguard Worker else
1049*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "PASS %s\r\n", ctxt->passwd);
1050*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1051*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1052*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1053*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1054*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1055*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1056*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1057*6777b538SAndroid Build Coastguard Worker return(res);
1058*6777b538SAndroid Build Coastguard Worker }
1059*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1060*6777b538SAndroid Build Coastguard Worker if ((res == 1) || (res == 2)) {
1061*6777b538SAndroid Build Coastguard Worker /* we assume it worked :-\ */
1062*6777b538SAndroid Build Coastguard Worker proxyType = 2;
1063*6777b538SAndroid Build Coastguard Worker return(0);
1064*6777b538SAndroid Build Coastguard Worker }
1065*6777b538SAndroid Build Coastguard Worker if (proxyType == 2) {
1066*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1067*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1068*6777b538SAndroid Build Coastguard Worker return(-1);
1069*6777b538SAndroid Build Coastguard Worker }
1070*6777b538SAndroid Build Coastguard Worker /* Falls through. */
1071*6777b538SAndroid Build Coastguard Worker case 3:
1072*6777b538SAndroid Build Coastguard Worker /*
1073*6777b538SAndroid Build Coastguard Worker * If you need support for other Proxy authentication scheme
1074*6777b538SAndroid Build Coastguard Worker * send the code or at least the sequence in use.
1075*6777b538SAndroid Build Coastguard Worker */
1076*6777b538SAndroid Build Coastguard Worker default:
1077*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1078*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1079*6777b538SAndroid Build Coastguard Worker return(-1);
1080*6777b538SAndroid Build Coastguard Worker }
1081*6777b538SAndroid Build Coastguard Worker }
1082*6777b538SAndroid Build Coastguard Worker /*
1083*6777b538SAndroid Build Coastguard Worker * Non-proxy handling.
1084*6777b538SAndroid Build Coastguard Worker */
1085*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPSendUser(ctxt);
1086*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1087*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1088*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1089*6777b538SAndroid Build Coastguard Worker return(-1);
1090*6777b538SAndroid Build Coastguard Worker }
1091*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1092*6777b538SAndroid Build Coastguard Worker switch (res) {
1093*6777b538SAndroid Build Coastguard Worker case 2:
1094*6777b538SAndroid Build Coastguard Worker return(0);
1095*6777b538SAndroid Build Coastguard Worker case 3:
1096*6777b538SAndroid Build Coastguard Worker break;
1097*6777b538SAndroid Build Coastguard Worker case 1:
1098*6777b538SAndroid Build Coastguard Worker case 4:
1099*6777b538SAndroid Build Coastguard Worker case 5:
1100*6777b538SAndroid Build Coastguard Worker case -1:
1101*6777b538SAndroid Build Coastguard Worker default:
1102*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1103*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1104*6777b538SAndroid Build Coastguard Worker return(-1);
1105*6777b538SAndroid Build Coastguard Worker }
1106*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPSendPasswd(ctxt);
1107*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1108*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1109*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1110*6777b538SAndroid Build Coastguard Worker return(-1);
1111*6777b538SAndroid Build Coastguard Worker }
1112*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1113*6777b538SAndroid Build Coastguard Worker switch (res) {
1114*6777b538SAndroid Build Coastguard Worker case 2:
1115*6777b538SAndroid Build Coastguard Worker break;
1116*6777b538SAndroid Build Coastguard Worker case 3:
1117*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, XML_FTP_ACCNT,
1118*6777b538SAndroid Build Coastguard Worker "FTP server asking for ACCNT on anonymous\n");
1119*6777b538SAndroid Build Coastguard Worker /* Falls through. */
1120*6777b538SAndroid Build Coastguard Worker case 1:
1121*6777b538SAndroid Build Coastguard Worker case 4:
1122*6777b538SAndroid Build Coastguard Worker case 5:
1123*6777b538SAndroid Build Coastguard Worker case -1:
1124*6777b538SAndroid Build Coastguard Worker default:
1125*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1126*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1127*6777b538SAndroid Build Coastguard Worker return(-1);
1128*6777b538SAndroid Build Coastguard Worker }
1129*6777b538SAndroid Build Coastguard Worker
1130*6777b538SAndroid Build Coastguard Worker return(0);
1131*6777b538SAndroid Build Coastguard Worker }
1132*6777b538SAndroid Build Coastguard Worker
1133*6777b538SAndroid Build Coastguard Worker /**
1134*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPConnectTo:
1135*6777b538SAndroid Build Coastguard Worker * @server: an FTP server name
1136*6777b538SAndroid Build Coastguard Worker * @port: the port (use 21 if 0)
1137*6777b538SAndroid Build Coastguard Worker *
1138*6777b538SAndroid Build Coastguard Worker * Tries to open a control connection to the given server/port
1139*6777b538SAndroid Build Coastguard Worker *
1140*6777b538SAndroid Build Coastguard Worker * Returns an fTP context or NULL if it failed
1141*6777b538SAndroid Build Coastguard Worker */
1142*6777b538SAndroid Build Coastguard Worker
1143*6777b538SAndroid Build Coastguard Worker void*
xmlNanoFTPConnectTo(const char * server,int port)1144*6777b538SAndroid Build Coastguard Worker xmlNanoFTPConnectTo(const char *server, int port) {
1145*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt;
1146*6777b538SAndroid Build Coastguard Worker int res;
1147*6777b538SAndroid Build Coastguard Worker
1148*6777b538SAndroid Build Coastguard Worker xmlNanoFTPInit();
1149*6777b538SAndroid Build Coastguard Worker if (server == NULL)
1150*6777b538SAndroid Build Coastguard Worker return(NULL);
1151*6777b538SAndroid Build Coastguard Worker if (port <= 0)
1152*6777b538SAndroid Build Coastguard Worker return(NULL);
1153*6777b538SAndroid Build Coastguard Worker ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(NULL);
1154*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
1155*6777b538SAndroid Build Coastguard Worker return(NULL);
1156*6777b538SAndroid Build Coastguard Worker ctxt->hostname = xmlMemStrdup(server);
1157*6777b538SAndroid Build Coastguard Worker if (ctxt->hostname == NULL) {
1158*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(ctxt);
1159*6777b538SAndroid Build Coastguard Worker return(NULL);
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker ctxt->port = port;
1162*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPConnect(ctxt);
1163*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1164*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(ctxt);
1165*6777b538SAndroid Build Coastguard Worker return(NULL);
1166*6777b538SAndroid Build Coastguard Worker }
1167*6777b538SAndroid Build Coastguard Worker return(ctxt);
1168*6777b538SAndroid Build Coastguard Worker }
1169*6777b538SAndroid Build Coastguard Worker
1170*6777b538SAndroid Build Coastguard Worker /**
1171*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPCwd:
1172*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1173*6777b538SAndroid Build Coastguard Worker * @directory: a directory on the server
1174*6777b538SAndroid Build Coastguard Worker *
1175*6777b538SAndroid Build Coastguard Worker * Tries to change the remote directory
1176*6777b538SAndroid Build Coastguard Worker *
1177*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 1 if CWD worked, 0 if it failed
1178*6777b538SAndroid Build Coastguard Worker */
1179*6777b538SAndroid Build Coastguard Worker
1180*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPCwd(void * ctx,const char * directory)1181*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCwd(void *ctx, const char *directory) {
1182*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1183*6777b538SAndroid Build Coastguard Worker char buf[400];
1184*6777b538SAndroid Build Coastguard Worker int len;
1185*6777b538SAndroid Build Coastguard Worker int res;
1186*6777b538SAndroid Build Coastguard Worker
1187*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
1188*6777b538SAndroid Build Coastguard Worker if (directory == NULL) return 0;
1189*6777b538SAndroid Build Coastguard Worker
1190*6777b538SAndroid Build Coastguard Worker /*
1191*6777b538SAndroid Build Coastguard Worker * Expected response code for CWD:
1192*6777b538SAndroid Build Coastguard Worker *
1193*6777b538SAndroid Build Coastguard Worker * CWD
1194*6777b538SAndroid Build Coastguard Worker * 250
1195*6777b538SAndroid Build Coastguard Worker * 500, 501, 502, 421, 530, 550
1196*6777b538SAndroid Build Coastguard Worker */
1197*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "CWD %s\r\n", directory);
1198*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1199*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1200*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1201*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1202*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1203*6777b538SAndroid Build Coastguard Worker return(res);
1204*6777b538SAndroid Build Coastguard Worker }
1205*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1206*6777b538SAndroid Build Coastguard Worker if (res == 4) {
1207*6777b538SAndroid Build Coastguard Worker return(-1);
1208*6777b538SAndroid Build Coastguard Worker }
1209*6777b538SAndroid Build Coastguard Worker if (res == 2) return(1);
1210*6777b538SAndroid Build Coastguard Worker if (res == 5) {
1211*6777b538SAndroid Build Coastguard Worker return(0);
1212*6777b538SAndroid Build Coastguard Worker }
1213*6777b538SAndroid Build Coastguard Worker return(0);
1214*6777b538SAndroid Build Coastguard Worker }
1215*6777b538SAndroid Build Coastguard Worker
1216*6777b538SAndroid Build Coastguard Worker /**
1217*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPDele:
1218*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1219*6777b538SAndroid Build Coastguard Worker * @file: a file or directory on the server
1220*6777b538SAndroid Build Coastguard Worker *
1221*6777b538SAndroid Build Coastguard Worker * Tries to delete an item (file or directory) from server
1222*6777b538SAndroid Build Coastguard Worker *
1223*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 1 if DELE worked, 0 if it failed
1224*6777b538SAndroid Build Coastguard Worker */
1225*6777b538SAndroid Build Coastguard Worker
1226*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPDele(void * ctx,const char * file)1227*6777b538SAndroid Build Coastguard Worker xmlNanoFTPDele(void *ctx, const char *file) {
1228*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1229*6777b538SAndroid Build Coastguard Worker char buf[400];
1230*6777b538SAndroid Build Coastguard Worker int len;
1231*6777b538SAndroid Build Coastguard Worker int res;
1232*6777b538SAndroid Build Coastguard Worker
1233*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET) ||
1234*6777b538SAndroid Build Coastguard Worker (file == NULL)) return(-1);
1235*6777b538SAndroid Build Coastguard Worker
1236*6777b538SAndroid Build Coastguard Worker /*
1237*6777b538SAndroid Build Coastguard Worker * Expected response code for DELE:
1238*6777b538SAndroid Build Coastguard Worker *
1239*6777b538SAndroid Build Coastguard Worker * DELE
1240*6777b538SAndroid Build Coastguard Worker * 250
1241*6777b538SAndroid Build Coastguard Worker * 450, 550
1242*6777b538SAndroid Build Coastguard Worker * 500, 501, 502, 421, 530
1243*6777b538SAndroid Build Coastguard Worker */
1244*6777b538SAndroid Build Coastguard Worker
1245*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "DELE %s\r\n", file);
1246*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1247*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1248*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1249*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1250*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1251*6777b538SAndroid Build Coastguard Worker return(res);
1252*6777b538SAndroid Build Coastguard Worker }
1253*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1254*6777b538SAndroid Build Coastguard Worker if (res == 4) {
1255*6777b538SAndroid Build Coastguard Worker return(-1);
1256*6777b538SAndroid Build Coastguard Worker }
1257*6777b538SAndroid Build Coastguard Worker if (res == 2) return(1);
1258*6777b538SAndroid Build Coastguard Worker if (res == 5) {
1259*6777b538SAndroid Build Coastguard Worker return(0);
1260*6777b538SAndroid Build Coastguard Worker }
1261*6777b538SAndroid Build Coastguard Worker return(0);
1262*6777b538SAndroid Build Coastguard Worker }
1263*6777b538SAndroid Build Coastguard Worker /**
1264*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPGetConnection:
1265*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1266*6777b538SAndroid Build Coastguard Worker *
1267*6777b538SAndroid Build Coastguard Worker * Try to open a data connection to the server. Currently only
1268*6777b538SAndroid Build Coastguard Worker * passive mode is supported.
1269*6777b538SAndroid Build Coastguard Worker *
1270*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
1271*6777b538SAndroid Build Coastguard Worker */
1272*6777b538SAndroid Build Coastguard Worker
1273*6777b538SAndroid Build Coastguard Worker SOCKET
xmlNanoFTPGetConnection(void * ctx)1274*6777b538SAndroid Build Coastguard Worker xmlNanoFTPGetConnection(void *ctx) {
1275*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1276*6777b538SAndroid Build Coastguard Worker char buf[200], *cur;
1277*6777b538SAndroid Build Coastguard Worker int len, i;
1278*6777b538SAndroid Build Coastguard Worker int res;
1279*6777b538SAndroid Build Coastguard Worker unsigned char ad[6], *adp, *portp;
1280*6777b538SAndroid Build Coastguard Worker unsigned int temp[6];
1281*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1282*6777b538SAndroid Build Coastguard Worker struct sockaddr_storage dataAddr;
1283*6777b538SAndroid Build Coastguard Worker #else
1284*6777b538SAndroid Build Coastguard Worker struct sockaddr_in dataAddr;
1285*6777b538SAndroid Build Coastguard Worker #endif
1286*6777b538SAndroid Build Coastguard Worker XML_SOCKLEN_T dataAddrLen;
1287*6777b538SAndroid Build Coastguard Worker
1288*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return INVALID_SOCKET;
1289*6777b538SAndroid Build Coastguard Worker
1290*6777b538SAndroid Build Coastguard Worker memset (&dataAddr, 0, sizeof(dataAddr));
1291*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1292*6777b538SAndroid Build Coastguard Worker if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1293*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP);
1294*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&dataAddr)->sin6_family = AF_INET6;
1295*6777b538SAndroid Build Coastguard Worker dataAddrLen = sizeof(struct sockaddr_in6);
1296*6777b538SAndroid Build Coastguard Worker } else
1297*6777b538SAndroid Build Coastguard Worker #endif
1298*6777b538SAndroid Build Coastguard Worker {
1299*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
1300*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in *)&dataAddr)->sin_family = AF_INET;
1301*6777b538SAndroid Build Coastguard Worker dataAddrLen = sizeof (struct sockaddr_in);
1302*6777b538SAndroid Build Coastguard Worker }
1303*6777b538SAndroid Build Coastguard Worker
1304*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd == INVALID_SOCKET) {
1305*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "socket failed");
1306*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1307*6777b538SAndroid Build Coastguard Worker }
1308*6777b538SAndroid Build Coastguard Worker
1309*6777b538SAndroid Build Coastguard Worker if (ctxt->passive) {
1310*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1311*6777b538SAndroid Build Coastguard Worker if ((ctxt->ftpAddr).ss_family == AF_INET6)
1312*6777b538SAndroid Build Coastguard Worker snprintf (buf, sizeof(buf), "EPSV\r\n");
1313*6777b538SAndroid Build Coastguard Worker else
1314*6777b538SAndroid Build Coastguard Worker #endif
1315*6777b538SAndroid Build Coastguard Worker snprintf (buf, sizeof(buf), "PASV\r\n");
1316*6777b538SAndroid Build Coastguard Worker len = strlen (buf);
1317*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1318*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1319*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1320*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1321*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1322*6777b538SAndroid Build Coastguard Worker }
1323*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPReadResponse(ctx);
1324*6777b538SAndroid Build Coastguard Worker if (res != 2) {
1325*6777b538SAndroid Build Coastguard Worker if (res == 5) {
1326*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1327*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1328*6777b538SAndroid Build Coastguard Worker } else {
1329*6777b538SAndroid Build Coastguard Worker /*
1330*6777b538SAndroid Build Coastguard Worker * retry with an active connection
1331*6777b538SAndroid Build Coastguard Worker */
1332*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1333*6777b538SAndroid Build Coastguard Worker ctxt->passive = 0;
1334*6777b538SAndroid Build Coastguard Worker }
1335*6777b538SAndroid Build Coastguard Worker }
1336*6777b538SAndroid Build Coastguard Worker cur = &ctxt->controlBuf[ctxt->controlBufAnswer];
1337*6777b538SAndroid Build Coastguard Worker while (((*cur < '0') || (*cur > '9')) && *cur != '\0') cur++;
1338*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1339*6777b538SAndroid Build Coastguard Worker if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1340*6777b538SAndroid Build Coastguard Worker if (sscanf (cur, "%u", &temp[0]) != 1) {
1341*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, XML_FTP_EPSV_ANSWER,
1342*6777b538SAndroid Build Coastguard Worker "Invalid answer to EPSV\n");
1343*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd != INVALID_SOCKET) {
1344*6777b538SAndroid Build Coastguard Worker closesocket (ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1345*6777b538SAndroid Build Coastguard Worker }
1346*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1347*6777b538SAndroid Build Coastguard Worker }
1348*6777b538SAndroid Build Coastguard Worker memcpy (&((struct sockaddr_in6 *)&dataAddr)->sin6_addr, &((struct sockaddr_in6 *)&ctxt->ftpAddr)->sin6_addr, sizeof(struct in6_addr));
1349*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&dataAddr)->sin6_port = htons (temp[0]);
1350*6777b538SAndroid Build Coastguard Worker }
1351*6777b538SAndroid Build Coastguard Worker else
1352*6777b538SAndroid Build Coastguard Worker #endif
1353*6777b538SAndroid Build Coastguard Worker {
1354*6777b538SAndroid Build Coastguard Worker if (sscanf (cur, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
1355*6777b538SAndroid Build Coastguard Worker &temp[3], &temp[4], &temp[5]) != 6) {
1356*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, XML_FTP_PASV_ANSWER,
1357*6777b538SAndroid Build Coastguard Worker "Invalid answer to PASV\n");
1358*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd != INVALID_SOCKET) {
1359*6777b538SAndroid Build Coastguard Worker closesocket (ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1360*6777b538SAndroid Build Coastguard Worker }
1361*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1362*6777b538SAndroid Build Coastguard Worker }
1363*6777b538SAndroid Build Coastguard Worker for (i=0; i<6; i++) ad[i] = (unsigned char) (temp[i] & 0xff);
1364*6777b538SAndroid Build Coastguard Worker memcpy (&((struct sockaddr_in *)&dataAddr)->sin_addr, &ad[0], 4);
1365*6777b538SAndroid Build Coastguard Worker memcpy (&((struct sockaddr_in *)&dataAddr)->sin_port, &ad[4], 2);
1366*6777b538SAndroid Build Coastguard Worker }
1367*6777b538SAndroid Build Coastguard Worker
1368*6777b538SAndroid Build Coastguard Worker if (connect(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
1369*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "Failed to create a data connection");
1370*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1371*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1372*6777b538SAndroid Build Coastguard Worker }
1373*6777b538SAndroid Build Coastguard Worker } else {
1374*6777b538SAndroid Build Coastguard Worker getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
1375*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1376*6777b538SAndroid Build Coastguard Worker if ((ctxt->ftpAddr).ss_family == AF_INET6)
1377*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in6 *)&dataAddr)->sin6_port = 0;
1378*6777b538SAndroid Build Coastguard Worker else
1379*6777b538SAndroid Build Coastguard Worker #endif
1380*6777b538SAndroid Build Coastguard Worker ((struct sockaddr_in *)&dataAddr)->sin_port = 0;
1381*6777b538SAndroid Build Coastguard Worker
1382*6777b538SAndroid Build Coastguard Worker if (bind(ctxt->dataFd, (struct sockaddr *) &dataAddr, dataAddrLen) < 0) {
1383*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "bind failed");
1384*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1385*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1386*6777b538SAndroid Build Coastguard Worker }
1387*6777b538SAndroid Build Coastguard Worker getsockname(ctxt->dataFd, (struct sockaddr *) &dataAddr, &dataAddrLen);
1388*6777b538SAndroid Build Coastguard Worker
1389*6777b538SAndroid Build Coastguard Worker if (listen(ctxt->dataFd, 1) < 0) {
1390*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "listen failed");
1391*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1392*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1393*6777b538SAndroid Build Coastguard Worker }
1394*6777b538SAndroid Build Coastguard Worker #ifdef SUPPORT_IP6
1395*6777b538SAndroid Build Coastguard Worker if ((ctxt->ftpAddr).ss_family == AF_INET6) {
1396*6777b538SAndroid Build Coastguard Worker char buf6[INET6_ADDRSTRLEN];
1397*6777b538SAndroid Build Coastguard Worker inet_ntop (AF_INET6, &((struct sockaddr_in6 *)&dataAddr)->sin6_addr,
1398*6777b538SAndroid Build Coastguard Worker buf6, INET6_ADDRSTRLEN);
1399*6777b538SAndroid Build Coastguard Worker adp = (unsigned char *) buf6;
1400*6777b538SAndroid Build Coastguard Worker portp = (unsigned char *) &((struct sockaddr_in6 *)&dataAddr)->sin6_port;
1401*6777b538SAndroid Build Coastguard Worker snprintf (buf, sizeof(buf), "EPRT |2|%s|%s|\r\n", adp, portp);
1402*6777b538SAndroid Build Coastguard Worker } else
1403*6777b538SAndroid Build Coastguard Worker #endif
1404*6777b538SAndroid Build Coastguard Worker {
1405*6777b538SAndroid Build Coastguard Worker adp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_addr;
1406*6777b538SAndroid Build Coastguard Worker portp = (unsigned char *) &((struct sockaddr_in *)&dataAddr)->sin_port;
1407*6777b538SAndroid Build Coastguard Worker snprintf (buf, sizeof(buf), "PORT %d,%d,%d,%d,%d,%d\r\n",
1408*6777b538SAndroid Build Coastguard Worker adp[0] & 0xff, adp[1] & 0xff, adp[2] & 0xff, adp[3] & 0xff,
1409*6777b538SAndroid Build Coastguard Worker portp[0] & 0xff, portp[1] & 0xff);
1410*6777b538SAndroid Build Coastguard Worker }
1411*6777b538SAndroid Build Coastguard Worker
1412*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1413*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1414*6777b538SAndroid Build Coastguard Worker
1415*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1416*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1417*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1418*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1419*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1420*6777b538SAndroid Build Coastguard Worker }
1421*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1422*6777b538SAndroid Build Coastguard Worker if (res != 2) {
1423*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1424*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1425*6777b538SAndroid Build Coastguard Worker }
1426*6777b538SAndroid Build Coastguard Worker }
1427*6777b538SAndroid Build Coastguard Worker return(ctxt->dataFd);
1428*6777b538SAndroid Build Coastguard Worker
1429*6777b538SAndroid Build Coastguard Worker }
1430*6777b538SAndroid Build Coastguard Worker
1431*6777b538SAndroid Build Coastguard Worker /**
1432*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPCloseConnection:
1433*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1434*6777b538SAndroid Build Coastguard Worker *
1435*6777b538SAndroid Build Coastguard Worker * Close the data connection from the server
1436*6777b538SAndroid Build Coastguard Worker *
1437*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
1438*6777b538SAndroid Build Coastguard Worker */
1439*6777b538SAndroid Build Coastguard Worker
1440*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPCloseConnection(void * ctx)1441*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCloseConnection(void *ctx) {
1442*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1443*6777b538SAndroid Build Coastguard Worker int res;
1444*6777b538SAndroid Build Coastguard Worker fd_set rfd, efd;
1445*6777b538SAndroid Build Coastguard Worker struct timeval tv;
1446*6777b538SAndroid Build Coastguard Worker
1447*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->controlFd == INVALID_SOCKET)) return(-1);
1448*6777b538SAndroid Build Coastguard Worker
1449*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1450*6777b538SAndroid Build Coastguard Worker tv.tv_sec = 15;
1451*6777b538SAndroid Build Coastguard Worker tv.tv_usec = 0;
1452*6777b538SAndroid Build Coastguard Worker FD_ZERO(&rfd);
1453*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->controlFd, &rfd);
1454*6777b538SAndroid Build Coastguard Worker FD_ZERO(&efd);
1455*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->controlFd, &efd);
1456*6777b538SAndroid Build Coastguard Worker res = select(ctxt->controlFd + 1, &rfd, NULL, &efd, &tv);
1457*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1458*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1459*6777b538SAndroid Build Coastguard Worker return(-1);
1460*6777b538SAndroid Build Coastguard Worker }
1461*6777b538SAndroid Build Coastguard Worker if (res == 0) {
1462*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1463*6777b538SAndroid Build Coastguard Worker } else {
1464*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPGetResponse(ctxt);
1465*6777b538SAndroid Build Coastguard Worker if (res != 2) {
1466*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd); ctxt->controlFd = INVALID_SOCKET;
1467*6777b538SAndroid Build Coastguard Worker return(-1);
1468*6777b538SAndroid Build Coastguard Worker }
1469*6777b538SAndroid Build Coastguard Worker }
1470*6777b538SAndroid Build Coastguard Worker return(0);
1471*6777b538SAndroid Build Coastguard Worker }
1472*6777b538SAndroid Build Coastguard Worker
1473*6777b538SAndroid Build Coastguard Worker /**
1474*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPParseList:
1475*6777b538SAndroid Build Coastguard Worker * @list: some data listing received from the server
1476*6777b538SAndroid Build Coastguard Worker * @callback: the user callback
1477*6777b538SAndroid Build Coastguard Worker * @userData: the user callback data
1478*6777b538SAndroid Build Coastguard Worker *
1479*6777b538SAndroid Build Coastguard Worker * Parse at most one entry from the listing.
1480*6777b538SAndroid Build Coastguard Worker *
1481*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, the length of data parsed otherwise
1482*6777b538SAndroid Build Coastguard Worker */
1483*6777b538SAndroid Build Coastguard Worker
1484*6777b538SAndroid Build Coastguard Worker static int
xmlNanoFTPParseList(const char * list,ftpListCallback callback,void * userData)1485*6777b538SAndroid Build Coastguard Worker xmlNanoFTPParseList(const char *list, ftpListCallback callback, void *userData) {
1486*6777b538SAndroid Build Coastguard Worker const char *cur = list;
1487*6777b538SAndroid Build Coastguard Worker char filename[151];
1488*6777b538SAndroid Build Coastguard Worker char attrib[11];
1489*6777b538SAndroid Build Coastguard Worker char owner[11];
1490*6777b538SAndroid Build Coastguard Worker char group[11];
1491*6777b538SAndroid Build Coastguard Worker char month[4];
1492*6777b538SAndroid Build Coastguard Worker int year = 0;
1493*6777b538SAndroid Build Coastguard Worker int minute = 0;
1494*6777b538SAndroid Build Coastguard Worker int hour = 0;
1495*6777b538SAndroid Build Coastguard Worker int day = 0;
1496*6777b538SAndroid Build Coastguard Worker unsigned long size = 0;
1497*6777b538SAndroid Build Coastguard Worker int links = 0;
1498*6777b538SAndroid Build Coastguard Worker int i;
1499*6777b538SAndroid Build Coastguard Worker
1500*6777b538SAndroid Build Coastguard Worker if (!strncmp(cur, "total", 5)) {
1501*6777b538SAndroid Build Coastguard Worker cur += 5;
1502*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1503*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1504*6777b538SAndroid Build Coastguard Worker links = (links * 10) + (*cur++ - '0');
1505*6777b538SAndroid Build Coastguard Worker while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r'))
1506*6777b538SAndroid Build Coastguard Worker cur++;
1507*6777b538SAndroid Build Coastguard Worker return(cur - list);
1508*6777b538SAndroid Build Coastguard Worker } else if (*list == '+') {
1509*6777b538SAndroid Build Coastguard Worker return(0);
1510*6777b538SAndroid Build Coastguard Worker } else {
1511*6777b538SAndroid Build Coastguard Worker while ((*cur == ' ') || (*cur == '\n') || (*cur == '\r'))
1512*6777b538SAndroid Build Coastguard Worker cur++;
1513*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1514*6777b538SAndroid Build Coastguard Worker i = 0;
1515*6777b538SAndroid Build Coastguard Worker while (*cur != ' ') {
1516*6777b538SAndroid Build Coastguard Worker if (i < 10)
1517*6777b538SAndroid Build Coastguard Worker attrib[i++] = *cur;
1518*6777b538SAndroid Build Coastguard Worker cur++;
1519*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1520*6777b538SAndroid Build Coastguard Worker }
1521*6777b538SAndroid Build Coastguard Worker attrib[10] = 0;
1522*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1523*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1524*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1525*6777b538SAndroid Build Coastguard Worker links = (links * 10) + (*cur++ - '0');
1526*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1527*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1528*6777b538SAndroid Build Coastguard Worker i = 0;
1529*6777b538SAndroid Build Coastguard Worker while (*cur != ' ') {
1530*6777b538SAndroid Build Coastguard Worker if (i < 10)
1531*6777b538SAndroid Build Coastguard Worker owner[i++] = *cur;
1532*6777b538SAndroid Build Coastguard Worker cur++;
1533*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1534*6777b538SAndroid Build Coastguard Worker }
1535*6777b538SAndroid Build Coastguard Worker owner[i] = 0;
1536*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1537*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1538*6777b538SAndroid Build Coastguard Worker i = 0;
1539*6777b538SAndroid Build Coastguard Worker while (*cur != ' ') {
1540*6777b538SAndroid Build Coastguard Worker if (i < 10)
1541*6777b538SAndroid Build Coastguard Worker group[i++] = *cur;
1542*6777b538SAndroid Build Coastguard Worker cur++;
1543*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1544*6777b538SAndroid Build Coastguard Worker }
1545*6777b538SAndroid Build Coastguard Worker group[i] = 0;
1546*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1547*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1548*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1549*6777b538SAndroid Build Coastguard Worker size = (size * 10) + (*cur++ - '0');
1550*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1551*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1552*6777b538SAndroid Build Coastguard Worker i = 0;
1553*6777b538SAndroid Build Coastguard Worker while (*cur != ' ') {
1554*6777b538SAndroid Build Coastguard Worker if (i < 3)
1555*6777b538SAndroid Build Coastguard Worker month[i++] = *cur;
1556*6777b538SAndroid Build Coastguard Worker cur++;
1557*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1558*6777b538SAndroid Build Coastguard Worker }
1559*6777b538SAndroid Build Coastguard Worker month[i] = 0;
1560*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1561*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1562*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1563*6777b538SAndroid Build Coastguard Worker day = (day * 10) + (*cur++ - '0');
1564*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1565*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1566*6777b538SAndroid Build Coastguard Worker if ((cur[1] == 0) || (cur[2] == 0)) return(0);
1567*6777b538SAndroid Build Coastguard Worker if ((cur[1] == ':') || (cur[2] == ':')) {
1568*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1569*6777b538SAndroid Build Coastguard Worker hour = (hour * 10) + (*cur++ - '0');
1570*6777b538SAndroid Build Coastguard Worker if (*cur == ':') cur++;
1571*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1572*6777b538SAndroid Build Coastguard Worker minute = (minute * 10) + (*cur++ - '0');
1573*6777b538SAndroid Build Coastguard Worker } else {
1574*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
1575*6777b538SAndroid Build Coastguard Worker year = (year * 10) + (*cur++ - '0');
1576*6777b538SAndroid Build Coastguard Worker }
1577*6777b538SAndroid Build Coastguard Worker while (*cur == ' ') cur++;
1578*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1579*6777b538SAndroid Build Coastguard Worker i = 0;
1580*6777b538SAndroid Build Coastguard Worker while ((*cur != '\n') && (*cur != '\r')) {
1581*6777b538SAndroid Build Coastguard Worker if (i < 150)
1582*6777b538SAndroid Build Coastguard Worker filename[i++] = *cur;
1583*6777b538SAndroid Build Coastguard Worker cur++;
1584*6777b538SAndroid Build Coastguard Worker if (*cur == 0) return(0);
1585*6777b538SAndroid Build Coastguard Worker }
1586*6777b538SAndroid Build Coastguard Worker filename[i] = 0;
1587*6777b538SAndroid Build Coastguard Worker if ((*cur != '\n') && (*cur != '\r'))
1588*6777b538SAndroid Build Coastguard Worker return(0);
1589*6777b538SAndroid Build Coastguard Worker while ((*cur == '\n') || (*cur == '\r'))
1590*6777b538SAndroid Build Coastguard Worker cur++;
1591*6777b538SAndroid Build Coastguard Worker }
1592*6777b538SAndroid Build Coastguard Worker if (callback != NULL) {
1593*6777b538SAndroid Build Coastguard Worker callback(userData, filename, attrib, owner, group, size, links,
1594*6777b538SAndroid Build Coastguard Worker year, month, day, hour, minute);
1595*6777b538SAndroid Build Coastguard Worker }
1596*6777b538SAndroid Build Coastguard Worker return(cur - list);
1597*6777b538SAndroid Build Coastguard Worker }
1598*6777b538SAndroid Build Coastguard Worker
1599*6777b538SAndroid Build Coastguard Worker /**
1600*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPList:
1601*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1602*6777b538SAndroid Build Coastguard Worker * @callback: the user callback
1603*6777b538SAndroid Build Coastguard Worker * @userData: the user callback data
1604*6777b538SAndroid Build Coastguard Worker * @filename: optional files to list
1605*6777b538SAndroid Build Coastguard Worker *
1606*6777b538SAndroid Build Coastguard Worker * Do a listing on the server. All files info are passed back
1607*6777b538SAndroid Build Coastguard Worker * in the callbacks.
1608*6777b538SAndroid Build Coastguard Worker *
1609*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
1610*6777b538SAndroid Build Coastguard Worker */
1611*6777b538SAndroid Build Coastguard Worker
1612*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPList(void * ctx,ftpListCallback callback,void * userData,const char * filename)1613*6777b538SAndroid Build Coastguard Worker xmlNanoFTPList(void *ctx, ftpListCallback callback, void *userData,
1614*6777b538SAndroid Build Coastguard Worker const char *filename) {
1615*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1616*6777b538SAndroid Build Coastguard Worker char buf[4096 + 1];
1617*6777b538SAndroid Build Coastguard Worker int len, res;
1618*6777b538SAndroid Build Coastguard Worker int indx = 0, base;
1619*6777b538SAndroid Build Coastguard Worker fd_set rfd, efd;
1620*6777b538SAndroid Build Coastguard Worker struct timeval tv;
1621*6777b538SAndroid Build Coastguard Worker
1622*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return (-1);
1623*6777b538SAndroid Build Coastguard Worker if (filename == NULL) {
1624*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
1625*6777b538SAndroid Build Coastguard Worker return(-1);
1626*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1627*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd == INVALID_SOCKET)
1628*6777b538SAndroid Build Coastguard Worker return(-1);
1629*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "LIST -L\r\n");
1630*6777b538SAndroid Build Coastguard Worker } else {
1631*6777b538SAndroid Build Coastguard Worker if (filename[0] != '/') {
1632*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPCwd(ctxt, ctxt->path) < 1)
1633*6777b538SAndroid Build Coastguard Worker return(-1);
1634*6777b538SAndroid Build Coastguard Worker }
1635*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1636*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd == INVALID_SOCKET)
1637*6777b538SAndroid Build Coastguard Worker return(-1);
1638*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "LIST -L %s\r\n", filename);
1639*6777b538SAndroid Build Coastguard Worker }
1640*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1641*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1642*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1643*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1644*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1645*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1646*6777b538SAndroid Build Coastguard Worker return(res);
1647*6777b538SAndroid Build Coastguard Worker }
1648*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPReadResponse(ctxt);
1649*6777b538SAndroid Build Coastguard Worker if (res != 1) {
1650*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1651*6777b538SAndroid Build Coastguard Worker return(-res);
1652*6777b538SAndroid Build Coastguard Worker }
1653*6777b538SAndroid Build Coastguard Worker
1654*6777b538SAndroid Build Coastguard Worker do {
1655*6777b538SAndroid Build Coastguard Worker tv.tv_sec = 1;
1656*6777b538SAndroid Build Coastguard Worker tv.tv_usec = 0;
1657*6777b538SAndroid Build Coastguard Worker FD_ZERO(&rfd);
1658*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->dataFd, &rfd);
1659*6777b538SAndroid Build Coastguard Worker FD_ZERO(&efd);
1660*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->dataFd, &efd);
1661*6777b538SAndroid Build Coastguard Worker res = select(ctxt->dataFd + 1, &rfd, NULL, &efd, &tv);
1662*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1663*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1664*6777b538SAndroid Build Coastguard Worker return(-1);
1665*6777b538SAndroid Build Coastguard Worker }
1666*6777b538SAndroid Build Coastguard Worker if (res == 0) {
1667*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPCheckResponse(ctxt);
1668*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1669*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1670*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = INVALID_SOCKET;
1671*6777b538SAndroid Build Coastguard Worker return(-1);
1672*6777b538SAndroid Build Coastguard Worker }
1673*6777b538SAndroid Build Coastguard Worker if (res == 2) {
1674*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1675*6777b538SAndroid Build Coastguard Worker return(0);
1676*6777b538SAndroid Build Coastguard Worker }
1677*6777b538SAndroid Build Coastguard Worker
1678*6777b538SAndroid Build Coastguard Worker continue;
1679*6777b538SAndroid Build Coastguard Worker }
1680*6777b538SAndroid Build Coastguard Worker
1681*6777b538SAndroid Build Coastguard Worker if ((len = recv(ctxt->dataFd, &buf[indx], sizeof(buf) - (indx + 1), 0)) < 0) {
1682*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "recv");
1683*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1684*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = INVALID_SOCKET;
1685*6777b538SAndroid Build Coastguard Worker return(-1);
1686*6777b538SAndroid Build Coastguard Worker }
1687*6777b538SAndroid Build Coastguard Worker indx += len;
1688*6777b538SAndroid Build Coastguard Worker buf[indx] = 0;
1689*6777b538SAndroid Build Coastguard Worker base = 0;
1690*6777b538SAndroid Build Coastguard Worker do {
1691*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPParseList(&buf[base], callback, userData);
1692*6777b538SAndroid Build Coastguard Worker base += res;
1693*6777b538SAndroid Build Coastguard Worker } while (res > 0);
1694*6777b538SAndroid Build Coastguard Worker
1695*6777b538SAndroid Build Coastguard Worker memmove(&buf[0], &buf[base], indx - base);
1696*6777b538SAndroid Build Coastguard Worker indx -= base;
1697*6777b538SAndroid Build Coastguard Worker } while (len != 0);
1698*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCloseConnection(ctxt);
1699*6777b538SAndroid Build Coastguard Worker return(0);
1700*6777b538SAndroid Build Coastguard Worker }
1701*6777b538SAndroid Build Coastguard Worker
1702*6777b538SAndroid Build Coastguard Worker /**
1703*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPGetSocket:
1704*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1705*6777b538SAndroid Build Coastguard Worker * @filename: the file to retrieve (or NULL if path is in context).
1706*6777b538SAndroid Build Coastguard Worker *
1707*6777b538SAndroid Build Coastguard Worker * Initiate fetch of the given file from the server.
1708*6777b538SAndroid Build Coastguard Worker *
1709*6777b538SAndroid Build Coastguard Worker * Returns the socket for the data connection, or <0 in case of error
1710*6777b538SAndroid Build Coastguard Worker */
1711*6777b538SAndroid Build Coastguard Worker
1712*6777b538SAndroid Build Coastguard Worker
1713*6777b538SAndroid Build Coastguard Worker SOCKET
xmlNanoFTPGetSocket(void * ctx,const char * filename)1714*6777b538SAndroid Build Coastguard Worker xmlNanoFTPGetSocket(void *ctx, const char *filename) {
1715*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1716*6777b538SAndroid Build Coastguard Worker char buf[300];
1717*6777b538SAndroid Build Coastguard Worker int res, len;
1718*6777b538SAndroid Build Coastguard Worker if (ctx == NULL)
1719*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1720*6777b538SAndroid Build Coastguard Worker if ((filename == NULL) && (ctxt->path == NULL))
1721*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1722*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = xmlNanoFTPGetConnection(ctxt);
1723*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd == INVALID_SOCKET)
1724*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1725*6777b538SAndroid Build Coastguard Worker
1726*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "TYPE I\r\n");
1727*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1728*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1729*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1730*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1731*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1732*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1733*6777b538SAndroid Build Coastguard Worker }
1734*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPReadResponse(ctxt);
1735*6777b538SAndroid Build Coastguard Worker if (res != 2) {
1736*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1737*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1738*6777b538SAndroid Build Coastguard Worker }
1739*6777b538SAndroid Build Coastguard Worker if (filename == NULL)
1740*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "RETR %s\r\n", ctxt->path);
1741*6777b538SAndroid Build Coastguard Worker else
1742*6777b538SAndroid Build Coastguard Worker snprintf(buf, sizeof(buf), "RETR %s\r\n", filename);
1743*6777b538SAndroid Build Coastguard Worker buf[sizeof(buf) - 1] = 0;
1744*6777b538SAndroid Build Coastguard Worker len = strlen(buf);
1745*6777b538SAndroid Build Coastguard Worker res = send(ctxt->controlFd, SEND_ARG2_CAST buf, len, 0);
1746*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1747*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "send failed");
1748*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1749*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1750*6777b538SAndroid Build Coastguard Worker }
1751*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPReadResponse(ctxt);
1752*6777b538SAndroid Build Coastguard Worker if (res != 1) {
1753*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1754*6777b538SAndroid Build Coastguard Worker return INVALID_SOCKET;
1755*6777b538SAndroid Build Coastguard Worker }
1756*6777b538SAndroid Build Coastguard Worker return(ctxt->dataFd);
1757*6777b538SAndroid Build Coastguard Worker }
1758*6777b538SAndroid Build Coastguard Worker
1759*6777b538SAndroid Build Coastguard Worker /**
1760*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPGet:
1761*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1762*6777b538SAndroid Build Coastguard Worker * @callback: the user callback
1763*6777b538SAndroid Build Coastguard Worker * @userData: the user callback data
1764*6777b538SAndroid Build Coastguard Worker * @filename: the file to retrieve
1765*6777b538SAndroid Build Coastguard Worker *
1766*6777b538SAndroid Build Coastguard Worker * Fetch the given file from the server. All data are passed back
1767*6777b538SAndroid Build Coastguard Worker * in the callbacks. The last callback has a size of 0 block.
1768*6777b538SAndroid Build Coastguard Worker *
1769*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
1770*6777b538SAndroid Build Coastguard Worker */
1771*6777b538SAndroid Build Coastguard Worker
1772*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPGet(void * ctx,ftpDataCallback callback,void * userData,const char * filename)1773*6777b538SAndroid Build Coastguard Worker xmlNanoFTPGet(void *ctx, ftpDataCallback callback, void *userData,
1774*6777b538SAndroid Build Coastguard Worker const char *filename) {
1775*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1776*6777b538SAndroid Build Coastguard Worker char buf[4096];
1777*6777b538SAndroid Build Coastguard Worker int len = 0, res;
1778*6777b538SAndroid Build Coastguard Worker fd_set rfd;
1779*6777b538SAndroid Build Coastguard Worker struct timeval tv;
1780*6777b538SAndroid Build Coastguard Worker
1781*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return(-1);
1782*6777b538SAndroid Build Coastguard Worker if ((filename == NULL) && (ctxt->path == NULL))
1783*6777b538SAndroid Build Coastguard Worker return(-1);
1784*6777b538SAndroid Build Coastguard Worker if (callback == NULL)
1785*6777b538SAndroid Build Coastguard Worker return(-1);
1786*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPGetSocket(ctxt, filename) == INVALID_SOCKET)
1787*6777b538SAndroid Build Coastguard Worker return(-1);
1788*6777b538SAndroid Build Coastguard Worker
1789*6777b538SAndroid Build Coastguard Worker do {
1790*6777b538SAndroid Build Coastguard Worker tv.tv_sec = 1;
1791*6777b538SAndroid Build Coastguard Worker tv.tv_usec = 0;
1792*6777b538SAndroid Build Coastguard Worker FD_ZERO(&rfd);
1793*6777b538SAndroid Build Coastguard Worker FD_SET(ctxt->dataFd, &rfd);
1794*6777b538SAndroid Build Coastguard Worker res = select(ctxt->dataFd + 1, &rfd, NULL, NULL, &tv);
1795*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1796*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1797*6777b538SAndroid Build Coastguard Worker return(-1);
1798*6777b538SAndroid Build Coastguard Worker }
1799*6777b538SAndroid Build Coastguard Worker if (res == 0) {
1800*6777b538SAndroid Build Coastguard Worker res = xmlNanoFTPCheckResponse(ctxt);
1801*6777b538SAndroid Build Coastguard Worker if (res < 0) {
1802*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1803*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = INVALID_SOCKET;
1804*6777b538SAndroid Build Coastguard Worker return(-1);
1805*6777b538SAndroid Build Coastguard Worker }
1806*6777b538SAndroid Build Coastguard Worker if (res == 2) {
1807*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1808*6777b538SAndroid Build Coastguard Worker return(0);
1809*6777b538SAndroid Build Coastguard Worker }
1810*6777b538SAndroid Build Coastguard Worker
1811*6777b538SAndroid Build Coastguard Worker continue;
1812*6777b538SAndroid Build Coastguard Worker }
1813*6777b538SAndroid Build Coastguard Worker if ((len = recv(ctxt->dataFd, buf, sizeof(buf), 0)) < 0) {
1814*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
1815*6777b538SAndroid Build Coastguard Worker callback(userData, buf, len);
1816*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd); ctxt->dataFd = INVALID_SOCKET;
1817*6777b538SAndroid Build Coastguard Worker return(-1);
1818*6777b538SAndroid Build Coastguard Worker }
1819*6777b538SAndroid Build Coastguard Worker callback(userData, buf, len);
1820*6777b538SAndroid Build Coastguard Worker } while (len != 0);
1821*6777b538SAndroid Build Coastguard Worker
1822*6777b538SAndroid Build Coastguard Worker return(xmlNanoFTPCloseConnection(ctxt));
1823*6777b538SAndroid Build Coastguard Worker }
1824*6777b538SAndroid Build Coastguard Worker
1825*6777b538SAndroid Build Coastguard Worker /**
1826*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPRead:
1827*6777b538SAndroid Build Coastguard Worker * @ctx: the FTP context
1828*6777b538SAndroid Build Coastguard Worker * @dest: a buffer
1829*6777b538SAndroid Build Coastguard Worker * @len: the buffer length
1830*6777b538SAndroid Build Coastguard Worker *
1831*6777b538SAndroid Build Coastguard Worker * This function tries to read @len bytes from the existing FTP connection
1832*6777b538SAndroid Build Coastguard Worker * and saves them in @dest. This is a blocking call.
1833*6777b538SAndroid Build Coastguard Worker *
1834*6777b538SAndroid Build Coastguard Worker * Returns the number of byte read. 0 is an indication of an end of connection.
1835*6777b538SAndroid Build Coastguard Worker * -1 indicates a parameter error.
1836*6777b538SAndroid Build Coastguard Worker */
1837*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPRead(void * ctx,void * dest,int len)1838*6777b538SAndroid Build Coastguard Worker xmlNanoFTPRead(void *ctx, void *dest, int len) {
1839*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1840*6777b538SAndroid Build Coastguard Worker
1841*6777b538SAndroid Build Coastguard Worker if (ctx == NULL) return(-1);
1842*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd == INVALID_SOCKET) return(0);
1843*6777b538SAndroid Build Coastguard Worker if (dest == NULL) return(-1);
1844*6777b538SAndroid Build Coastguard Worker if (len <= 0) return(0);
1845*6777b538SAndroid Build Coastguard Worker
1846*6777b538SAndroid Build Coastguard Worker len = recv(ctxt->dataFd, dest, len, 0);
1847*6777b538SAndroid Build Coastguard Worker if (len <= 0) {
1848*6777b538SAndroid Build Coastguard Worker if (len < 0)
1849*6777b538SAndroid Build Coastguard Worker __xmlIOErr(XML_FROM_FTP, 0, "recv failed");
1850*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCloseConnection(ctxt);
1851*6777b538SAndroid Build Coastguard Worker }
1852*6777b538SAndroid Build Coastguard Worker return(len);
1853*6777b538SAndroid Build Coastguard Worker }
1854*6777b538SAndroid Build Coastguard Worker
1855*6777b538SAndroid Build Coastguard Worker /**
1856*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPOpen:
1857*6777b538SAndroid Build Coastguard Worker * @URL: the URL to the resource
1858*6777b538SAndroid Build Coastguard Worker *
1859*6777b538SAndroid Build Coastguard Worker * Start to fetch the given ftp:// resource
1860*6777b538SAndroid Build Coastguard Worker *
1861*6777b538SAndroid Build Coastguard Worker * Returns an FTP context, or NULL
1862*6777b538SAndroid Build Coastguard Worker */
1863*6777b538SAndroid Build Coastguard Worker
1864*6777b538SAndroid Build Coastguard Worker void*
xmlNanoFTPOpen(const char * URL)1865*6777b538SAndroid Build Coastguard Worker xmlNanoFTPOpen(const char *URL) {
1866*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt;
1867*6777b538SAndroid Build Coastguard Worker SOCKET sock;
1868*6777b538SAndroid Build Coastguard Worker
1869*6777b538SAndroid Build Coastguard Worker xmlNanoFTPInit();
1870*6777b538SAndroid Build Coastguard Worker if (URL == NULL) return(NULL);
1871*6777b538SAndroid Build Coastguard Worker if (strncmp("ftp://", URL, 6)) return(NULL);
1872*6777b538SAndroid Build Coastguard Worker
1873*6777b538SAndroid Build Coastguard Worker ctxt = (xmlNanoFTPCtxtPtr) xmlNanoFTPNewCtxt(URL);
1874*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return(NULL);
1875*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPConnect(ctxt) < 0) {
1876*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(ctxt);
1877*6777b538SAndroid Build Coastguard Worker return(NULL);
1878*6777b538SAndroid Build Coastguard Worker }
1879*6777b538SAndroid Build Coastguard Worker sock = xmlNanoFTPGetSocket(ctxt, ctxt->path);
1880*6777b538SAndroid Build Coastguard Worker if (sock == INVALID_SOCKET) {
1881*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(ctxt);
1882*6777b538SAndroid Build Coastguard Worker return(NULL);
1883*6777b538SAndroid Build Coastguard Worker }
1884*6777b538SAndroid Build Coastguard Worker return(ctxt);
1885*6777b538SAndroid Build Coastguard Worker }
1886*6777b538SAndroid Build Coastguard Worker
1887*6777b538SAndroid Build Coastguard Worker /**
1888*6777b538SAndroid Build Coastguard Worker * xmlNanoFTPClose:
1889*6777b538SAndroid Build Coastguard Worker * @ctx: an FTP context
1890*6777b538SAndroid Build Coastguard Worker *
1891*6777b538SAndroid Build Coastguard Worker * Close the connection and both control and transport
1892*6777b538SAndroid Build Coastguard Worker *
1893*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error, 0 otherwise
1894*6777b538SAndroid Build Coastguard Worker */
1895*6777b538SAndroid Build Coastguard Worker
1896*6777b538SAndroid Build Coastguard Worker int
xmlNanoFTPClose(void * ctx)1897*6777b538SAndroid Build Coastguard Worker xmlNanoFTPClose(void *ctx) {
1898*6777b538SAndroid Build Coastguard Worker xmlNanoFTPCtxtPtr ctxt = (xmlNanoFTPCtxtPtr) ctx;
1899*6777b538SAndroid Build Coastguard Worker
1900*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
1901*6777b538SAndroid Build Coastguard Worker return(-1);
1902*6777b538SAndroid Build Coastguard Worker
1903*6777b538SAndroid Build Coastguard Worker if (ctxt->dataFd != INVALID_SOCKET) {
1904*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->dataFd);
1905*6777b538SAndroid Build Coastguard Worker ctxt->dataFd = INVALID_SOCKET;
1906*6777b538SAndroid Build Coastguard Worker }
1907*6777b538SAndroid Build Coastguard Worker if (ctxt->controlFd != INVALID_SOCKET) {
1908*6777b538SAndroid Build Coastguard Worker xmlNanoFTPQuit(ctxt);
1909*6777b538SAndroid Build Coastguard Worker closesocket(ctxt->controlFd);
1910*6777b538SAndroid Build Coastguard Worker ctxt->controlFd = INVALID_SOCKET;
1911*6777b538SAndroid Build Coastguard Worker }
1912*6777b538SAndroid Build Coastguard Worker xmlNanoFTPFreeCtxt(ctxt);
1913*6777b538SAndroid Build Coastguard Worker return(0);
1914*6777b538SAndroid Build Coastguard Worker }
1915*6777b538SAndroid Build Coastguard Worker
1916*6777b538SAndroid Build Coastguard Worker #ifdef STANDALONE
1917*6777b538SAndroid Build Coastguard Worker /************************************************************************
1918*6777b538SAndroid Build Coastguard Worker * *
1919*6777b538SAndroid Build Coastguard Worker * Basic test in Standalone mode *
1920*6777b538SAndroid Build Coastguard Worker * *
1921*6777b538SAndroid Build Coastguard Worker ************************************************************************/
1922*6777b538SAndroid Build Coastguard Worker static
ftpList(void * userData,const char * filename,const char * attrib,const char * owner,const char * group,unsigned long size,int links,int year,const char * month,int day,int hour,int minute)1923*6777b538SAndroid Build Coastguard Worker void ftpList(void *userData, const char *filename, const char* attrib,
1924*6777b538SAndroid Build Coastguard Worker const char *owner, const char *group, unsigned long size, int links,
1925*6777b538SAndroid Build Coastguard Worker int year, const char *month, int day, int hour, int minute) {
1926*6777b538SAndroid Build Coastguard Worker fprintf(stderr,
1927*6777b538SAndroid Build Coastguard Worker "%s %s %s %ld %s\n", attrib, owner, group, size, filename);
1928*6777b538SAndroid Build Coastguard Worker }
1929*6777b538SAndroid Build Coastguard Worker static
ftpData(void * userData,const char * data,int len)1930*6777b538SAndroid Build Coastguard Worker void ftpData(void *userData, const char *data, int len) {
1931*6777b538SAndroid Build Coastguard Worker if (userData == NULL) return;
1932*6777b538SAndroid Build Coastguard Worker if (len <= 0) {
1933*6777b538SAndroid Build Coastguard Worker fclose((FILE*)userData);
1934*6777b538SAndroid Build Coastguard Worker return;
1935*6777b538SAndroid Build Coastguard Worker }
1936*6777b538SAndroid Build Coastguard Worker fwrite(data, len, 1, (FILE*)userData);
1937*6777b538SAndroid Build Coastguard Worker }
1938*6777b538SAndroid Build Coastguard Worker
main(int argc,char ** argv)1939*6777b538SAndroid Build Coastguard Worker int main(int argc, char **argv) {
1940*6777b538SAndroid Build Coastguard Worker void *ctxt;
1941*6777b538SAndroid Build Coastguard Worker FILE *output;
1942*6777b538SAndroid Build Coastguard Worker char *tstfile = NULL;
1943*6777b538SAndroid Build Coastguard Worker
1944*6777b538SAndroid Build Coastguard Worker xmlNanoFTPInit();
1945*6777b538SAndroid Build Coastguard Worker if (argc > 1) {
1946*6777b538SAndroid Build Coastguard Worker ctxt = xmlNanoFTPNewCtxt(argv[1]);
1947*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPConnect(ctxt) < 0) {
1948*6777b538SAndroid Build Coastguard Worker fprintf(stderr,
1949*6777b538SAndroid Build Coastguard Worker "Couldn't connect to %s\n", argv[1]);
1950*6777b538SAndroid Build Coastguard Worker exit(1);
1951*6777b538SAndroid Build Coastguard Worker }
1952*6777b538SAndroid Build Coastguard Worker if (argc > 2)
1953*6777b538SAndroid Build Coastguard Worker tstfile = argv[2];
1954*6777b538SAndroid Build Coastguard Worker } else
1955*6777b538SAndroid Build Coastguard Worker ctxt = xmlNanoFTPConnectTo("localhost", 0);
1956*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) {
1957*6777b538SAndroid Build Coastguard Worker fprintf(stderr,
1958*6777b538SAndroid Build Coastguard Worker "Couldn't connect to localhost\n");
1959*6777b538SAndroid Build Coastguard Worker exit(1);
1960*6777b538SAndroid Build Coastguard Worker }
1961*6777b538SAndroid Build Coastguard Worker xmlNanoFTPList(ctxt, ftpList, NULL, tstfile);
1962*6777b538SAndroid Build Coastguard Worker output = fopen("/tmp/tstdata", "w");
1963*6777b538SAndroid Build Coastguard Worker if (output != NULL) {
1964*6777b538SAndroid Build Coastguard Worker if (xmlNanoFTPGet(ctxt, ftpData, (void *) output, tstfile) < 0)
1965*6777b538SAndroid Build Coastguard Worker fprintf(stderr,
1966*6777b538SAndroid Build Coastguard Worker "Failed to get file\n");
1967*6777b538SAndroid Build Coastguard Worker
1968*6777b538SAndroid Build Coastguard Worker }
1969*6777b538SAndroid Build Coastguard Worker xmlNanoFTPClose(ctxt);
1970*6777b538SAndroid Build Coastguard Worker exit(0);
1971*6777b538SAndroid Build Coastguard Worker }
1972*6777b538SAndroid Build Coastguard Worker #endif /* STANDALONE */
1973*6777b538SAndroid Build Coastguard Worker #else /* !LIBXML_FTP_ENABLED */
1974*6777b538SAndroid Build Coastguard Worker #ifdef STANDALONE
1975*6777b538SAndroid Build Coastguard Worker #include <stdio.h>
main(int argc,char ** argv)1976*6777b538SAndroid Build Coastguard Worker int main(int argc, char **argv) {
1977*6777b538SAndroid Build Coastguard Worker fprintf(stderr,
1978*6777b538SAndroid Build Coastguard Worker "%s : FTP support not compiled in\n", argv[0]);
1979*6777b538SAndroid Build Coastguard Worker return(0);
1980*6777b538SAndroid Build Coastguard Worker }
1981*6777b538SAndroid Build Coastguard Worker #endif /* STANDALONE */
1982*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_FTP_ENABLED */
1983