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