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);
|
858
|
1210
|
|
1211 if (ret == '5')
|
|
1212 return (GFTP_EFATAL);
|
|
1213 else
|
|
1214 return (GFTP_ERETRYABLE);
|
58
|
1215 }
|
1
|
1216
|
122
|
1217 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1218 if (!passive_transfer &&
|
1
|
1219 (ret = rfc959_accept_active_connection (request)) < 0)
|
|
1220 return (ret);
|
|
1221
|
|
1222 if ((tempstr = strrchr (request->last_ftp_response, '(')) == NULL)
|
|
1223 {
|
|
1224 tempstr = request->last_ftp_response + 4;
|
|
1225 while (!isdigit ((int) *tempstr) && *tempstr != '\0')
|
|
1226 tempstr++;
|
|
1227 }
|
|
1228 else
|
|
1229 tempstr++;
|
|
1230
|
244
|
1231 return (gftp_parse_file_size (tempstr) + startsize);
|
1
|
1232 }
|
|
1233
|
|
1234
|
|
1235 static int
|
58
|
1236 rfc959_put_file (gftp_request * request, const char *filename, int fd,
|
1
|
1237 off_t startsize, off_t totalsize)
|
|
1238 {
|
325
|
1239 intptr_t passive_transfer;
|
830
|
1240 char *command;
|
169
|
1241 rfc959_parms * parms;
|
426
|
1242 int ret;
|
1
|
1243
|
84
|
1244 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1245 g_return_val_if_fail (filename != NULL, GFTP_EFATAL);
|
169
|
1246 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1247
|
169
|
1248 parms = request->protocol_data;
|
816
|
1249 if (fd > 0) /* FIXME */
|
169
|
1250 fd = parms->data_connection;
|
1
|
1251
|
309
|
1252 if ((ret = rfc959_set_data_type (request, filename)) < 0)
|
|
1253 return (ret);
|
122
|
1254
|
169
|
1255 if (parms->data_connection < 0 &&
|
820
|
1256 (ret = rfc959_data_connection_new (request, 0)) < 0)
|
1
|
1257 return (ret);
|
|
1258
|
169
|
1259 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0)
|
84
|
1260 return (ret);
|
1
|
1261
|
|
1262 if (startsize > 0)
|
|
1263 {
|
532
|
1264 command = g_strdup_printf ("REST " GFTP_OFF_T_PRINTF_MOD "\r\n",
|
|
1265 startsize);
|
847
|
1266 ret = rfc959_send_command (request, command, -1, 1, 0);
|
1
|
1267 g_free (command);
|
518
|
1268 if (ret < 0)
|
|
1269 return (ret);
|
|
1270 else if (ret != '3')
|
1
|
1271 {
|
816
|
1272 rfc959_close_data_connection (request);
|
84
|
1273 return (GFTP_ERETRYABLE);
|
1
|
1274 }
|
|
1275 }
|
|
1276
|
830
|
1277 ret = rfc959_generate_and_send_command (request, "STOR", filename, 1, 0);
|
442
|
1278 if (ret < 0)
|
|
1279 return (ret);
|
|
1280 else if (ret != '1')
|
58
|
1281 {
|
816
|
1282 rfc959_close_data_connection (request);
|
858
|
1283
|
|
1284 if (ret == '5')
|
|
1285 return (GFTP_EFATAL);
|
|
1286 else
|
|
1287 return (GFTP_ERETRYABLE);
|
58
|
1288 }
|
1
|
1289
|
122
|
1290 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1291 if (!passive_transfer &&
|
1
|
1292 (ret = rfc959_accept_active_connection (request)) < 0)
|
|
1293 return (ret);
|
|
1294
|
|
1295 return (0);
|
|
1296 }
|
|
1297
|
58
|
1298
|
765
|
1299 static off_t
|
1
|
1300 rfc959_transfer_file (gftp_request *fromreq, const char *fromfile,
|
|
1301 off_t fromsize, gftp_request *toreq,
|
|
1302 const char *tofile, off_t tosize)
|
|
1303 {
|
|
1304 char *tempstr, *pos, *endpos;
|
426
|
1305 rfc959_parms * parms;
|
84
|
1306 int ret;
|
1
|
1307
|
84
|
1308 g_return_val_if_fail (fromreq != NULL, GFTP_EFATAL);
|
|
1309 g_return_val_if_fail (fromfile != NULL, GFTP_EFATAL);
|
|
1310 g_return_val_if_fail (toreq != NULL, GFTP_EFATAL);
|
|
1311 g_return_val_if_fail (tofile != NULL, GFTP_EFATAL);
|
169
|
1312 g_return_val_if_fail (fromreq->datafd > 0, GFTP_EFATAL);
|
|
1313 g_return_val_if_fail (toreq->datafd > 0, GFTP_EFATAL);
|
1
|
1314
|
847
|
1315 if ((ret = rfc959_send_command (fromreq, "PASV\r\n", -1, 1, 0)) < 0)
|
84
|
1316 return (ret);
|
442
|
1317 else if (ret != '2')
|
|
1318 return (GFTP_ERETRYABLE);
|
1
|
1319
|
|
1320 pos = fromreq->last_ftp_response + 4;
|
|
1321 while (!isdigit ((int) *pos) && *pos != '\0')
|
|
1322 pos++;
|
|
1323 if (*pos == '\0')
|
84
|
1324 return (GFTP_EFATAL);
|
1
|
1325
|
|
1326 endpos = pos;
|
|
1327 while (*endpos != ')' && *endpos != '\0')
|
|
1328 endpos++;
|
|
1329 if (*endpos == ')')
|
|
1330 *endpos = '\0';
|
|
1331
|
|
1332 tempstr = g_strconcat ("PORT ", pos, "\r\n", NULL);
|
847
|
1333 ret = rfc959_send_command (toreq, tempstr, -1, 1, 0);
|
1
|
1334 g_free (tempstr);
|
|
1335
|
442
|
1336 if (ret < 0)
|
|
1337 return (ret);
|
|
1338 else if (ret != '2')
|
|
1339 return (GFTP_ERETRYABLE);
|
|
1340
|
830
|
1341 ret = rfc959_generate_and_send_command (fromreq, "RETR", fromfile, 0, 0);
|
443
|
1342 if (ret < 0)
|
|
1343 return (ret);
|
|
1344
|
830
|
1345 ret = rfc959_generate_and_send_command (toreq, "STOR", tofile, 0, 0);
|
443
|
1346 if (ret < 0)
|
|
1347 return (ret);
|
|
1348
|
292
|
1349 if ((ret = rfc959_read_response (fromreq, 1)) < 0)
|
84
|
1350 return (ret);
|
|
1351
|
292
|
1352 if ((ret = rfc959_read_response (toreq, 1)) < 0)
|
84
|
1353 return (ret);
|
1
|
1354
|
426
|
1355 parms = fromreq->protocol_data;
|
|
1356 parms->is_fxp_transfer = 1;
|
|
1357
|
|
1358 parms = toreq->protocol_data;
|
|
1359 parms->is_fxp_transfer = 1;
|
|
1360
|
1
|
1361 return (0);
|
|
1362 }
|
|
1363
|
|
1364
|
|
1365 static int
|
|
1366 rfc959_end_transfer (gftp_request * request)
|
|
1367 {
|
169
|
1368 rfc959_parms * parms;
|
84
|
1369 int ret;
|
|
1370
|
|
1371 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1372 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1373
|
169
|
1374 parms = request->protocol_data;
|
426
|
1375 parms->is_fxp_transfer = 0;
|
292
|
1376
|
816
|
1377 rfc959_close_data_connection (request);
|
84
|
1378
|
292
|
1379 ret = rfc959_read_response (request, 1);
|
84
|
1380
|
|
1381 if (ret < 0)
|
|
1382 return (ret);
|
|
1383 else if (ret == '2')
|
|
1384 return (0);
|
|
1385 else
|
|
1386 return (GFTP_ERETRYABLE);
|
1
|
1387 }
|
|
1388
|
|
1389
|
|
1390 static int
|
40
|
1391 rfc959_abort_transfer (gftp_request * request)
|
|
1392 {
|
|
1393 int ret;
|
|
1394
|
84
|
1395 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1396 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
40
|
1397
|
847
|
1398 if ((ret = rfc959_send_command (request, "ABOR\r\n", -1, 0, 0)) < 0)
|
292
|
1399 return (ret);
|
|
1400
|
816
|
1401 rfc959_close_data_connection (request);
|
40
|
1402
|
169
|
1403 if (request->datafd > 0)
|
40
|
1404 {
|
292
|
1405 if ((ret = rfc959_read_response (request, 0)) < 0)
|
40
|
1406 gftp_disconnect (request);
|
|
1407 }
|
292
|
1408
|
40
|
1409 return (0);
|
|
1410 }
|
|
1411
|
|
1412
|
|
1413 static int
|
1
|
1414 rfc959_list_files (gftp_request * request)
|
|
1415 {
|
325
|
1416 intptr_t show_hidden_files, resolve_symlinks, passive_transfer;
|
1
|
1417 char *tempstr, parms[3];
|
518
|
1418 int ret;
|
1
|
1419
|
84
|
1420 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
169
|
1421 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1422
|
820
|
1423 if ((ret = rfc959_data_connection_new (request, 0)) < 0)
|
1
|
1424 return (ret);
|
|
1425
|
122
|
1426 gftp_lookup_request_option (request, "show_hidden_files", &show_hidden_files);
|
|
1427 gftp_lookup_request_option (request, "resolve_symlinks", &resolve_symlinks);
|
|
1428 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer);
|
|
1429
|
1
|
1430 *parms = '\0';
|
|
1431 strcat (parms, show_hidden_files ? "a" : "");
|
|
1432 strcat (parms, resolve_symlinks ? "L" : "");
|
|
1433 tempstr = g_strconcat ("LIST", *parms != '\0' ? " -" : "", parms, "\r\n",
|
|
1434 NULL);
|
|
1435
|
847
|
1436 ret = rfc959_send_command (request, tempstr, -1, 1, 0);
|
1
|
1437 g_free (tempstr);
|
|
1438
|
442
|
1439 if (ret < 0)
|
|
1440 return (ret);
|
|
1441 else if (ret != '1')
|
411
|
1442 {
|
|
1443 request->logging_function (gftp_logging_error, request,
|
|
1444 _("Invalid response '%c' received from server.\n"),
|
|
1445 ret);
|
|
1446 return (GFTP_ERETRYABLE);
|
|
1447 }
|
1
|
1448
|
|
1449 ret = 0;
|
122
|
1450 if (!passive_transfer)
|
1
|
1451 ret = rfc959_accept_active_connection (request);
|
|
1452
|
|
1453 return (ret);
|
|
1454 }
|
|
1455
|
|
1456
|
122
|
1457 static ssize_t
|
|
1458 rfc959_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
1459 {
|
301
|
1460 ssize_t num_read, ret;
|
169
|
1461 rfc959_parms * parms;
|
299
|
1462 int i, j;
|
122
|
1463
|
169
|
1464 parms = request->protocol_data;
|
426
|
1465 if (parms->is_fxp_transfer)
|
|
1466 return (GFTP_ENOTRANS);
|
299
|
1467
|
390
|
1468 num_read = parms->data_conn_read (request, buf, size, parms->data_connection);
|
122
|
1469 if (num_read < 0)
|
|
1470 return (num_read);
|
|
1471
|
301
|
1472 ret = num_read;
|
299
|
1473 if (parms->is_ascii_transfer)
|
122
|
1474 {
|
|
1475 for (i = 0, j = 0; i < num_read; i++)
|
|
1476 {
|
|
1477 if (buf[i] != '\r')
|
|
1478 buf[j++] = buf[i];
|
|
1479 else
|
301
|
1480 ret--;
|
122
|
1481 }
|
|
1482 }
|
|
1483
|
301
|
1484 return (ret);
|
122
|
1485 }
|
|
1486
|
|
1487
|
|
1488 static ssize_t
|
|
1489 rfc959_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
|
|
1490 {
|
818
|
1491 ssize_t num_wrote, ret;
|
169
|
1492 rfc959_parms * parms;
|
818
|
1493 char *tempstr, *pos;
|
521
|
1494 size_t rsize, i, j;
|
122
|
1495
|
169
|
1496 parms = request->protocol_data;
|
|
1497
|
426
|
1498 if (parms->is_fxp_transfer)
|
|
1499 return (GFTP_ENOTRANS);
|
|
1500
|
299
|
1501 if (parms->is_ascii_transfer)
|
122
|
1502 {
|
818
|
1503 rsize = size;
|
|
1504 for (i = 1; i < size; i++)
|
122
|
1505 {
|
818
|
1506 if (buf[i] == '\n' && buf[i - 1] != '\r')
|
122
|
1507 rsize++;
|
|
1508 }
|
|
1509
|
|
1510 if (rsize != size)
|
|
1511 {
|
|
1512 tempstr = g_malloc (rsize);
|
|
1513
|
|
1514 for (i = 0, j = 0; i < size; i++)
|
|
1515 {
|
|
1516 if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
|
|
1517 tempstr[j++] = '\r';
|
|
1518 tempstr[j++] = buf[i];
|
|
1519 }
|
|
1520 }
|
|
1521 else
|
|
1522 tempstr = buf;
|
|
1523 }
|
|
1524 else
|
|
1525 {
|
|
1526 rsize = size;
|
|
1527 tempstr = buf;
|
|
1528 }
|
|
1529
|
818
|
1530 /* I need to ensure that the entire buffer has been transfered properly due
|
|
1531 to the ascii conversion that may occur.
|
|
1532 FIXME - the ascii conversion doesn't occur properly when the \n occurs
|
|
1533 at the beginning of the buffer. I need to remember the last character
|
|
1534 in the previous buffer */
|
|
1535
|
|
1536 ret = rsize;
|
|
1537 pos = tempstr;
|
|
1538 while (rsize > 0)
|
|
1539 {
|
|
1540 num_wrote = parms->data_conn_write (request, pos, rsize,
|
|
1541 parms->data_connection);
|
|
1542 if (num_wrote < 0)
|
|
1543 {
|
|
1544 ret = num_wrote;
|
|
1545 break;
|
|
1546 }
|
|
1547
|
|
1548 pos += num_wrote;
|
|
1549 rsize -= num_wrote;
|
|
1550 }
|
122
|
1551
|
|
1552 if (tempstr != buf)
|
|
1553 g_free (tempstr);
|
|
1554
|
818
|
1555 return (ret);
|
122
|
1556 }
|
|
1557
|
|
1558
|
485
|
1559 static ssize_t
|
|
1560 rfc959_get_next_dirlist_line (gftp_request * request, int fd,
|
|
1561 char *buf, size_t buflen)
|
|
1562 {
|
|
1563 ssize_t (*oldread_func) (gftp_request * request, void *ptr, size_t size,
|
|
1564 int fd);
|
|
1565 rfc959_parms * parms;
|
|
1566 ssize_t len;
|
|
1567
|
|
1568 parms = request->protocol_data;
|
|
1569
|
|
1570 oldread_func = request->read_function;
|
|
1571 request->read_function = parms->data_conn_read;
|
|
1572 len = gftp_get_line (request, &parms->dataconn_rbuf, buf, buflen, fd);
|
|
1573 request->read_function = oldread_func;
|
|
1574
|
|
1575 return (len);
|
|
1576 }
|
|
1577
|
1
|
1578 int
|
58
|
1579 rfc959_get_next_file (gftp_request * request, gftp_file * fle, int fd)
|
1
|
1580 {
|
58
|
1581 rfc959_parms * parms;
|
249
|
1582 char tempstr[1024];
|
516
|
1583 size_t stlen;
|
58
|
1584 ssize_t len;
|
1
|
1585
|
84
|
1586 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1587 g_return_val_if_fail (fle != NULL, GFTP_EFATAL);
|
|
1588 g_return_val_if_fail (fd > 0, GFTP_EFATAL);
|
1
|
1589
|
|
1590 if (request->last_dir_entry)
|
|
1591 {
|
|
1592 g_free (request->last_dir_entry);
|
|
1593 request->last_dir_entry = NULL;
|
|
1594 }
|
58
|
1595
|
|
1596 parms = request->protocol_data;
|
|
1597
|
169
|
1598 if (fd == request->datafd)
|
|
1599 fd = parms->data_connection;
|
|
1600
|
1
|
1601 do
|
|
1602 {
|
485
|
1603 len = rfc959_get_next_dirlist_line (request, fd, tempstr,
|
|
1604 sizeof (tempstr));
|
389
|
1605 if (len <= 0)
|
1
|
1606 {
|
598
|
1607 gftp_file_destroy (fle, 0);
|
518
|
1608 return (len);
|
1
|
1609 }
|
|
1610
|
485
|
1611 if (gftp_parse_ls (request, tempstr, fle, fd) != 0)
|
1
|
1612 {
|
58
|
1613 if (strncmp (tempstr, "total", strlen ("total")) != 0 &&
|
|
1614 strncmp (tempstr, _("total"), strlen (_("total"))) != 0)
|
186
|
1615 request->logging_function (gftp_logging_error, request,
|
1
|
1616 _("Warning: Cannot parse listing %s\n"),
|
|
1617 tempstr);
|
598
|
1618 gftp_file_destroy (fle, 0);
|
1
|
1619 continue;
|
|
1620 }
|
|
1621 else
|
|
1622 break;
|
|
1623 }
|
|
1624 while (1);
|
|
1625
|
516
|
1626 stlen = strlen (tempstr);
|
1
|
1627 if (!request->cached)
|
|
1628 {
|
60
|
1629 request->last_dir_entry = g_strdup_printf ("%s\n", tempstr);
|
516
|
1630 request->last_dir_entry_len = stlen + 1;
|
1
|
1631 }
|
|
1632 return (len);
|
|
1633 }
|
|
1634
|
|
1635
|
|
1636 static off_t
|
|
1637 rfc959_get_file_size (gftp_request * request, const char *filename)
|
|
1638 {
|
|
1639 int ret;
|
|
1640
|
|
1641 g_return_val_if_fail (request != NULL, 0);
|
|
1642 g_return_val_if_fail (filename != NULL, 0);
|
169
|
1643 g_return_val_if_fail (request->datafd > 0, 0);
|
1
|
1644
|
830
|
1645 ret = rfc959_generate_and_send_command (request, "SIZE", filename, 1, 0);
|
1
|
1646 if (ret < 0)
|
84
|
1647 return (ret);
|
1
|
1648
|
|
1649 if (*request->last_ftp_response != '2')
|
|
1650 return (0);
|
830
|
1651
|
1
|
1652 return (strtol (request->last_ftp_response + 4, NULL, 10));
|
|
1653 }
|
|
1654
|
|
1655
|
|
1656 static int
|
|
1657 rfc959_rmdir (gftp_request * request, const char *directory)
|
|
1658 {
|
518
|
1659 int ret;
|
1
|
1660
|
84
|
1661 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1662 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
169
|
1663 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1664
|
830
|
1665 ret = rfc959_generate_and_send_command (request, "RMD", directory, 1, 0);
|
84
|
1666 if (ret < 0)
|
|
1667 return (ret);
|
|
1668 else if (ret == '2')
|
|
1669 return (0);
|
|
1670 else
|
|
1671 return (GFTP_ERETRYABLE);
|
1
|
1672 }
|
|
1673
|
|
1674
|
|
1675 static int
|
|
1676 rfc959_rmfile (gftp_request * request, const char *file)
|
|
1677 {
|
518
|
1678 int ret;
|
1
|
1679
|
84
|
1680 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1681 g_return_val_if_fail (file != NULL, GFTP_EFATAL);
|
169
|
1682 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1683
|
830
|
1684 ret = rfc959_generate_and_send_command (request, "DELE", file, 1, 0);
|
84
|
1685 if (ret < 0)
|
|
1686 return (ret);
|
|
1687 else if (ret == '2')
|
|
1688 return (0);
|
|
1689 else
|
|
1690 return (GFTP_ERETRYABLE);
|
1
|
1691 }
|
|
1692
|
|
1693
|
|
1694 static int
|
|
1695 rfc959_mkdir (gftp_request * request, const char *directory)
|
|
1696 {
|
518
|
1697 int ret;
|
1
|
1698
|
84
|
1699 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1700 g_return_val_if_fail (directory != NULL, GFTP_EFATAL);
|
169
|
1701 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1702
|
830
|
1703 ret = rfc959_generate_and_send_command (request, "MKD", directory, 1, 0);
|
84
|
1704 if (ret < 0)
|
|
1705 return (ret);
|
|
1706 else if (ret == '2')
|
|
1707 return (0);
|
|
1708 else
|
|
1709 return (GFTP_ERETRYABLE);
|
1
|
1710 }
|
|
1711
|
|
1712
|
|
1713 static int
|
|
1714 rfc959_rename (gftp_request * request, const char *oldname,
|
|
1715 const char *newname)
|
|
1716 {
|
518
|
1717 int ret;
|
1
|
1718
|
84
|
1719 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1720 g_return_val_if_fail (oldname != NULL, GFTP_EFATAL);
|
|
1721 g_return_val_if_fail (newname != NULL, GFTP_EFATAL);
|
169
|
1722 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1723
|
830
|
1724 ret = rfc959_generate_and_send_command (request, "RNFR", oldname, 1, 0);
|
84
|
1725 if (ret < 0)
|
|
1726 return (ret);
|
278
|
1727 else if (ret != '3')
|
84
|
1728 return (GFTP_ERETRYABLE);
|
1
|
1729
|
830
|
1730 ret = rfc959_generate_and_send_command (request, "RNTO", newname, 1, 0);
|
84
|
1731 if (ret < 0)
|
|
1732 return (ret);
|
|
1733 else if (ret == '2')
|
|
1734 return (0);
|
|
1735 else
|
|
1736 return (GFTP_ERETRYABLE);
|
1
|
1737 }
|
|
1738
|
|
1739
|
|
1740 static int
|
499
|
1741 rfc959_chmod (gftp_request * request, const char *file, mode_t mode)
|
1
|
1742 {
|
847
|
1743 char *tempstr, *utf8, *cmd;
|
838
|
1744 size_t destlen;
|
518
|
1745 int ret;
|
1
|
1746
|
84
|
1747 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1748 g_return_val_if_fail (file != NULL, GFTP_EFATAL);
|
169
|
1749 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1750
|
845
|
1751 utf8 = gftp_filename_from_utf8 (request, file, &destlen);
|
830
|
1752 if (utf8 != NULL)
|
|
1753 {
|
|
1754 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, utf8);
|
|
1755 g_free (utf8);
|
|
1756 }
|
|
1757 else
|
|
1758 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, file);
|
541
|
1759
|
847
|
1760 ret = rfc959_send_command (request, tempstr, -1, 1, 0); /* FIXME - add length */
|
1
|
1761 g_free (tempstr);
|
84
|
1762
|
|
1763 if (ret < 0)
|
|
1764 return (ret);
|
|
1765 else if (ret == '2')
|
|
1766 return (0);
|
|
1767 else
|
|
1768 return (GFTP_ERETRYABLE);
|
1
|
1769 }
|
|
1770
|
|
1771
|
|
1772 static int
|
478
|
1773 rfc959_site (gftp_request * request, int specify_site, const char *command)
|
1
|
1774 {
|
830
|
1775 char *tempstr, *utf8;
|
847
|
1776 size_t len;
|
518
|
1777 int ret;
|
1
|
1778
|
84
|
1779 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
|
1780 g_return_val_if_fail (command != NULL, GFTP_EFATAL);
|
169
|
1781 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL);
|
1
|
1782
|
847
|
1783 utf8 = gftp_string_from_utf8 (request, -1, command, &len);
|
830
|
1784 if (utf8 != NULL)
|
|
1785 {
|
|
1786 if (specify_site)
|
847
|
1787 {
|
|
1788 len += 7;
|
|
1789 tempstr = g_strconcat ("SITE ", utf8, "\r\n", NULL);
|
|
1790 }
|
830
|
1791 else
|
847
|
1792 {
|
|
1793 len += 2;
|
|
1794 tempstr = g_strconcat (utf8, "\r\n", NULL);
|
|
1795 }
|
830
|
1796
|
|
1797 g_free (utf8);
|
|
1798 }
|
478
|
1799 else
|
830
|
1800 {
|
|
1801 if (specify_site)
|
847
|
1802 {
|
|
1803 len = strlen (command) + 7;
|
|
1804 tempstr = g_strconcat ("SITE ", command, "\r\n", NULL);
|
|
1805 }
|
830
|
1806 else
|
847
|
1807 {
|
|
1808 len = strlen (command) + 2;
|
|
1809 tempstr = g_strconcat (command, "\r\n", NULL);
|
|
1810 }
|
830
|
1811 }
|
478
|
1812
|
847
|
1813 ret = rfc959_send_command (request, tempstr, len, 1, 0);
|
1
|
1814 g_free (tempstr);
|
84
|
1815
|
|
1816 if (ret < 0)
|
|
1817 return (ret);
|
|
1818 else if (ret == '2')
|
|
1819 return (0);
|
|
1820 else
|
|
1821 return (GFTP_ERETRYABLE);
|
58
|
1822 }
|
|
1823
|
|
1824
|
513
|
1825 static int
|
58
|
1826 rfc959_set_config_options (gftp_request * request)
|
|
1827 {
|
122
|
1828 char *proxy_config;
|
177
|
1829 int ret;
|
58
|
1830
|
122
|
1831 gftp_lookup_request_option (request, "proxy_config", &proxy_config);
|
|
1832 if (strcmp (proxy_config, "http") == 0)
|
58
|
1833 {
|
177
|
1834 if ((ret = gftp_protocols[GFTP_HTTP_NUM].init (request)) < 0)
|
|
1835 return (ret);
|
173
|
1836
|
122
|
1837 gftp_set_request_option (request, "proxy_config", "ftp");
|
58
|
1838 }
|
177
|
1839
|
|
1840 return (0);
|
122
|
1841 }
|
58
|
1842
|
|
1843
|
122
|
1844 void
|
|
1845 rfc959_register_module (void)
|
|
1846 {
|
|
1847 gftp_register_config_vars (config_vars);
|
1
|
1848 }
|
|
1849
|
|
1850
|
516
|
1851 static void
|
201
|
1852 rfc959_request_destroy (gftp_request * request)
|
|
1853 {
|
|
1854 rfc959_parms * parms;
|
|
1855
|
|
1856 parms = request->protocol_data;
|
|
1857
|
|
1858 if (parms->datafd_rbuf != NULL)
|
|
1859 gftp_free_getline_buffer (&parms->datafd_rbuf);
|
|
1860
|
|
1861 if (parms->dataconn_rbuf != NULL)
|
|
1862 gftp_free_getline_buffer (&parms->dataconn_rbuf);
|
|
1863 }
|
|
1864
|
|
1865
|
516
|
1866 static void
|
309
|
1867 rfc959_copy_param_options (gftp_request * dest_request,
|
|
1868 gftp_request * src_request)
|
|
1869 {
|
|
1870 rfc959_parms * dparms, * sparms;
|
|
1871
|
|
1872 dparms = dest_request->protocol_data;
|
|
1873 sparms = src_request->protocol_data;
|
|
1874
|
432
|
1875 dparms->data_connection = -1;
|
309
|
1876 dparms->is_ascii_transfer = sparms->is_ascii_transfer;
|
432
|
1877 dparms->is_fxp_transfer = sparms->is_fxp_transfer;
|
|
1878 dparms->auth_tls_start = sparms->auth_tls_start;
|
|
1879 dparms->data_conn_read = sparms->data_conn_read;
|
|
1880 dparms->data_conn_write = sparms->data_conn_write;
|
|
1881
|
|
1882 dest_request->read_function = src_request->read_function;
|
|
1883 dest_request->write_function = src_request->write_function;
|
309
|
1884 }
|
|
1885
|
|
1886
|
173
|
1887 int
|
48
|
1888 rfc959_init (gftp_request * request)
|
1
|
1889 {
|
169
|
1890 rfc959_parms * parms;
|
227
|
1891 struct hostent *hent;
|
|
1892 struct utsname unme;
|
|
1893 struct passwd *pw;
|
|
1894 char *tempstr;
|
169
|
1895
|
173
|
1896 g_return_val_if_fail (request != NULL, GFTP_EFATAL);
|
1
|
1897
|
227
|
1898 gftp_lookup_global_option ("email", &tempstr);
|
|
1899 if (tempstr == NULL || *tempstr == '\0')
|
|
1900 {
|
|
1901 /* If there is no email address specified, then we'll just use the
|
|
1902 currentuser@currenthost */
|
|
1903 uname (&unme);
|
|
1904 pw = getpwuid (geteuid ());
|
|
1905 hent = gethostbyname (unme.nodename);
|
|
1906 if (strchr (unme.nodename, '.') == NULL && hent != NULL)
|
|
1907 tempstr = g_strconcat (pw->pw_name, "@", hent->h_name, NULL);
|
|
1908 else
|
|
1909 tempstr = g_strconcat (pw->pw_name, "@", unme.nodename, NULL);
|
|
1910 gftp_set_global_option ("email", tempstr);
|
|
1911 g_free (tempstr);
|
|
1912 }
|
|
1913
|
48
|
1914 request->protonum = GFTP_FTP_NUM;
|
|
1915 request->init = rfc959_init;
|
309
|
1916 request->copy_param_options = rfc959_copy_param_options;
|
201
|
1917 request->destroy = rfc959_request_destroy;
|
168
|
1918 request->read_function = gftp_fd_read;
|
|
1919 request->write_function = gftp_fd_write;
|
48
|
1920 request->connect = rfc959_connect;
|
168
|
1921 request->post_connect = NULL;
|
48
|
1922 request->disconnect = rfc959_disconnect;
|
|
1923 request->get_file = rfc959_get_file;
|
|
1924 request->put_file = rfc959_put_file;
|
|
1925 request->transfer_file = rfc959_transfer_file;
|
122
|
1926 request->get_next_file_chunk = rfc959_get_next_file_chunk;
|
|
1927 request->put_next_file_chunk = rfc959_put_next_file_chunk;
|
48
|
1928 request->end_transfer = rfc959_end_transfer;
|
|
1929 request->abort_transfer = rfc959_abort_transfer;
|
500
|
1930 request->stat_filename = NULL;
|
48
|
1931 request->list_files = rfc959_list_files;
|
|
1932 request->get_next_file = rfc959_get_next_file;
|
485
|
1933 request->get_next_dirlist_line = rfc959_get_next_dirlist_line;
|
48
|
1934 request->get_file_size = rfc959_get_file_size;
|
|
1935 request->chdir = rfc959_chdir;
|
|
1936 request->rmdir = rfc959_rmdir;
|
|
1937 request->rmfile = rfc959_rmfile;
|
|
1938 request->mkdir = rfc959_mkdir;
|
|
1939 request->rename = rfc959_rename;
|
|
1940 request->chmod = rfc959_chmod;
|
818
|
1941 request->set_file_time = NULL;
|
48
|
1942 request->site = rfc959_site;
|
|
1943 request->parse_url = NULL;
|
63
|
1944 request->swap_socks = NULL;
|
58
|
1945 request->set_config_options = rfc959_set_config_options;
|
48
|
1946 request->url_prefix = "ftp";
|
|
1947 request->need_hostport = 1;
|
650
|
1948 request->need_username = 1;
|
553
|
1949 request->need_password = 1;
|
48
|
1950 request->use_cache = 1;
|
|
1951 request->always_connected = 0;
|
832
|
1952 request->use_local_encoding = 0;
|
169
|
1953
|
58
|
1954 request->protocol_data = g_malloc0 (sizeof (rfc959_parms));
|
169
|
1955 parms = request->protocol_data;
|
|
1956 parms->data_connection = -1;
|
389
|
1957 parms->auth_tls_start = NULL;
|
390
|
1958 parms->data_conn_read = gftp_fd_read;
|
|
1959 parms->data_conn_write = gftp_fd_write;
|
169
|
1960
|
177
|
1961 return (gftp_set_config_options (request));
|
1
|
1962 }
|
|
1963
|