1
|
1 /*****************************************************************************/
|
|
2 /* rfc959.c - General purpose routines for the FTP protocol (RFC 959) */
|
122
|
3 /* Copyright (C) 1998-2003 Brian Masney <masneyb@gftp.org> */
|
1
|
4 /* */
|
|
5 /* This program is free software; you can redistribute it and/or modify */
|
|
6 /* it under the terms of the GNU General Public License as published by */
|
|
7 /* the Free Software Foundation; either version 2 of the License, or */
|
|
8 /* (at your option) any later version. */
|
|
9 /* */
|
|
10 /* This program is distributed in the hope that it will be useful, */
|
|
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
13 /* GNU General Public License for more details. */
|
|
14 /* */
|
|
15 /* You should have received a copy of the GNU General Public License */
|
|
16 /* along with this program; if not, write to the Free Software */
|
|
17 /* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA */
|
|
18 /*****************************************************************************/
|
|
19
|
|
20 #include "gftp.h"
|
389
|
21 #include "ftpcommon.h"
|
|
22
|
33
|
23 static const char cvsid[] = "$Id$";
|
1
|
24
|
126
|
25 static gftp_textcomboedt_data gftp_proxy_type[] = {
|
136
|
26 {N_("none"), "", 0},
|
|
27 {N_("SITE command"), "USER %pu\nPASS %pp\nSITE %hh\nUSER %hu\nPASS %hp\n", 0},
|
|
28 {N_("user@host"), "USER %pu\nPASS %pp\nUSER %hu@%hh\nPASS %hp\n", 0},
|
|
29 {N_("user@host:port"), "USER %hu@%hh:%ho\nPASS %hp\n", 0},
|
|
30 {N_("AUTHENTICATE"), "USER %hu@%hh\nPASS %hp\nSITE AUTHENTICATE %pu\nSITE RESPONSE %pp\n", 0},
|
|
31 {N_("user@host port"), "USER %hu@%hh %ho\nPASS %hp\n", 0},
|
|
32 {N_("user@host NOAUTH"), "USER %hu@%hh\nPASS %hp\n", 0},
|
|
33 {N_("HTTP Proxy"), "http", 0},
|
|
34 {N_("Custom"), "", GFTP_TEXTCOMBOEDT_EDITABLE},
|
526
|
35 {NULL, NULL, 0}
|
126
|
36 };
|
|
37
|
122
|
38 static gftp_config_vars config_vars[] =
|
|
39 {
|
227
|
40 {"", N_("FTP"), gftp_option_type_notebook, NULL, NULL,
|
|
41 GFTP_CVARS_FLAGS_SHOW_BOOKMARK, NULL, GFTP_PORT_GTK, NULL},
|
122
|
42
|
|
43 {"email", N_("Email address:"),
|
227
|
44 gftp_option_type_text, "", NULL, GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
|
122
|
45 N_("This is the password that will be used whenever you log into a remote FTP server as anonymous"),
|
|
46 GFTP_PORT_ALL, NULL},
|
|
47 {"ftp_proxy_host", N_("Proxy hostname:"),
|
|
48 gftp_option_type_text, "", NULL, 0,
|
|
49 N_("Firewall hostname"), GFTP_PORT_ALL, NULL},
|
|
50 {"ftp_proxy_port", N_("Proxy port:"),
|
|
51 gftp_option_type_int, GINT_TO_POINTER(21), NULL, 0,
|
|
52 N_("Port to connect to on the firewall"), GFTP_PORT_ALL, NULL},
|
|
53 {"ftp_proxy_username", N_("Proxy username:"),
|
|
54 gftp_option_type_text, "", NULL, 0,
|
|
55 N_("Your firewall username"), GFTP_PORT_ALL, NULL},
|
|
56 {"ftp_proxy_password", N_("Proxy password:"),
|
|
57 gftp_option_type_hidetext, "", NULL, 0,
|
|
58 N_("Your firewall password"), GFTP_PORT_ALL, NULL},
|
|
59 {"ftp_proxy_account", N_("Proxy account:"),
|
|
60 gftp_option_type_text, "", NULL, 0,
|
|
61 N_("Your firewall account (optional)"), GFTP_PORT_ALL, NULL},
|
|
62
|
126
|
63 {"proxy_config", N_("Proxy server type:"),
|
|
64 gftp_option_type_textcomboedt, "", gftp_proxy_type, 0,
|
149
|
65 /* xgettext:no-c-format */
|
126
|
66 N_("This specifies how your proxy server expects us to log in. You can specify a 2 character replacement string prefixed by a % that will be replaced with the proper data. The first character can be either p for proxy or h for the host of the FTP server. The second character can be u (user), p (pass), h (host), o (port) or a (account). For example, to specify the proxy user, you can you type in %pu"),
|
|
67 GFTP_PORT_ALL, NULL},
|
|
68
|
643
|
69 {"ignore_pasv_address", N_("Ignore PASV address"),
|
|
70 gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL,
|
|
71 GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
|
|
72 N_("If this is enabled, then the remote FTP server's PASV IP address field will be ignored and the host's IP address will be used instead. This is often needed for routers giving their internal rather then their external IP address in a PASV reply."),
|
|
73 GFTP_PORT_ALL, NULL},
|
136
|
74 {"passive_transfer", N_("Passive file transfers"),
|
227
|
75 gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL,
|
|
76 GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
|
136
|
77 N_("If this is enabled, then the remote FTP server will open up a port for the data connection. If you are behind a firewall, you will need to enable this. Generally, it is a good idea to keep this enabled unless you are connecting to an older FTP server that doesn't support this. If this is disabled, then gFTP will open up a port on the client side and the remote server will attempt to connect to it."),
|
|
78 GFTP_PORT_ALL, NULL},
|
|
79 {"resolve_symlinks", N_("Resolve Remote Symlinks (LIST -L)"),
|
227
|
80 gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL,
|
|
81 GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
|
136
|
82 N_("The remote FTP server will attempt to resolve symlinks in the directory listings. Generally, this is a good idea to leave enabled. The only time you will want to disable this is if the remote FTP server doesn't support the -L option to LIST"),
|
|
83 GFTP_PORT_ALL, NULL},
|
|
84 {"ascii_transfers", N_("Transfer files in ASCII mode"),
|
227
|
85 gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL,
|
|
86 GFTP_CVARS_FLAGS_SHOW_BOOKMARK,
|
136
|
87 N_("If you are transfering a text file from Windows to UNIX box or vice versa, then you should enable this. Each system represents newlines differently for text files. If you are transfering from UNIX to UNIX, then it is safe to leave this off. If you are downloading binary data, you will want to disable this."),
|
|
88 GFTP_PORT_ALL, NULL},
|
|
89
|
122
|
90 {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL}
|
|
91 };
|
|
92
|
|
93
|
48
|
94 static int
|
292
|
95 rfc959_read_response (gftp_request * request, int disconnect_on_42x)
|
48
|
96 {
|
|
97 char tempstr[255], code[4];
|
58
|
98 rfc959_parms * parms;
|
|
99 ssize_t num_read;
|
48
|
100
|
84
|
101 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
102 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
48
|
103
|
|
104 *code = '\0';
|
|
105 if (request->last_ftp_response)
|
|
106 {
|
|
107 g_free (request->last_ftp_response);
|
|
108 request->last_ftp_response = NULL;
|
|
109 }
|
|
110
|
58
|
111 parms = request->protocol_data;
|
|
112
|
48
|
113 do
|
|
114 {
|
169
|
115 if ((num_read = gftp_get_line (request, &parms->datafd_rbuf, tempstr,
|
|
116 sizeof (tempstr), request->datafd)) <= 0)
|
48
|
117 break;
|
58
|
118
|
48
|
119 if (isdigit ((int) *tempstr) && isdigit ((int) *(tempstr + 1))
|
|
120 && isdigit ((int) *(tempstr + 2)))
|
|
121 {
|
|
122 strncpy (code, tempstr, 3);
|
|
123 code[3] = ' ';
|
|
124 }
|
186
|
125 request->logging_function (gftp_logging_recv, request,
|
48
|
126 "%s\n", tempstr);
|
|
127 }
|
|
128 while (strncmp (code, tempstr, 4) != 0);
|
|
129
|
58
|
130 if (num_read < 0)
|
84
|
131 return ((int) num_read);
|
48
|
132
|
105
|
133 request->last_ftp_response = g_strdup (tempstr);
|
48
|
134
|
|
135 if (request->last_ftp_response[0] == '4' &&
|
292
|
136 request->last_ftp_response[1] == '2' &&
|
|
137 disconnect_on_42x)
|
442
|
138 {
|
|
139 gftp_disconnect (request);
|
|
140 return (GFTP_ETIMEDOUT);
|
|
141 }
|
48
|
142
|
|
143 return (*request->last_ftp_response);
|
|
144 }
|
|
145
|
|
146
|
389
|
147 int
|
292
|
148 rfc959_send_command (gftp_request * request, const char *command,
|
820
|
149 int read_response, int dont_try_to_reconnect)
|
48
|
150 {
|
84
|
151 int ret;
|
|
152
|
|
153 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
154 g_return_val_if_fail (command != NULL, GFTP_EFATAL);
|
169
|
155 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
48
|
156
|
|
157 if (strncmp (command, "PASS", 4) == 0)
|
|
158 {
|
186
|
159 request->logging_function (gftp_logging_send, request,
|
48
|
160 "PASS xxxx\n");
|
|
161 }
|
|
162 else if (strncmp (command, "ACCT", 4) == 0)
|
|
163 {
|
186
|
164 request->logging_function (gftp_logging_send, request,
|
48
|
165 "ACCT xxxx\n");
|
|
166 }
|
|
167 else
|
|
168 {
|
186
|
169 request->logging_function (gftp_logging_send, request, "%s",
|
48
|
170 command);
|
|
171 }
|
|
172
|
389
|
173 if ((ret = request->write_function (request, command, strlen (command),
|
|
174 request->datafd)) < 0)
|
84
|
175 return (ret);
|
48
|
176
|
292
|
177 if (read_response)
|
820
|
178 {
|
|
179 ret = rfc959_read_response (request, 1);
|
|
180 if (ret == GFTP_ETIMEDOUT && !dont_try_to_reconnect)
|
|
181 {
|
|
182 ret = gftp_connect (request);
|
|
183 if (ret < 0)
|
|
184 return (ret);
|
|
185
|
|
186 return (rfc959_send_command (request, command, 1, 1));
|
|
187 }
|
|
188 else
|
|
189 return (ret);
|
|
190 }
|
292
|
191 else
|
|
192 return (0);
|
48
|
193 }
|
|
194
|
830
|
195 static int
|
|
196 rfc959_generate_and_send_command (gftp_request * request, const char *command,
|
|
197 const char *argument, int read_response,
|
|
198 int dont_try_to_reconnect)
|
|
199 {
|
|
200 char *tempstr, *utf8;
|
838
|
201 size_t destlen;
|
830
|
202 int resp;
|
|
203
|
|
204 if (argument != NULL)
|
|
205 {
|
838
|
206 utf8 = gftp_string_from_utf8 (request, argument, &destlen);
|
830
|
207 if (utf8 != NULL)
|
|
208 {
|
|
209 tempstr = g_strconcat (command, " ", utf8, "\r\n", NULL);
|
|
210 g_free (utf8);
|
|
211 }
|
|
212 tempstr = g_strconcat (command, " ", argument, "\r\n", NULL);
|
|
213 }
|
|
214 else
|
|
215 tempstr = g_strconcat (command, "\r\n", NULL);
|
|
216
|
|
217 resp = rfc959_send_command (request, tempstr, read_response,
|
|
218 dont_try_to_reconnect);
|
|
219 g_free (tempstr);
|
|
220 return (resp);
|
|
221 }
|
|
222
|
48
|
223
|
|
224 static char *
|
|
225 parse_ftp_proxy_string (gftp_request * request)
|
|
226 {
|
298
|
227 char *startpos, *endpos, *newstr, *newval, tempport[6], *proxy_config, *utf8,
|
126
|
228 savechar;
|
838
|
229 size_t len, destlen;
|
325
|
230 intptr_t tmp;
|
48
|
231
|
|
232 g_return_val_if_fail (request != NULL, NULL);
|
1
|
233
|
122
|
234 gftp_lookup_request_option (request, "proxy_config", &proxy_config);
|
126
|
235
|
|
236 newstr = g_malloc0 (1);
|
|
237 len = 0;
|
122
|
238 startpos = endpos = proxy_config;
|
48
|
239 while (*endpos != '\0')
|
|
240 {
|
|
241 if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'p')
|
|
242 {
|
|
243 switch (tolower ((int) *(endpos + 2)))
|
|
244 {
|
|
245 case 'u':
|
124
|
246 gftp_lookup_request_option (request, "ftp_proxy_username", &newval);
|
48
|
247 break;
|
|
248 case 'p':
|
124
|
249 gftp_lookup_request_option (request, "ftp_proxy_password", &newval);
|
48
|
250 break;
|
|
251 case 'h':
|
124
|
252 gftp_lookup_request_option (request, "ftp_proxy_host", &newval);
|
48
|
253 break;
|
|
254 case 'o':
|
124
|
255 gftp_lookup_request_option (request, "ftp_proxy_port", &tmp);
|
325
|
256 g_snprintf (tempport, sizeof (tempport), "%d", (int)tmp);
|
48
|
257 newval = tempport;
|
|
258 break;
|
|
259 case 'a':
|
124
|
260 gftp_lookup_request_option (request, "ftp_proxy_account", &newval);
|
48
|
261 break;
|
|
262 default:
|
|
263 endpos++;
|
|
264 continue;
|
|
265 }
|
|
266 }
|
|
267 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'h')
|
|
268 {
|
|
269 switch (tolower ((int) *(endpos + 2)))
|
|
270 {
|
|
271 case 'u':
|
|
272 newval = request->username;
|
|
273 break;
|
|
274 case 'p':
|
|
275 newval = request->password;
|
|
276 break;
|
|
277 case 'h':
|
|
278 newval = request->hostname;
|
|
279 break;
|
|
280 case 'o':
|
126
|
281 g_snprintf (tempport, sizeof (tempport), "%d", request->port);
|
48
|
282 newval = tempport;
|
|
283 break;
|
|
284 case 'a':
|
|
285 newval = request->account;
|
|
286 break;
|
|
287 default:
|
|
288 endpos++;
|
|
289 continue;
|
|
290 }
|
|
291 }
|
|
292 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'n')
|
|
293 {
|
126
|
294 savechar = *endpos;
|
|
295 *endpos = '\0';
|
|
296
|
|
297 len += strlen (startpos) + 2;
|
765
|
298 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1));
|
126
|
299 strcat (newstr, startpos);
|
|
300 strcat (newstr, "\r\n");
|
|
301
|
|
302 *endpos = savechar;
|
48
|
303 endpos += 2;
|
|
304 startpos = endpos;
|
|
305 continue;
|
|
306 }
|
|
307 else
|
|
308 {
|
|
309 endpos++;
|
|
310 continue;
|
|
311 }
|
1
|
312
|
126
|
313 savechar = *endpos;
|
48
|
314 *endpos = '\0';
|
126
|
315 len += strlen (startpos);
|
48
|
316 if (!newval)
|
126
|
317 {
|
765
|
318 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1));
|
126
|
319 strcat (newstr, startpos);
|
|
320 }
|
48
|
321 else
|
126
|
322 {
|
838
|
323 utf8 = gftp_string_from_utf8 (request, newval, &destlen);
|
298
|
324 if (utf8 != NULL)
|
|
325 len += strlen (utf8);
|
|
326 else
|
|
327 len += strlen (newval);
|
|
328
|
765
|
329 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1));
|
126
|
330 strcat (newstr, startpos);
|
298
|
331
|
|
332 if (utf8 != NULL)
|
|
333 {
|
|
334 strcat (newstr, utf8);
|
|
335 g_free (utf8);
|
|
336 }
|
|
337 else
|
|
338 strcat (newstr, newval);
|
126
|
339 }
|
|
340
|
|
341 *endpos = savechar;
|
48
|
342 endpos += 3;
|
|
343 startpos = endpos;
|
|
344 }
|
126
|
345
|
48
|
346 return (newstr);
|
|
347 }
|
|
348
|
|
349
|
|
350 static int
|
58
|
351 rfc959_getcwd (gftp_request * request)
|
|
352 {
|
830
|
353 char *pos, *dir, *utf8;
|
838
|
354 size_t destlen;
|
58
|
355 int ret;
|
|
356
|
820
|
357 ret = rfc959_send_command (request, "PWD\r\n", 1, 0);
|
58
|
358 if (ret < 0)
|
84
|
359 return (ret);
|
58
|
360 else if (ret != '2')
|
|
361 {
|
186
|
362 request->logging_function (gftp_logging_error, request,
|
411
|
363 _("Invalid response '%c' received from server.\n"),
|
|
364 ret);
|
58
|
365 gftp_disconnect (request);
|
84
|
366 return (GFTP_ERETRYABLE);
|
58
|
367 }
|
|
368
|
|
369 if ((pos = strchr (request->last_ftp_response, '"')) == NULL)
|
|
370 {
|
186
|
371 request->logging_function (gftp_logging_error, request,
|
411
|
372 _("Invalid response '%c' received from server.\n"),
|
|
373 ret);
|
58
|
374 gftp_disconnect (request);
|
84
|
375 return (GFTP_EFATAL);
|
58
|
376 }
|
|
377
|
|
378 dir = pos + 1;
|
|
379
|
|
380 if ((pos = strchr (dir, '"')) == NULL)
|
|
381 {
|
186
|
382 request->logging_function (gftp_logging_error, request,
|
411
|
383 _("Invalid response '%c' received from server.\n"),
|
|
384 ret);
|
58
|
385 gftp_disconnect (request);
|
84
|
386 return (GFTP_EFATAL);
|
58
|
387 }
|
|
388
|
|
389 *pos = '\0';
|
|
390
|
|
391 if (request->directory)
|
|
392 g_free (request->directory);
|
|
393
|
838
|
394 utf8 = gftp_string_to_utf8 (request, dir, &destlen);
|
830
|
395 if (utf8 != NULL)
|
|
396 request->directory = utf8;
|
|
397 else
|
|
398 request->directory = g_strdup (dir);
|
|
399
|
58
|
400 return (0);
|
|
401 }
|
|
402
|
|
403
|
|
404 static int
|
48
|
405 rfc959_chdir (gftp_request * request, const char *directory)
|
|
406 {
|
518
|
407 int ret;
|
48
|
408
|
84
|
409 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
410 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
48
|
411
|
|
412 if (strcmp (directory, "..") == 0)
|
820
|
413 ret = rfc959_send_command (request, "CDUP\r\n", 1, 0);
|
48
|
414 else
|
830
|
415 ret = rfc959_generate_and_send_command (request, "CWD", directory, 1, 0);
|
48
|
416
|
442
|
417 if (ret < 0)
|
|
418 return (ret);
|
|
419 else if (ret != '2')
|
84
|
420 return (GFTP_ERETRYABLE);
|
48
|
421
|
787
|
422 if ((ret = rfc959_getcwd (request)) < 0)
|
|
423 return (ret);
|
48
|
424
|
|
425 return (0);
|
1
|
426 }
|
|
427
|
|
428
|
|
429 static int
|
91
|
430 rfc959_syst (gftp_request * request)
|
|
431 {
|
811
|
432 int ret, disable_ls_options;
|
91
|
433 char *stpos, *endpos;
|
|
434
|
|
435 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
436 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
91
|
437
|
820
|
438 ret = rfc959_send_command (request, "SYST\r\n", 1, 0);
|
91
|
439
|
|
440 if (ret < 0)
|
|
441 return (ret);
|
|
442 else if (ret != '2')
|
|
443 return (GFTP_ERETRYABLE);
|
|
444
|
|
445 if ((stpos = strchr (request->last_ftp_response, ' ')) == NULL)
|
|
446 return (GFTP_ERETRYABLE);
|
|
447
|
114
|
448 stpos++;
|
|
449
|
91
|
450 if ((endpos = strchr (stpos, ' ')) == NULL)
|
|
451 return (GFTP_ERETRYABLE);
|
|
452
|
|
453 *endpos = '\0';
|
811
|
454 disable_ls_options = 0;
|
541
|
455
|
91
|
456 if (strcmp (stpos, "UNIX") == 0)
|
647
|
457 request->server_type = GFTP_DIRTYPE_UNIX;
|
107
|
458 else if (strcmp (stpos, "VMS") == 0)
|
757
|
459 {
|
811
|
460 disable_ls_options = 1;
|
757
|
461 request->server_type = GFTP_DIRTYPE_VMS;
|
|
462 }
|
367
|
463 else if (strcmp (stpos, "MVS") == 0 ||
|
|
464 strcmp (stpos, "OS/MVS") == 0)
|
358
|
465 request->server_type = GFTP_DIRTYPE_MVS;
|
305
|
466 else if (strcmp (stpos, "NETWARE") == 0)
|
|
467 request->server_type = GFTP_DIRTYPE_NOVELL;
|
136
|
468 else if (strcmp (stpos, "CRAY") == 0)
|
|
469 request->server_type = GFTP_DIRTYPE_CRAY;
|
91
|
470 else
|
122
|
471 request->server_type = GFTP_DIRTYPE_OTHER;
|
91
|
472
|
811
|
473 if (strcmp (stpos, "OS/400") == 0)
|
|
474 disable_ls_options = 1;
|
|
475
|
|
476 if (disable_ls_options)
|
|
477 {
|
|
478 gftp_set_request_option (request, "show_hidden_files",
|
|
479 GINT_TO_POINTER(0));
|
|
480 gftp_set_request_option (request, "resolve_symlinks", GINT_TO_POINTER(0));
|
|
481 }
|
|
482
|
91
|
483 return (0);
|
|
484 }
|
|
485
|
|
486
|
451
|
487 int
|
1
|
488 rfc959_connect (gftp_request * request)
|
|
489 {
|
830
|
490 char tempchar, *startpos, *endpos, *tempstr, *email, *proxy_hostname;
|
325
|
491 intptr_t ascii_transfers, proxy_port;
|
122
|
492 rfc959_parms * parms;
|
518
|
493 int ret, resp;
|
1
|
494
|
84
|
495 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
496 g_return_val_if_fail (request->hostname != NULL, GFTP_EFATAL);
|
1
|
497
|
169
|
498 if (request->datafd > 0)
|
58
|
499 return (0);
|
|
500
|
122
|
501 parms = request->protocol_data;
|
|
502
|
124
|
503 gftp_lookup_request_option (request, "ftp_proxy_host", &proxy_hostname);
|
|
504 gftp_lookup_request_option (request, "ftp_proxy_port", &proxy_port);
|
122
|
505
|
7
|
506 if (request->username == NULL || *request->username == '\0')
|
570
|
507 gftp_set_username (request, GFTP_ANONYMOUS_USER);
|
370
|
508
|
570
|
509 if (strcasecmp (request->username, GFTP_ANONYMOUS_USER) == 0 &&
|
370
|
510 (request->password == NULL || *request->password == '\0'))
|
7
|
511 {
|
370
|
512 gftp_lookup_request_option (request, "email", &email);
|
122
|
513 gftp_set_password (request, email);
|
7
|
514 }
|
122
|
515
|
765
|
516 if ((ret = gftp_connect_server (request, "ftp", proxy_hostname,
|
|
517 proxy_port)) < 0)
|
177
|
518 return (ret);
|
1
|
519
|
|
520 /* Get the banner */
|
292
|
521 if ((ret = rfc959_read_response (request, 1)) != '2')
|
1
|
522 {
|
|
523 gftp_disconnect (request);
|
567
|
524 if (ret < 0)
|
|
525 return (ret);
|
|
526 else
|
|
527 return (GFTP_ERETRYABLE);
|
1
|
528 }
|
|
529
|
389
|
530 if (parms->auth_tls_start != NULL)
|
|
531 {
|
|
532 if ((ret = parms->auth_tls_start (request)) < 0)
|
|
533 {
|
|
534 gftp_disconnect (request);
|
|
535 return (ret);
|
|
536 }
|
|
537 }
|
|
538
|
1
|
539 /* Login the proxy server if available */
|
|
540 if (request->use_proxy)
|
|
541 {
|
|
542 resp = '3';
|
|
543 startpos = endpos = tempstr = parse_ftp_proxy_string (request);
|
|
544 while ((resp == '3' || resp == '2') && *startpos != '\0')
|
|
545 {
|
|
546 if (*endpos == '\n' || *endpos == '\0')
|
|
547 {
|
|
548 tempchar = *(endpos + 1);
|
|
549 if (*endpos != '\0')
|
|
550 *(endpos + 1) = '\0';
|
820
|
551 if ((resp = rfc959_send_command (request, startpos, 1, 0)) < 0)
|
84
|
552 return (resp);
|
1
|
553 if (*endpos != '\0')
|
|
554 *(endpos + 1) = tempchar;
|
|
555 else
|
|
556 break;
|
|
557 startpos = endpos + 1;
|
|
558 }
|
|
559 endpos++;
|
|
560 }
|
|
561 g_free (tempstr);
|
|
562 }
|
|
563 else
|
|
564 {
|
830
|
565 resp = rfc959_generate_and_send_command (request, "USER",
|
|
566 request->username, 1, 0);
|
1
|
567 if (resp < 0)
|
443
|
568 return (resp);
|
286
|
569
|
1
|
570 if (resp == '3')
|
|
571 {
|
830
|
572 resp = rfc959_generate_and_send_command (request, "PASS",
|
|
573 request->password, 1, 0);
|
1
|
574 if (resp < 0)
|
443
|
575 return (resp);
|
1
|
576 }
|
286
|
577
|
570
|
578 if (resp == '3' && request->account != NULL)
|
1
|
579 {
|
830
|
580 resp = rfc959_generate_and_send_command (request, "ACCT",
|
|
581 request->account, 1, 0);
|
1
|
582 if (resp < 0)
|
443
|
583 return (resp);
|
1
|
584 }
|
|
585 }
|
|
586
|
|
587 if (resp != '2')
|
|
588 {
|
|
589 gftp_disconnect (request);
|
286
|
590
|
|
591 if (resp == '5')
|
|
592 return (GFTP_EFATAL);
|
|
593 else
|
|
594 return (GFTP_ERETRYABLE);
|
1
|
595 }
|
|
596
|
169
|
597 if ((ret = rfc959_syst (request)) < 0 && request->datafd < 0)
|
91
|
598 return (ret);
|
|
599
|
122
|
600 gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers);
|
|
601 if (ascii_transfers)
|
|
602 {
|
|
603 tempstr = "TYPE A\r\n";
|
|
604 parms->is_ascii_transfer = 1;
|
|
605 }
|
1
|
606 else
|
122
|
607 {
|
|
608 tempstr = "TYPE I\r\n";
|
|
609 parms->is_ascii_transfer = 0;
|
|
610 }
|
1
|
611
|
820
|
612 if ((ret = rfc959_send_command (request, tempstr, 1, 0)) < 0)
|
84
|
613 return (ret);
|
1
|
614
|
|
615 ret = -1;
|
|
616 if (request->directory != NULL && *request->directory != '\0')
|
|
617 {
|
|
618 ret = rfc959_chdir (request, request->directory);
|
169
|
619 if (request->datafd < 0)
|
84
|
620 return (ret);
|
1
|
621 }
|
|
622
|
|
623 if (ret != 0)
|
|
624 {
|
84
|
625 if ((ret = rfc959_getcwd (request)) < 0)
|
|
626 return (ret);
|
1
|
627 }
|
|
628
|
169
|
629 if (request->datafd < 0)
|
84
|
630 return (GFTP_EFATAL);
|
1
|
631
|
|
632 return (0);
|
|
633 }
|
|
634
|
|
635
|
|
636 static void
|
816
|
637 rfc959_close_data_connection (gftp_request * request)
|
1
|
638 {
|
169
|
639 rfc959_parms * parms;
|
|
640
|
1
|
641 g_return_if_fail (request != NULL);
|
|
642
|
169
|
643 parms = request->protocol_data;
|
816
|
644 if (parms->data_connection != -1)
|
|
645 {
|
|
646 close (parms->data_connection);
|
|
647 parms->data_connection = -1;
|
|
648 }
|
|
649 }
|
|
650
|
|
651
|
|
652 static void
|
|
653 rfc959_disconnect (gftp_request * request)
|
|
654 {
|
|
655 g_return_if_fail (request != NULL);
|
169
|
656
|
818
|
657 rfc959_close_data_connection (request);
|
169
|
658 if (request->datafd > 0)
|
1
|
659 {
|
186
|
660 request->logging_function (gftp_logging_misc, request,
|
1
|
661 _("Disconnecting from site %s\n"),
|
|
662 request->hostname);
|
169
|
663 close (request->datafd);
|
|
664 request->datafd = -1;
|
|
665 }
|
1
|
666 }
|
|
667
|
|
668
|
48
|
669 static int
|
146
|
670 rfc959_ipv4_data_connection_new (gftp_request * request)
|
48
|
671 {
|
|
672 struct sockaddr_in data_addr;
|
643
|
673 intptr_t ignore_pasv_address;
|
518
|
674 char *pos, *pos1, *command;
|
325
|
675 intptr_t passive_transfer;
|
169
|
676 rfc959_parms * parms;
|
195
|
677 socklen_t data_addr_len;
|
48
|
678 unsigned int temp[6];
|
|
679 unsigned char ad[6];
|
518
|
680 int i, resp;
|
48
|
681
|
169
|
682 parms = request->protocol_data;
|
|
683
|
820
|
684 parms->data_connection = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
685 if (parms->data_connection == -1)
|
48
|
686 {
|
186
|
687 request->logging_function (gftp_logging_error, request,
|
313
|
688 _("Failed to create a IPv4 socket: %s\n"),
|
48
|
689 g_strerror (errno));
|
|
690 gftp_disconnect (request);
|
84
|
691 return (GFTP_ERETRYABLE);
|
48
|
692 }
|
|
693
|
182
|
694 if (fcntl (parms->data_connection, F_SETFD, 1) == -1)
|
|
695 {
|
186
|
696 request->logging_function (gftp_logging_error, request,
|
182
|
697 _("Error: Cannot set close on exec flag: %s\n"),
|
|
698 g_strerror (errno));
|
|
699
|
|
700 return (GFTP_ERETRYABLE);
|
|
701 }
|
|
702
|
48
|
703 data_addr_len = sizeof (data_addr);
|
|
704 memset (&data_addr, 0, data_addr_len);
|
|
705 data_addr.sin_family = AF_INET;
|
|
706
|
122
|
707 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
708 if (passive_transfer)
|
48
|
709 {
|
820
|
710 resp = rfc959_send_command (request, "PASV\r\n", 1, 1);
|
443
|
711 if (resp < 0)
|
|
712 return (resp);
|
|
713 else if (resp != '2')
|
48
|
714 {
|
443
|
715 gftp_set_request_option (request, "passive_transfer",
|
|
716 GINT_TO_POINTER(0));
|
146
|
717 return (rfc959_ipv4_data_connection_new (request));
|
48
|
718 }
|
58
|
719
|
48
|
720 pos = request->last_ftp_response + 4;
|
|
721 while (!isdigit ((int) *pos) && *pos != '\0')
|
|
722 pos++;
|
58
|
723
|
48
|
724 if (*pos == '\0')
|
|
725 {
|
186
|
726 request->logging_function (gftp_logging_error, request,
|
58
|
727 _("Cannot find an IP address in PASV response '%s'\n"),
|
|
728 request->last_ftp_response);
|
48
|
729 gftp_disconnect (request);
|
84
|
730 return (GFTP_EFATAL);
|
48
|
731 }
|
58
|
732
|
48
|
733 if (sscanf (pos, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2],
|
|
734 &temp[3], &temp[4], &temp[5]) != 6)
|
|
735 {
|
186
|
736 request->logging_function (gftp_logging_error, request,
|
58
|
737 _("Cannot find an IP address in PASV response '%s'\n"),
|
|
738 request->last_ftp_response);
|
48
|
739 gftp_disconnect (request);
|
84
|
740 return (GFTP_EFATAL);
|
48
|
741 }
|
58
|
742
|
48
|
743 for (i = 0; i < 6; i++)
|
|
744 ad[i] = (unsigned char) (temp[i] & 0xff);
|
|
745
|
|
746 memcpy (&data_addr.sin_port, &ad[4], 2);
|
642
|
747
|
643
|
748 gftp_lookup_request_option (request, "ignore_pasv_address",
|
|
749 &ignore_pasv_address);
|
|
750 if (ignore_pasv_address)
|
642
|
751 {
|
|
752 #if defined (HAVE_GETADDRINFO)
|
|
753 memcpy (&data_addr.sin_addr,
|
|
754 &((struct sockaddr_in *) request->current_hostp->ai_addr)->sin_addr,
|
|
755 sizeof (data_addr.sin_addr));
|
|
756 #else
|
|
757 memcpy (&data_addr.sin_addr, request->hostp->h_addr_list[request->curhost],
|
|
758 request->hostp->h_length);
|
|
759 #endif
|
|
760
|
|
761 pos = (char *) &data_addr.sin_addr;
|
677
|
762 request->logging_function (gftp_logging_error, request,
|
642
|
763 _("Ignoring IP address in PASV response, connecting to %d.%d.%d.%d:%d\n"),
|
|
764 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff, pos[3] & 0xff,
|
|
765 ntohs (data_addr.sin_port));
|
|
766 }
|
|
767 else
|
|
768 memcpy (&data_addr.sin_addr, &ad[0], 4);
|
|
769
|
169
|
770 if (connect (parms->data_connection, (struct sockaddr *) &data_addr,
|
58
|
771 data_addr_len) == -1)
|
48
|
772 {
|
186
|
773 request->logging_function (gftp_logging_error, request,
|
48
|
774 _("Cannot create a data connection: %s\n"),
|
|
775 g_strerror (errno));
|
|
776 gftp_disconnect (request);
|
84
|
777 return (GFTP_ERETRYABLE);
|
48
|
778 }
|
|
779 }
|
|
780 else
|
|
781 {
|
169
|
782 if (getsockname (request->datafd, (struct sockaddr *) &data_addr,
|
58
|
783 &data_addr_len) == -1)
|
|
784 {
|
186
|
785 request->logging_function (gftp_logging_error, request,
|
58
|
786 _("Cannot get socket name: %s\n"),
|
|
787 g_strerror (errno));
|
|
788 gftp_disconnect (request);
|
84
|
789 return (GFTP_ERETRYABLE);
|
58
|
790 }
|
|
791
|
48
|
792 data_addr.sin_port = 0;
|
169
|
793 if (bind (parms->data_connection, (struct sockaddr *) &data_addr,
|
58
|
794 data_addr_len) == -1)
|
48
|
795 {
|
186
|
796 request->logging_function (gftp_logging_error, request,
|
48
|
797 _("Cannot bind a port: %s\n"),
|
|
798 g_strerror (errno));
|
|
799 gftp_disconnect (request);
|
84
|
800 return (GFTP_ERETRYABLE);
|
48
|
801 }
|
|
802
|
169
|
803 if (getsockname (parms->data_connection, (struct sockaddr *) &data_addr,
|
58
|
804 &data_addr_len) == -1)
|
|
805 {
|
186
|
806 request->logging_function (gftp_logging_error, request,
|
58
|
807 _("Cannot get socket name: %s\n"),
|
|
808 g_strerror (errno));
|
|
809 gftp_disconnect (request);
|
84
|
810 return (GFTP_ERETRYABLE);
|
58
|
811 }
|
|
812
|
169
|
813 if (listen (parms->data_connection, 1) == -1)
|
48
|
814 {
|
186
|
815 request->logging_function (gftp_logging_error, request,
|
48
|
816 _("Cannot listen on port %d: %s\n"),
|
|
817 ntohs (data_addr.sin_port),
|
|
818 g_strerror (errno));
|
|
819 gftp_disconnect (request);
|
84
|
820 return (GFTP_ERETRYABLE);
|
48
|
821 }
|
58
|
822
|
48
|
823 pos = (char *) &data_addr.sin_addr;
|
|
824 pos1 = (char *) &data_addr.sin_port;
|
|
825 command = g_strdup_printf ("PORT %u,%u,%u,%u,%u,%u\r\n",
|
|
826 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff,
|
|
827 pos[3] & 0xff, pos1[0] & 0xff,
|
|
828 pos1[1] & 0xff);
|
820
|
829 resp = rfc959_send_command (request, command, 1, 1);
|
48
|
830 g_free (command);
|
443
|
831
|
|
832 if (resp < 0)
|
|
833 return (resp);
|
|
834 else if (resp != '2')
|
48
|
835 {
|
411
|
836 request->logging_function (gftp_logging_error, request,
|
|
837 _("Invalid response '%c' received from server.\n"),
|
|
838 resp);
|
48
|
839 gftp_disconnect (request);
|
84
|
840 return (GFTP_ERETRYABLE);
|
48
|
841 }
|
|
842 }
|
|
843
|
|
844 return (0);
|
|
845 }
|
|
846
|
|
847
|
146
|
848 #ifdef HAVE_IPV6
|
|
849
|
|
850 static int
|
|
851 rfc959_ipv6_data_connection_new (gftp_request * request)
|
|
852 {
|
|
853 struct sockaddr_in6 data_addr;
|
518
|
854 char *pos, buf[64], *command;
|
463
|
855 intptr_t passive_transfer;
|
195
|
856 socklen_t data_addr_len;
|
169
|
857 rfc959_parms * parms;
|
146
|
858 unsigned int port;
|
518
|
859 int resp;
|
146
|
860
|
169
|
861 parms = request->protocol_data;
|
|
862 if ((parms->data_connection = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
146
|
863 {
|
186
|
864 request->logging_function (gftp_logging_error, request,
|
313
|
865 _("Failed to create a IPv6 socket: %s\n"),
|
146
|
866 g_strerror (errno));
|
|
867 gftp_disconnect (request);
|
|
868 return (GFTP_ERETRYABLE);
|
|
869 }
|
|
870
|
182
|
871 if (fcntl (parms->data_connection, F_SETFD, 1) == -1)
|
|
872 {
|
186
|
873 request->logging_function (gftp_logging_error, request,
|
182
|
874 _("Error: Cannot set close on exec flag: %s\n"),
|
|
875 g_strerror (errno));
|
|
876
|
|
877 return (GFTP_ERETRYABLE);
|
|
878 }
|
|
879
|
146
|
880 data_addr_len = sizeof (data_addr);
|
|
881 /* This condition shouldn't happen. We better check anyway... */
|
572
|
882 if (data_addr_len != request->current_hostp->ai_addrlen)
|
146
|
883 {
|
186
|
884 request->logging_function (gftp_logging_error, request,
|
146
|
885 _("Error: It doesn't look like we are connected via IPv6. Aborting connection.\n"));
|
|
886 gftp_disconnect (request);
|
|
887 return (GFTP_EFATAL);
|
|
888 }
|
|
889
|
|
890 memset (&data_addr, 0, data_addr_len);
|
|
891 data_addr.sin6_family = AF_INET6;
|
|
892
|
|
893 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
894 if (passive_transfer)
|
|
895 {
|
820
|
896 resp = rfc959_send_command (request, "EPSV\r\n", 1, 1);
|
443
|
897 if (resp < 0)
|
|
898 return (resp);
|
|
899 else if (resp != '2')
|
146
|
900 {
|
|
901 gftp_set_request_option (request, "passive_transfer",
|
|
902 GINT_TO_POINTER(0));
|
|
903 return (rfc959_ipv6_data_connection_new (request));
|
|
904 }
|
|
905
|
|
906 pos = request->last_ftp_response + 4;
|
|
907 while (*pos != '(' && *pos != '\0')
|
|
908 pos++;
|
|
909
|
572
|
910 if (*pos == '\0' || *(pos + 1) == '\0')
|
146
|
911 {
|
186
|
912 request->logging_function (gftp_logging_error, request,
|
146
|
913 _("Invalid EPSV response '%s'\n"),
|
|
914 request->last_ftp_response);
|
|
915 gftp_disconnect (request);
|
|
916 return (GFTP_EFATAL);
|
|
917 }
|
|
918
|
572
|
919 if (sscanf (pos + 1, "|||%u|", &port) != 1)
|
146
|
920 {
|
186
|
921 request->logging_function (gftp_logging_error, request,
|
146
|
922 _("Invalid EPSV response '%s'\n"),
|
|
923 request->last_ftp_response);
|
|
924 gftp_disconnect (request);
|
|
925 return (GFTP_EFATAL);
|
|
926 }
|
|
927
|
572
|
928 memcpy (&data_addr, request->current_hostp->ai_addr, data_addr_len);
|
146
|
929 data_addr.sin6_port = htons (port);
|
|
930
|
169
|
931 if (connect (parms->data_connection, (struct sockaddr *) &data_addr,
|
146
|
932 data_addr_len) == -1)
|
|
933 {
|
186
|
934 request->logging_function (gftp_logging_error, request,
|
146
|
935 _("Cannot create a data connection: %s\n"),
|
|
936 g_strerror (errno));
|
|
937 gftp_disconnect (request);
|
|
938 return (GFTP_ERETRYABLE);
|
|
939 }
|
|
940 }
|
|
941 else
|
|
942 {
|
572
|
943 memcpy (&data_addr, request->current_hostp->ai_addr, data_addr_len);
|
146
|
944 data_addr.sin6_port = 0;
|
|
945
|
169
|
946 if (bind (parms->data_connection, (struct sockaddr *) &data_addr,
|
146
|
947 data_addr_len) == -1)
|
|
948 {
|
186
|
949 request->logging_function (gftp_logging_error, request,
|
146
|
950 _("Cannot bind a port: %s\n"),
|
|
951 g_strerror (errno));
|
|
952 gftp_disconnect (request);
|
|
953 return (GFTP_ERETRYABLE);
|
|
954 }
|
|
955
|
169
|
956 if (getsockname (parms->data_connection, (struct sockaddr *) &data_addr,
|
146
|
957 &data_addr_len) == -1)
|
|
958 {
|
186
|
959 request->logging_function (gftp_logging_error, request,
|
146
|
960 _("Cannot get socket name: %s\n"),
|
|
961 g_strerror (errno));
|
|
962 gftp_disconnect (request);
|
|
963 return (GFTP_ERETRYABLE);
|
|
964 }
|
|
965
|
169
|
966 if (listen (parms->data_connection, 1) == -1)
|
146
|
967 {
|
186
|
968 request->logging_function (gftp_logging_error, request,
|
146
|
969 _("Cannot listen on port %d: %s\n"),
|
|
970 ntohs (data_addr.sin6_port),
|
|
971 g_strerror (errno));
|
|
972 gftp_disconnect (request);
|
|
973 return (GFTP_ERETRYABLE);
|
|
974 }
|
|
975
|
|
976 if (inet_ntop (AF_INET6, &data_addr.sin6_addr, buf, sizeof (buf)) == NULL)
|
|
977 {
|
186
|
978 request->logging_function (gftp_logging_error, request,
|
146
|
979 _("Cannot get address of local socket: %s\n"),
|
|
980 g_strerror (errno));
|
|
981 gftp_disconnect (request);
|
|
982 return (GFTP_ERETRYABLE);
|
|
983 }
|
|
984
|
|
985 command = g_strdup_printf ("EPRT |2|%s|%d|\n", buf,
|
|
986 ntohs (data_addr.sin6_port));
|
|
987
|
820
|
988 resp = rfc959_send_command (request, command, 1, 1);
|
146
|
989 g_free (command);
|
443
|
990
|
|
991 if (resp < 0)
|
|
992 return (resp);
|
|
993 else if (resp != '2')
|
146
|
994 {
|
|
995 gftp_disconnect (request);
|
|
996 return (GFTP_ERETRYABLE);
|
|
997 }
|
|
998 }
|
|
999
|
|
1000 return (0);
|
|
1001 }
|
|
1002
|
|
1003 #endif /* HAVE_IPV6 */
|
|
1004
|
|
1005
|
|
1006 static int
|
820
|
1007 rfc959_data_connection_new (gftp_request * request, int dont_try_to_reconnect)
|
146
|
1008 {
|
830
|
1009 int ret;
|
|
1010
|
146
|
1011 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1012 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
146
|
1013
|
|
1014 #ifdef HAVE_IPV6
|
547
|
1015 if (request->ai_family == AF_INET6)
|
820
|
1016 ret = rfc959_ipv6_data_connection_new (request);
|
146
|
1017 else
|
820
|
1018 ret = rfc959_ipv4_data_connection_new (request);
|
151
|
1019 #else
|
820
|
1020 ret = rfc959_ipv4_data_connection_new (request);
|
146
|
1021 #endif
|
820
|
1022
|
|
1023 if (ret == GFTP_ETIMEDOUT && !dont_try_to_reconnect)
|
|
1024 {
|
|
1025 ret = gftp_connect (request);
|
|
1026 if (ret < 0)
|
|
1027 return (ret);
|
|
1028
|
|
1029 return (rfc959_data_connection_new (request, 1));
|
|
1030 }
|
|
1031 else
|
|
1032 return (ret);
|
146
|
1033 }
|
|
1034
|
|
1035
|
48
|
1036 static int
|
|
1037 rfc959_accept_active_connection (gftp_request * request)
|
|
1038 {
|
325
|
1039 int infd, ret;
|
|
1040 intptr_t passive_transfer;
|
169
|
1041 rfc959_parms * parms;
|
146
|
1042 #ifdef HAVE_IPV6
|
339
|
1043 struct sockaddr_in6 cli_addr;
|
146
|
1044 #else
|
339
|
1045 struct sockaddr_in cli_addr;
|
146
|
1046 #endif
|
195
|
1047 socklen_t cli_addr_len;
|
48
|
1048
|
169
|
1049 parms = request->protocol_data;
|
|
1050
|
84
|
1051 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1052 g_return_val_if_fail (parms->data_connection > 0, GFTP_EFATAL);
|
122
|
1053
|
|
1054 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1055 g_return_val_if_fail (!passive_transfer, GFTP_EFATAL);
|
48
|
1056
|
|
1057 cli_addr_len = sizeof (cli_addr);
|
58
|
1058
|
169
|
1059 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 0)) < 0)
|
84
|
1060 return (ret);
|
58
|
1061
|
169
|
1062 if ((infd = accept (parms->data_connection, (struct sockaddr *) &cli_addr,
|
48
|
1063 &cli_addr_len)) == -1)
|
|
1064 {
|
186
|
1065 request->logging_function (gftp_logging_error, request,
|
48
|
1066 _("Cannot accept connection from server: %s\n"),
|
|
1067 g_strerror (errno));
|
|
1068 gftp_disconnect (request);
|
84
|
1069 return (GFTP_ERETRYABLE);
|
48
|
1070 }
|
|
1071
|
169
|
1072 close (parms->data_connection);
|
816
|
1073 parms->data_connection = infd;
|
48
|
1074
|
169
|
1075 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0)
|
84
|
1076 return (ret);
|
58
|
1077
|
48
|
1078 return (0);
|
|
1079 }
|
|
1080
|
|
1081
|
765
|
1082 static unsigned int
|
254
|
1083 rfc959_is_ascii_transfer (gftp_request * request, const char *filename)
|
122
|
1084 {
|
|
1085 gftp_config_list_vars * tmplistvar;
|
|
1086 gftp_file_extensions * tempext;
|
325
|
1087 intptr_t ascii_transfers;
|
122
|
1088 GList * templist;
|
518
|
1089 size_t stlen;
|
122
|
1090
|
|
1091 gftp_lookup_global_option ("ext", &tmplistvar);
|
254
|
1092 gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers);
|
122
|
1093
|
|
1094 stlen = strlen (filename);
|
|
1095 for (templist = tmplistvar->list; templist != NULL; templist = templist->next)
|
|
1096 {
|
|
1097 tempext = templist->data;
|
|
1098
|
|
1099 if (stlen >= tempext->stlen &&
|
|
1100 strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0)
|
|
1101 {
|
|
1102 if (toupper (*tempext->ascii_binary == 'A'))
|
254
|
1103 ascii_transfers = 1;
|
|
1104 else if (toupper (*tempext->ascii_binary == 'B'))
|
|
1105 ascii_transfers = 0;
|
122
|
1106 break;
|
|
1107 }
|
|
1108 }
|
|
1109
|
254
|
1110 return (ascii_transfers);
|
122
|
1111 }
|
|
1112
|
|
1113
|
309
|
1114 static int
|
122
|
1115 rfc959_set_data_type (gftp_request * request, const char *filename)
|
|
1116 {
|
765
|
1117 unsigned int new_ascii;
|
122
|
1118 rfc959_parms * parms;
|
|
1119 char *tempstr;
|
765
|
1120 int ret;
|
122
|
1121
|
309
|
1122 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
122
|
1123
|
|
1124 parms = request->protocol_data;
|
254
|
1125 new_ascii = rfc959_is_ascii_transfer (request, filename);
|
122
|
1126
|
169
|
1127 if (request->datafd > 0 && new_ascii != parms->is_ascii_transfer)
|
122
|
1128 {
|
|
1129 if (new_ascii)
|
|
1130 {
|
|
1131 tempstr = "TYPE A\r\n";
|
|
1132 parms->is_ascii_transfer = 1;
|
|
1133 }
|
|
1134 else
|
|
1135 {
|
|
1136 tempstr = "TYPE I\r\n";
|
254
|
1137 parms->is_ascii_transfer = 0;
|
122
|
1138 }
|
|
1139
|
820
|
1140 if ((ret = rfc959_send_command (request, tempstr, 1, 0)) < 0)
|
309
|
1141 return (ret);
|
122
|
1142 }
|
|
1143
|
309
|
1144 return (0);
|
122
|
1145 }
|
|
1146
|
|
1147
|
58
|
1148 static off_t
|
|
1149 rfc959_get_file (gftp_request * request, const char *filename, int fd,
|
1
|
1150 off_t startsize)
|
|
1151 {
|
518
|
1152 char *command, *tempstr;
|
325
|
1153 intptr_t passive_transfer;
|
169
|
1154 rfc959_parms * parms;
|
518
|
1155 int ret;
|
1
|
1156
|
84
|
1157 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1158 g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
|
169
|
1159 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1160
|
169
|
1161 parms = request->protocol_data;
|
58
|
1162 if (fd > 0)
|
169
|
1163 parms->data_connection = fd;
|
1
|
1164
|
309
|
1165 if ((ret = rfc959_set_data_type (request, filename)) < 0)
|
|
1166 return (ret);
|
122
|
1167
|
169
|
1168 if (parms->data_connection < 0 &&
|
820
|
1169 (ret = rfc959_data_connection_new (request, 0)) < 0)
|
1
|
1170 return (ret);
|
|
1171
|
169
|
1172 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0)
|
84
|
1173 return (ret);
|
1
|
1174
|
|
1175 if (startsize > 0)
|
|
1176 {
|
532
|
1177 command = g_strdup_printf ("REST " GFTP_OFF_T_PRINTF_MOD "\r\n",
|
|
1178 startsize);
|
820
|
1179 ret = rfc959_send_command (request, command, 1, 0);
|
1
|
1180 g_free (command);
|
|
1181
|
518
|
1182 if (ret < 0)
|
|
1183 return (ret);
|
|
1184 else if (ret != '3')
|
1
|
1185 {
|
816
|
1186 rfc959_close_data_connection (request);
|
84
|
1187 return (GFTP_ERETRYABLE);
|
1
|
1188 }
|
|
1189 }
|
|
1190
|
830
|
1191 ret = rfc959_generate_and_send_command (request, "RETR", filename, 1, 0);
|
442
|
1192 if (ret < 0)
|
|
1193 return (ret);
|
|
1194 else if (ret != '1')
|
58
|
1195 {
|
816
|
1196 rfc959_close_data_connection (request);
|
84
|
1197 return (GFTP_ERETRYABLE);
|
58
|
1198 }
|
1
|
1199
|
122
|
1200 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1201 if (!passive_transfer &&
|
1
|
1202 (ret = rfc959_accept_active_connection (request)) < 0)
|
|
1203 return (ret);
|
|
1204
|
|
1205 if ((tempstr = strrchr (request->last_ftp_response, '(')) == NULL)
|
|
1206 {
|
|
1207 tempstr = request->last_ftp_response + 4;
|
|
1208 while (!isdigit ((int) *tempstr) && *tempstr != '\0')
|
|
1209 tempstr++;
|
|
1210 }
|
|
1211 else
|
|
1212 tempstr++;
|
|
1213
|
244
|
1214 return (gftp_parse_file_size (tempstr) + startsize);
|
1
|
1215 }
|
|
1216
|
|
1217
|
|
1218 static int
|
58
|
1219 rfc959_put_file (gftp_request * request, const char *filename, int fd,
|
1
|
1220 off_t startsize, off_t totalsize)
|
|
1221 {
|
325
|
1222 intptr_t passive_transfer;
|
830
|
1223 char *command;
|
169
|
1224 rfc959_parms * parms;
|
426
|
1225 int ret;
|
1
|
1226
|
84
|
1227 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1228 g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
|
169
|
1229 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1230
|
169
|
1231 parms = request->protocol_data;
|
816
|
1232 if (fd > 0) /* FIXME */
|
169
|
1233 fd = parms->data_connection;
|
1
|
1234
|
309
|
1235 if ((ret = rfc959_set_data_type (request, filename)) < 0)
|
|
1236 return (ret);
|
122
|
1237
|
169
|
1238 if (parms->data_connection < 0 &&
|
820
|
1239 (ret = rfc959_data_connection_new (request, 0)) < 0)
|
1
|
1240 return (ret);
|
|
1241
|
169
|
1242 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0)
|
84
|
1243 return (ret);
|
1
|
1244
|
|
1245 if (startsize > 0)
|
|
1246 {
|
532
|
1247 command = g_strdup_printf ("REST " GFTP_OFF_T_PRINTF_MOD "\r\n",
|
|
1248 startsize);
|
820
|
1249 ret = rfc959_send_command (request, command, 1, 0);
|
1
|
1250 g_free (command);
|
518
|
1251 if (ret < 0)
|
|
1252 return (ret);
|
|
1253 else if (ret != '3')
|
1
|
1254 {
|
816
|
1255 rfc959_close_data_connection (request);
|
84
|
1256 return (GFTP_ERETRYABLE);
|
1
|
1257 }
|
|
1258 }
|
|
1259
|
830
|
1260 ret = rfc959_generate_and_send_command (request, "STOR", filename, 1, 0);
|
442
|
1261 if (ret < 0)
|
|
1262 return (ret);
|
|
1263 else if (ret != '1')
|
58
|
1264 {
|
816
|
1265 rfc959_close_data_connection (request);
|
84
|
1266 return (GFTP_ERETRYABLE);
|
58
|
1267 }
|
1
|
1268
|
122
|
1269 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1270 if (!passive_transfer &&
|
1
|
1271 (ret = rfc959_accept_active_connection (request)) < 0)
|
|
1272 return (ret);
|
|
1273
|
|
1274 return (0);
|
|
1275 }
|
|
1276
|
58
|
1277
|
765
|
1278 static off_t
|
1
|
1279 rfc959_transfer_file (gftp_request *fromreq, const char *fromfile,
|
|
1280 off_t fromsize, gftp_request *toreq,
|
|
1281 const char *tofile, off_t tosize)
|
|
1282 {
|
|
1283 char *tempstr, *pos, *endpos;
|
426
|
1284 rfc959_parms * parms;
|
84
|
1285 int ret;
|
1
|
1286
|
84
|
1287 g_return_val_if_fail (fromreq != NULL, GFTP_EFATAL);
|
|
1288 g_return_val_if_fail (fromfile != NULL, GFTP_EFATAL);
|
|
1289 g_return_val_if_fail (toreq != NULL, GFTP_EFATAL);
|
|
1290 g_return_val_if_fail (tofile != NULL, GFTP_EFATAL);
|
169
|
1291 g_return_val_if_fail (fromreq->datafd > 0, GFTP_EFATAL);
|
|
1292 g_return_val_if_fail (toreq->datafd > 0, GFTP_EFATAL);
|
1
|
1293
|
820
|
1294 if ((ret = rfc959_send_command (fromreq, "PASV\r\n", 1, 0)) < 0)
|
84
|
1295 return (ret);
|
442
|
1296 else if (ret != '2')
|
|
1297 return (GFTP_ERETRYABLE);
|
1
|
1298
|
|
1299 pos = fromreq->last_ftp_response + 4;
|
|
1300 while (!isdigit ((int) *pos) && *pos != '\0')
|
|
1301 pos++;
|
|
1302 if (*pos == '\0')
|
84
|
1303 return (GFTP_EFATAL);
|
1
|
1304
|
|
1305 endpos = pos;
|
|
1306 while (*endpos != ')' && *endpos != '\0')
|
|
1307 endpos++;
|
|
1308 if (*endpos == ')')
|
|
1309 *endpos = '\0';
|
|
1310
|
|
1311 tempstr = g_strconcat ("PORT ", pos, "\r\n", NULL);
|
820
|
1312 ret = rfc959_send_command (toreq, tempstr, 1, 0);
|
1
|
1313 g_free (tempstr);
|
|
1314
|
442
|
1315 if (ret < 0)
|
|
1316 return (ret);
|
|
1317 else if (ret != '2')
|
|
1318 return (GFTP_ERETRYABLE);
|
|
1319
|
830
|
1320 ret = rfc959_generate_and_send_command (fromreq, "RETR", fromfile, 0, 0);
|
443
|
1321 if (ret < 0)
|
|
1322 return (ret);
|
|
1323
|
830
|
1324 ret = rfc959_generate_and_send_command (toreq, "STOR", tofile, 0, 0);
|
443
|
1325 if (ret < 0)
|
|
1326 return (ret);
|
|
1327
|
292
|
1328 if ((ret = rfc959_read_response (fromreq, 1)) < 0)
|
84
|
1329 return (ret);
|
|
1330
|
292
|
1331 if ((ret = rfc959_read_response (toreq, 1)) < 0)
|
84
|
1332 return (ret);
|
1
|
1333
|
426
|
1334 parms = fromreq->protocol_data;
|
|
1335 parms->is_fxp_transfer = 1;
|
|
1336
|
|
1337 parms = toreq->protocol_data;
|
|
1338 parms->is_fxp_transfer = 1;
|
|
1339
|
1
|
1340 return (0);
|
|
1341 }
|
|
1342
|
|
1343
|
|
1344 static int
|
|
1345 rfc959_end_transfer (gftp_request * request)
|
|
1346 {
|
169
|
1347 rfc959_parms * parms;
|
84
|
1348 int ret;
|
|
1349
|
|
1350 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1351 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1352
|
169
|
1353 parms = request->protocol_data;
|
426
|
1354 parms->is_fxp_transfer = 0;
|
292
|
1355
|
816
|
1356 rfc959_close_data_connection (request);
|
84
|
1357
|
292
|
1358 ret = rfc959_read_response (request, 1);
|
84
|
1359
|
|
1360 if (ret < 0)
|
|
1361 return (ret);
|
|
1362 else if (ret == '2')
|
|
1363 return (0);
|
|
1364 else
|
|
1365 return (GFTP_ERETRYABLE);
|
1
|
1366 }
|
|
1367
|
|
1368
|
|
1369 static int
|
40
|
1370 rfc959_abort_transfer (gftp_request * request)
|
|
1371 {
|
|
1372 int ret;
|
|
1373
|
84
|
1374 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1375 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
40
|
1376
|
820
|
1377 if ((ret = rfc959_send_command (request, "ABOR\r\n", 0, 0)) < 0)
|
292
|
1378 return (ret);
|
|
1379
|
816
|
1380 rfc959_close_data_connection (request);
|
40
|
1381
|
169
|
1382 if (request->datafd > 0)
|
40
|
1383 {
|
292
|
1384 if ((ret = rfc959_read_response (request, 0)) < 0)
|
40
|
1385 gftp_disconnect (request);
|
|
1386 }
|
292
|
1387
|
40
|
1388 return (0);
|
|
1389 }
|
|
1390
|
|
1391
|
|
1392 static int
|
1
|
1393 rfc959_list_files (gftp_request * request)
|
|
1394 {
|
325
|
1395 intptr_t show_hidden_files, resolve_symlinks, passive_transfer;
|
1
|
1396 char *tempstr, parms[3];
|
518
|
1397 int ret;
|
1
|
1398
|
84
|
1399 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1400 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1401
|
820
|
1402 if ((ret = rfc959_data_connection_new (request, 0)) < 0)
|
1
|
1403 return (ret);
|
|
1404
|
122
|
1405 gftp_lookup_request_option (request, "show_hidden_files", &show_hidden_files);
|
|
1406 gftp_lookup_request_option (request, "resolve_symlinks", &resolve_symlinks);
|
|
1407 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1408
|
1
|
1409 *parms = '\0';
|
|
1410 strcat (parms, show_hidden_files ? "a" : "");
|
|
1411 strcat (parms, resolve_symlinks ? "L" : "");
|
|
1412 tempstr = g_strconcat ("LIST", *parms != '\0' ? " -" : "", parms, "\r\n",
|
|
1413 NULL);
|
|
1414
|
820
|
1415 ret = rfc959_send_command (request, tempstr, 1, 0);
|
1
|
1416 g_free (tempstr);
|
|
1417
|
442
|
1418 if (ret < 0)
|
|
1419 return (ret);
|
|
1420 else if (ret != '1')
|
411
|
1421 {
|
|
1422 request->logging_function (gftp_logging_error, request,
|
|
1423 _("Invalid response '%c' received from server.\n"),
|
|
1424 ret);
|
|
1425 return (GFTP_ERETRYABLE);
|
|
1426 }
|
1
|
1427
|
|
1428 ret = 0;
|
122
|
1429 if (!passive_transfer)
|
1
|
1430 ret = rfc959_accept_active_connection (request);
|
|
1431
|
|
1432 return (ret);
|
|
1433 }
|
|
1434
|
|
1435
|
122
|
1436 static ssize_t
|
|
1437 rfc959_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
1438 {
|
301
|
1439 ssize_t num_read, ret;
|
169
|
1440 rfc959_parms * parms;
|
299
|
1441 int i, j;
|
122
|
1442
|
169
|
1443 parms = request->protocol_data;
|
426
|
1444 if (parms->is_fxp_transfer)
|
|
1445 return (GFTP_ENOTRANS);
|
299
|
1446
|
390
|
1447 num_read = parms->data_conn_read (request, buf, size, parms->data_connection);
|
122
|
1448 if (num_read < 0)
|
|
1449 return (num_read);
|
|
1450
|
301
|
1451 ret = num_read;
|
299
|
1452 if (parms->is_ascii_transfer)
|
122
|
1453 {
|
|
1454 for (i = 0, j = 0; i < num_read; i++)
|
|
1455 {
|
|
1456 if (buf[i] != '\r')
|
|
1457 buf[j++] = buf[i];
|
|
1458 else
|
301
|
1459 ret--;
|
122
|
1460 }
|
|
1461 }
|
|
1462
|
301
|
1463 return (ret);
|
122
|
1464 }
|
|
1465
|
|
1466
|
|
1467 static ssize_t
|
|
1468 rfc959_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
1469 {
|
818
|
1470 ssize_t num_wrote, ret;
|
169
|
1471 rfc959_parms * parms;
|
818
|
1472 char *tempstr, *pos;
|
521
|
1473 size_t rsize, i, j;
|
122
|
1474
|
169
|
1475 parms = request->protocol_data;
|
|
1476
|
426
|
1477 if (parms->is_fxp_transfer)
|
|
1478 return (GFTP_ENOTRANS);
|
|
1479
|
299
|
1480 if (parms->is_ascii_transfer)
|
122
|
1481 {
|
818
|
1482 rsize = size;
|
|
1483 for (i = 1; i < size; i++)
|
122
|
1484 {
|
818
|
1485 if (buf[i] == '\n' && buf[i - 1] != '\r')
|
122
|
1486 rsize++;
|
|
1487 }
|
|
1488
|
|
1489 if (rsize != size)
|
|
1490 {
|
|
1491 tempstr = g_malloc (rsize);
|
|
1492
|
|
1493 for (i = 0, j = 0; i < size; i++)
|
|
1494 {
|
|
1495 if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
|
|
1496 tempstr[j++] = '\r';
|
|
1497 tempstr[j++] = buf[i];
|
|
1498 }
|
|
1499 }
|
|
1500 else
|
|
1501 tempstr = buf;
|
|
1502 }
|
|
1503 else
|
|
1504 {
|
|
1505 rsize = size;
|
|
1506 tempstr = buf;
|
|
1507 }
|
|
1508
|
818
|
1509 /* I need to ensure that the entire buffer has been transfered properly due
|
|
1510 to the ascii conversion that may occur.
|
|
1511 FIXME - the ascii conversion doesn't occur properly when the \n occurs
|
|
1512 at the beginning of the buffer. I need to remember the last character
|
|
1513 in the previous buffer */
|
|
1514
|
|
1515 ret = rsize;
|
|
1516 pos = tempstr;
|
|
1517 while (rsize > 0)
|
|
1518 {
|
|
1519 num_wrote = parms->data_conn_write (request, pos, rsize,
|
|
1520 parms->data_connection);
|
|
1521 if (num_wrote < 0)
|
|
1522 {
|
|
1523 ret = num_wrote;
|
|
1524 break;
|
|
1525 }
|
|
1526
|
|
1527 pos += num_wrote;
|
|
1528 rsize -= num_wrote;
|
|
1529 }
|
122
|
1530
|
|
1531 if (tempstr != buf)
|
|
1532 g_free (tempstr);
|
|
1533
|
818
|
1534 return (ret);
|
122
|
1535 }
|
|
1536
|
|
1537
|
485
|
1538 static ssize_t
|
|
1539 rfc959_get_next_dirlist_line (gftp_request * request, int fd,
|
|
1540 char *buf, size_t buflen)
|
|
1541 {
|
|
1542 ssize_t (*oldread_func) (gftp_request * request, void *ptr, size_t size,
|
|
1543 int fd);
|
|
1544 rfc959_parms * parms;
|
|
1545 ssize_t len;
|
|
1546
|
|
1547 parms = request->protocol_data;
|
|
1548
|
|
1549 oldread_func = request->read_function;
|
|
1550 request->read_function = parms->data_conn_read;
|
|
1551 len = gftp_get_line (request, &parms->dataconn_rbuf, buf, buflen, fd);
|
|
1552 request->read_function = oldread_func;
|
|
1553
|
|
1554 return (len);
|
|
1555 }
|
|
1556
|
1
|
1557 int
|
58
|
1558 rfc959_get_next_file (gftp_request * request, gftp_file * fle, int fd)
|
1
|
1559 {
|
58
|
1560 rfc959_parms * parms;
|
249
|
1561 char tempstr[1024];
|
516
|
1562 size_t stlen;
|
58
|
1563 ssize_t len;
|
1
|
1564
|
84
|
1565 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1566 g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
|
|
1567 g_return_val_if_fail (fd > 0, GFTP_EFATAL);
|
1
|
1568
|
|
1569 if (request->last_dir_entry)
|
|
1570 {
|
|
1571 g_free (request->last_dir_entry);
|
|
1572 request->last_dir_entry = NULL;
|
|
1573 }
|
58
|
1574
|
|
1575 parms = request->protocol_data;
|
|
1576
|
169
|
1577 if (fd == request->datafd)
|
|
1578 fd = parms->data_connection;
|
|
1579
|
1
|
1580 do
|
|
1581 {
|
485
|
1582 len = rfc959_get_next_dirlist_line (request, fd, tempstr,
|
|
1583 sizeof (tempstr));
|
389
|
1584 if (len <= 0)
|
1
|
1585 {
|
598
|
1586 gftp_file_destroy (fle, 0);
|
518
|
1587 return (len);
|
1
|
1588 }
|
|
1589
|
485
|
1590 if (gftp_parse_ls (request, tempstr, fle, fd) != 0)
|
1
|
1591 {
|
58
|
1592 if (strncmp (tempstr, "total", strlen ("total")) != 0 &&
|
|
1593 strncmp (tempstr, _("total"), strlen (_("total"))) != 0)
|
186
|
1594 request->logging_function (gftp_logging_error, request,
|
1
|
1595 _("Warning: Cannot parse listing %s\n"),
|
|
1596 tempstr);
|
598
|
1597 gftp_file_destroy (fle, 0);
|
1
|
1598 continue;
|
|
1599 }
|
|
1600 else
|
|
1601 break;
|
|
1602 }
|
|
1603 while (1);
|
|
1604
|
516
|
1605 stlen = strlen (tempstr);
|
1
|
1606 if (!request->cached)
|
|
1607 {
|
60
|
1608 request->last_dir_entry = g_strdup_printf ("%s\n", tempstr);
|
516
|
1609 request->last_dir_entry_len = stlen + 1;
|
1
|
1610 }
|
|
1611 return (len);
|
|
1612 }
|
|
1613
|
|
1614
|
|
1615 static off_t
|
|
1616 rfc959_get_file_size (gftp_request * request, const char *filename)
|
|
1617 {
|
|
1618 int ret;
|
|
1619
|
|
1620 g_return_val_if_fail (request != NULL, 0);
|
|
1621 g_return_val_if_fail (filename != NULL, 0);
|
169
|
1622 g_return_val_if_fail (request->datafd > 0, 0);
|
1
|
1623
|
830
|
1624 ret = rfc959_generate_and_send_command (request, "SIZE", filename, 1, 0);
|
1
|
1625 if (ret < 0)
|
84
|
1626 return (ret);
|
1
|
1627
|
|
1628 if (*request->last_ftp_response != '2')
|
|
1629 return (0);
|
830
|
1630
|
1
|
1631 return (strtol (request->last_ftp_response + 4, NULL, 10));
|
|
1632 }
|
|
1633
|
|
1634
|
|
1635 static int
|
|
1636 rfc959_rmdir (gftp_request * request, const char *directory)
|
|
1637 {
|
518
|
1638 int ret;
|
1
|
1639
|
84
|
1640 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1641 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
169
|
1642 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1643
|
830
|
1644 ret = rfc959_generate_and_send_command (request, "RMD", directory, 1, 0);
|
84
|
1645 if (ret < 0)
|
|
1646 return (ret);
|
|
1647 else if (ret == '2')
|
|
1648 return (0);
|
|
1649 else
|
|
1650 return (GFTP_ERETRYABLE);
|
1
|
1651 }
|
|
1652
|
|
1653
|
|
1654 static int
|
|
1655 rfc959_rmfile (gftp_request * request, const char *file)
|
|
1656 {
|
518
|
1657 int ret;
|
1
|
1658
|
84
|
1659 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1660 g_return_val_if_fail (file != NULL, GFTP_EFATAL);
|
169
|
1661 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1662
|
830
|
1663 ret = rfc959_generate_and_send_command (request, "DELE", file, 1, 0);
|
84
|
1664 if (ret < 0)
|
|
1665 return (ret);
|
|
1666 else if (ret == '2')
|
|
1667 return (0);
|
|
1668 else
|
|
1669 return (GFTP_ERETRYABLE);
|
1
|
1670 }
|
|
1671
|
|
1672
|
|
1673 static int
|
|
1674 rfc959_mkdir (gftp_request * request, const char *directory)
|
|
1675 {
|
518
|
1676 int ret;
|
1
|
1677
|
84
|
1678 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1679 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
169
|
1680 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1681
|
830
|
1682 ret = rfc959_generate_and_send_command (request, "MKD", directory, 1, 0);
|
84
|
1683 if (ret < 0)
|
|
1684 return (ret);
|
|
1685 else if (ret == '2')
|
|
1686 return (0);
|
|
1687 else
|
|
1688 return (GFTP_ERETRYABLE);
|
1
|
1689 }
|
|
1690
|
|
1691
|
|
1692 static int
|
|
1693 rfc959_rename (gftp_request * request, const char *oldname,
|
|
1694 const char *newname)
|
|
1695 {
|
518
|
1696 int ret;
|
1
|
1697
|
84
|
1698 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1699 g_return_val_if_fail (oldname != NULL, GFTP_EFATAL);
|
|
1700 g_return_val_if_fail (newname != NULL, GFTP_EFATAL);
|
169
|
1701 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1702
|
830
|
1703 ret = rfc959_generate_and_send_command (request, "RNFR", oldname, 1, 0);
|
84
|
1704 if (ret < 0)
|
|
1705 return (ret);
|
278
|
1706 else if (ret != '3')
|
84
|
1707 return (GFTP_ERETRYABLE);
|
1
|
1708
|
830
|
1709 ret = rfc959_generate_and_send_command (request, "RNTO", newname, 1, 0);
|
84
|
1710 if (ret < 0)
|
|
1711 return (ret);
|
|
1712 else if (ret == '2')
|
|
1713 return (0);
|
|
1714 else
|
|
1715 return (GFTP_ERETRYABLE);
|
1
|
1716 }
|
|
1717
|
|
1718
|
|
1719 static int
|
499
|
1720 rfc959_chmod (gftp_request * request, const char *file, mode_t mode)
|
1
|
1721 {
|
830
|
1722 char *tempstr, *utf8;
|
838
|
1723 size_t destlen;
|
518
|
1724 int ret;
|
1
|
1725
|
84
|
1726 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1727 g_return_val_if_fail (file != NULL, GFTP_EFATAL);
|
169
|
1728 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1729
|
838
|
1730 utf8 = gftp_string_from_utf8 (request, file, &destlen);
|
830
|
1731 if (utf8 != NULL)
|
|
1732 {
|
|
1733 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, utf8);
|
|
1734 g_free (utf8);
|
|
1735 }
|
|
1736 else
|
|
1737 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, file);
|
541
|
1738
|
820
|
1739 ret = rfc959_send_command (request, tempstr, 1, 0);
|
1
|
1740 g_free (tempstr);
|
84
|
1741
|
|
1742 if (ret < 0)
|
|
1743 return (ret);
|
|
1744 else if (ret == '2')
|
|
1745 return (0);
|
|
1746 else
|
|
1747 return (GFTP_ERETRYABLE);
|
1
|
1748 }
|
|
1749
|
|
1750
|
|
1751 static int
|
478
|
1752 rfc959_site (gftp_request * request, int specify_site, const char *command)
|
1
|
1753 {
|
830
|
1754 char *tempstr, *utf8;
|
838
|
1755 size_t destlen;
|
518
|
1756 int ret;
|
1
|
1757
|
84
|
1758 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1759 g_return_val_if_fail (command != NULL, GFTP_EFATAL);
|
169
|
1760 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1761
|
838
|
1762 utf8 = gftp_string_from_utf8 (request, command, &destlen);
|
830
|
1763 if (utf8 != NULL)
|
|
1764 {
|
|
1765 if (specify_site)
|
|
1766 tempstr = g_strconcat ("SITE ", utf8, "\r\n", NULL);
|
|
1767 else
|
|
1768 tempstr = g_strconcat (utf8, "\r\n", NULL);
|
|
1769
|
|
1770 g_free (utf8);
|
|
1771 }
|
478
|
1772 else
|
830
|
1773 {
|
|
1774 if (specify_site)
|
|
1775 tempstr = g_strconcat ("SITE ", command, "\r\n", NULL);
|
|
1776 else
|
|
1777 tempstr = g_strconcat (command, "\r\n", NULL);
|
|
1778 }
|
478
|
1779
|
820
|
1780 ret = rfc959_send_command (request, tempstr, 1, 0);
|
1
|
1781 g_free (tempstr);
|
84
|
1782
|
|
1783 if (ret < 0)
|
|
1784 return (ret);
|
|
1785 else if (ret == '2')
|
|
1786 return (0);
|
|
1787 else
|
|
1788 return (GFTP_ERETRYABLE);
|
58
|
1789 }
|
|
1790
|
|
1791
|
513
|
1792 static int
|
58
|
1793 rfc959_set_config_options (gftp_request * request)
|
|
1794 {
|
122
|
1795 char *proxy_config;
|
177
|
1796 int ret;
|
58
|
1797
|
122
|
1798 gftp_lookup_request_option (request, "proxy_config", &proxy_config);
|
|
1799 if (strcmp (proxy_config, "http") == 0)
|
58
|
1800 {
|
177
|
1801 if ((ret = gftp_protocols[GFTP_HTTP_NUM].init (request)) < 0)
|
|
1802 return (ret);
|
173
|
1803
|
122
|
1804 gftp_set_request_option (request, "proxy_config", "ftp");
|
58
|
1805 }
|
177
|
1806
|
|
1807 return (0);
|
122
|
1808 }
|
58
|
1809
|
|
1810
|
122
|
1811 void
|
|
1812 rfc959_register_module (void)
|
|
1813 {
|
|
1814 gftp_register_config_vars (config_vars);
|
1
|
1815 }
|
|
1816
|
|
1817
|
516
|
1818 static void
|
201
|
1819 rfc959_request_destroy (gftp_request * request)
|
|
1820 {
|
|
1821 rfc959_parms * parms;
|
|
1822
|
|
1823 parms = request->protocol_data;
|
|
1824
|
|
1825 if (parms->datafd_rbuf != NULL)
|
|
1826 gftp_free_getline_buffer (&parms->datafd_rbuf);
|
|
1827
|
|
1828 if (parms->dataconn_rbuf != NULL)
|
|
1829 gftp_free_getline_buffer (&parms->dataconn_rbuf);
|
|
1830 }
|
|
1831
|
|
1832
|
516
|
1833 static void
|
309
|
1834 rfc959_copy_param_options (gftp_request * dest_request,
|
|
1835 gftp_request * src_request)
|
|
1836 {
|
|
1837 rfc959_parms * dparms, * sparms;
|
|
1838
|
|
1839 dparms = dest_request->protocol_data;
|
|
1840 sparms = src_request->protocol_data;
|
|
1841
|
432
|
1842 dparms->data_connection = -1;
|
309
|
1843 dparms->is_ascii_transfer = sparms->is_ascii_transfer;
|
432
|
1844 dparms->is_fxp_transfer = sparms->is_fxp_transfer;
|
|
1845 dparms->auth_tls_start = sparms->auth_tls_start;
|
|
1846 dparms->data_conn_read = sparms->data_conn_read;
|
|
1847 dparms->data_conn_write = sparms->data_conn_write;
|
|
1848
|
|
1849 dest_request->read_function = src_request->read_function;
|
|
1850 dest_request->write_function = src_request->write_function;
|
309
|
1851 }
|
|
1852
|
|
1853
|
173
|
1854 int
|
48
|
1855 rfc959_init (gftp_request * request)
|
1
|
1856 {
|
169
|
1857 rfc959_parms * parms;
|
227
|
1858 struct hostent *hent;
|
|
1859 struct utsname unme;
|
|
1860 struct passwd *pw;
|
|
1861 char *tempstr;
|
169
|
1862
|
173
|
1863 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
1864
|
227
|
1865 gftp_lookup_global_option ("email", &tempstr);
|
|
1866 if (tempstr == NULL || *tempstr == '\0')
|
|
1867 {
|
|
1868 /* If there is no email address specified, then we'll just use the
|
|
1869 currentuser@currenthost */
|
|
1870 uname (&unme);
|
|
1871 pw = getpwuid (geteuid ());
|
|
1872 hent = gethostbyname (unme.nodename);
|
|
1873 if (strchr (unme.nodename, '.') == NULL && hent != NULL)
|
|
1874 tempstr = g_strconcat (pw->pw_name, "@", hent->h_name, NULL);
|
|
1875 else
|
|
1876 tempstr = g_strconcat (pw->pw_name, "@", unme.nodename, NULL);
|
|
1877 gftp_set_global_option ("email", tempstr);
|
|
1878 g_free (tempstr);
|
|
1879 }
|
|
1880
|
48
|
1881 request->protonum = GFTP_FTP_NUM;
|
|
1882 request->init = rfc959_init;
|
309
|
1883 request->copy_param_options = rfc959_copy_param_options;
|
201
|
1884 request->destroy = rfc959_request_destroy;
|
168
|
1885 request->read_function = gftp_fd_read;
|
|
1886 request->write_function = gftp_fd_write;
|
48
|
1887 request->connect = rfc959_connect;
|
168
|
1888 request->post_connect = NULL;
|
48
|
1889 request->disconnect = rfc959_disconnect;
|
|
1890 request->get_file = rfc959_get_file;
|
|
1891 request->put_file = rfc959_put_file;
|
|
1892 request->transfer_file = rfc959_transfer_file;
|
122
|
1893 request->get_next_file_chunk = rfc959_get_next_file_chunk;
|
|
1894 request->put_next_file_chunk = rfc959_put_next_file_chunk;
|
48
|
1895 request->end_transfer = rfc959_end_transfer;
|
|
1896 request->abort_transfer = rfc959_abort_transfer;
|
500
|
1897 request->stat_filename = NULL;
|
48
|
1898 request->list_files = rfc959_list_files;
|
|
1899 request->get_next_file = rfc959_get_next_file;
|
485
|
1900 request->get_next_dirlist_line = rfc959_get_next_dirlist_line;
|
48
|
1901 request->get_file_size = rfc959_get_file_size;
|
|
1902 request->chdir = rfc959_chdir;
|
|
1903 request->rmdir = rfc959_rmdir;
|
|
1904 request->rmfile = rfc959_rmfile;
|
|
1905 request->mkdir = rfc959_mkdir;
|
|
1906 request->rename = rfc959_rename;
|
|
1907 request->chmod = rfc959_chmod;
|
818
|
1908 request->set_file_time = NULL;
|
48
|
1909 request->site = rfc959_site;
|
|
1910 request->parse_url = NULL;
|
63
|
1911 request->swap_socks = NULL;
|
58
|
1912 request->set_config_options = rfc959_set_config_options;
|
48
|
1913 request->url_prefix = "ftp";
|
|
1914 request->need_hostport = 1;
|
650
|
1915 request->need_username = 1;
|
553
|
1916 request->need_password = 1;
|
48
|
1917 request->use_cache = 1;
|
|
1918 request->always_connected = 0;
|
832
|
1919 request->use_local_encoding = 0;
|
169
|
1920
|
58
|
1921 request->protocol_data = g_malloc0 (sizeof (rfc959_parms));
|
169
|
1922 parms = request->protocol_data;
|
|
1923 parms->data_connection = -1;
|
389
|
1924 parms->auth_tls_start = NULL;
|
390
|
1925 parms->data_conn_read = gftp_fd_read;
|
|
1926 parms->data_conn_write = gftp_fd_write;
|
169
|
1927
|
177
|
1928 return (gftp_set_config_options (request));
|
1
|
1929 }
|
|
1930
|