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