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