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