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