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