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