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