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