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