Mercurial > gftp.yaz
annotate lib/rfc959.c @ 992:9c583f570950 default tip
more character set conversion on remote file names.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Wed, 15 Sep 2010 11:42:57 +0900 |
parents | 63555c9744c2 |
children |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* rfc959.c - General purpose routines for the FTP protocol (RFC 959) */ | |
885 | 3 /* Copyright (C) 1998-2007 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}, | |
988
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
47 |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
48 /* charset */ |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
49 #if 0 |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
50 {"remote_charset", N_("Remote Character Set:"), |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
51 gftp_option_type_text, "", NULL, GFTP_CVARS_FLAGS_SHOW_BOOKMARK_ONLY, |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
52 N_("This is the site specific charset"), |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
53 GFTP_PORT_ALL, NULL}, |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
54 #endif |
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
55 |
122 | 56 {"ftp_proxy_host", N_("Proxy hostname:"), |
57 gftp_option_type_text, "", NULL, 0, | |
58 N_("Firewall hostname"), GFTP_PORT_ALL, NULL}, | |
59 {"ftp_proxy_port", N_("Proxy port:"), | |
60 gftp_option_type_int, GINT_TO_POINTER(21), NULL, 0, | |
61 N_("Port to connect to on the firewall"), GFTP_PORT_ALL, NULL}, | |
62 {"ftp_proxy_username", N_("Proxy username:"), | |
63 gftp_option_type_text, "", NULL, 0, | |
64 N_("Your firewall username"), GFTP_PORT_ALL, NULL}, | |
65 {"ftp_proxy_password", N_("Proxy password:"), | |
66 gftp_option_type_hidetext, "", NULL, 0, | |
67 N_("Your firewall password"), GFTP_PORT_ALL, NULL}, | |
68 {"ftp_proxy_account", N_("Proxy account:"), | |
69 gftp_option_type_text, "", NULL, 0, | |
70 N_("Your firewall account (optional)"), GFTP_PORT_ALL, NULL}, | |
71 | |
126 | 72 {"proxy_config", N_("Proxy server type:"), |
73 gftp_option_type_textcomboedt, "", gftp_proxy_type, 0, | |
149 | 74 /* xgettext:no-c-format */ |
126 | 75 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"), |
76 GFTP_PORT_ALL, NULL}, | |
77 | |
643 | 78 {"ignore_pasv_address", N_("Ignore PASV address"), |
79 gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, | |
80 GFTP_CVARS_FLAGS_SHOW_BOOKMARK, | |
81 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."), | |
82 GFTP_PORT_ALL, NULL}, | |
136 | 83 {"passive_transfer", N_("Passive file transfers"), |
227 | 84 gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, |
85 GFTP_CVARS_FLAGS_SHOW_BOOKMARK, | |
136 | 86 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."), |
87 GFTP_PORT_ALL, NULL}, | |
88 {"resolve_symlinks", N_("Resolve Remote Symlinks (LIST -L)"), | |
227 | 89 gftp_option_type_checkbox, GINT_TO_POINTER(1), NULL, |
90 GFTP_CVARS_FLAGS_SHOW_BOOKMARK, | |
136 | 91 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"), |
92 GFTP_PORT_ALL, NULL}, | |
93 {"ascii_transfers", N_("Transfer files in ASCII mode"), | |
227 | 94 gftp_option_type_checkbox, GINT_TO_POINTER(0), NULL, |
95 GFTP_CVARS_FLAGS_SHOW_BOOKMARK, | |
136 | 96 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."), |
97 GFTP_PORT_ALL, NULL}, | |
98 | |
122 | 99 {NULL, NULL, 0, NULL, NULL, 0, NULL, 0, NULL} |
100 }; | |
101 | |
102 | |
48 | 103 static int |
292 | 104 rfc959_read_response (gftp_request * request, int disconnect_on_42x) |
48 | 105 { |
106 char tempstr[255], code[4]; | |
58 | 107 rfc959_parms * parms; |
108 ssize_t num_read; | |
48 | 109 |
84 | 110 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
169 | 111 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
48 | 112 |
113 *code = '\0'; | |
114 if (request->last_ftp_response) | |
115 { | |
116 g_free (request->last_ftp_response); | |
117 request->last_ftp_response = NULL; | |
118 } | |
119 | |
58 | 120 parms = request->protocol_data; |
121 | |
48 | 122 do |
123 { | |
169 | 124 if ((num_read = gftp_get_line (request, &parms->datafd_rbuf, tempstr, |
125 sizeof (tempstr), request->datafd)) <= 0) | |
48 | 126 break; |
58 | 127 |
48 | 128 if (isdigit ((int) *tempstr) && isdigit ((int) *(tempstr + 1)) |
129 && isdigit ((int) *(tempstr + 2))) | |
130 { | |
131 strncpy (code, tempstr, 3); | |
132 code[3] = ' '; | |
133 } | |
881 | 134 |
135 if (*tempstr == '4' || *tempstr == '5') | |
136 request->logging_function (gftp_logging_error, request, | |
137 "%s\n", tempstr); | |
138 else | |
139 request->logging_function (gftp_logging_recv, request, | |
140 "%s\n", tempstr); | |
48 | 141 } |
142 while (strncmp (code, tempstr, 4) != 0); | |
143 | |
58 | 144 if (num_read < 0) |
84 | 145 return ((int) num_read); |
48 | 146 |
105 | 147 request->last_ftp_response = g_strdup (tempstr); |
48 | 148 |
149 if (request->last_ftp_response[0] == '4' && | |
292 | 150 request->last_ftp_response[1] == '2' && |
151 disconnect_on_42x) | |
442 | 152 { |
153 gftp_disconnect (request); | |
154 return (GFTP_ETIMEDOUT); | |
155 } | |
48 | 156 |
157 return (*request->last_ftp_response); | |
158 } | |
159 | |
160 | |
389 | 161 int |
292 | 162 rfc959_send_command (gftp_request * request, const char *command, |
847 | 163 ssize_t command_len, int read_response, |
164 int dont_try_to_reconnect) | |
48 | 165 { |
84 | 166 int ret; |
167 | |
168 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
169 g_return_val_if_fail (command != NULL, GFTP_EFATAL); | |
169 | 170 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
48 | 171 |
172 if (strncmp (command, "PASS", 4) == 0) | |
173 { | |
186 | 174 request->logging_function (gftp_logging_send, request, |
48 | 175 "PASS xxxx\n"); |
176 } | |
177 else if (strncmp (command, "ACCT", 4) == 0) | |
178 { | |
186 | 179 request->logging_function (gftp_logging_send, request, |
48 | 180 "ACCT xxxx\n"); |
181 } | |
182 else | |
183 { | |
186 | 184 request->logging_function (gftp_logging_send, request, "%s", |
48 | 185 command); |
186 } | |
187 | |
847 | 188 if (command_len == -1) |
189 command_len = strlen (command); | |
190 | |
191 if ((ret = request->write_function (request, command, command_len, | |
389 | 192 request->datafd)) < 0) |
84 | 193 return (ret); |
48 | 194 |
292 | 195 if (read_response) |
820 | 196 { |
197 ret = rfc959_read_response (request, 1); | |
198 if (ret == GFTP_ETIMEDOUT && !dont_try_to_reconnect) | |
199 { | |
200 ret = gftp_connect (request); | |
201 if (ret < 0) | |
202 return (ret); | |
203 | |
847 | 204 return (rfc959_send_command (request, command, command_len, 1, 1)); |
820 | 205 } |
206 else | |
207 return (ret); | |
208 } | |
292 | 209 else |
210 return (0); | |
48 | 211 } |
212 | |
830 | 213 static int |
214 rfc959_generate_and_send_command (gftp_request * request, const char *command, | |
215 const char *argument, int read_response, | |
216 int dont_try_to_reconnect) | |
217 { | |
218 char *tempstr, *utf8; | |
847 | 219 size_t len; |
830 | 220 int resp; |
221 | |
222 if (argument != NULL) | |
223 { | |
988
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
224 utf8 = gftp_remote_filename_from_utf8 (request, argument, &len); |
830 | 225 if (utf8 != NULL) |
226 { | |
227 tempstr = g_strconcat (command, " ", utf8, "\r\n", NULL); | |
228 g_free (utf8); | |
229 } | |
847 | 230 else |
231 { | |
232 tempstr = g_strconcat (command, " ", argument, "\r\n", NULL); | |
233 len = strlen (argument); | |
234 } | |
235 | |
236 len += strlen (command) + 3; | |
830 | 237 } |
238 else | |
847 | 239 { |
240 tempstr = g_strconcat (command, "\r\n", NULL); | |
241 len = strlen (command) + 2; | |
242 } | |
830 | 243 |
847 | 244 resp = rfc959_send_command (request, tempstr, len, read_response, |
830 | 245 dont_try_to_reconnect); |
246 g_free (tempstr); | |
247 return (resp); | |
248 } | |
249 | |
48 | 250 |
251 static char * | |
252 parse_ftp_proxy_string (gftp_request * request) | |
253 { | |
298 | 254 char *startpos, *endpos, *newstr, *newval, tempport[6], *proxy_config, *utf8, |
126 | 255 savechar; |
838 | 256 size_t len, destlen; |
325 | 257 intptr_t tmp; |
48 | 258 |
259 g_return_val_if_fail (request != NULL, NULL); | |
1 | 260 |
122 | 261 gftp_lookup_request_option (request, "proxy_config", &proxy_config); |
126 | 262 |
263 newstr = g_malloc0 (1); | |
264 len = 0; | |
122 | 265 startpos = endpos = proxy_config; |
48 | 266 while (*endpos != '\0') |
267 { | |
268 if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'p') | |
269 { | |
270 switch (tolower ((int) *(endpos + 2))) | |
271 { | |
272 case 'u': | |
124 | 273 gftp_lookup_request_option (request, "ftp_proxy_username", &newval); |
48 | 274 break; |
275 case 'p': | |
124 | 276 gftp_lookup_request_option (request, "ftp_proxy_password", &newval); |
48 | 277 break; |
278 case 'h': | |
124 | 279 gftp_lookup_request_option (request, "ftp_proxy_host", &newval); |
48 | 280 break; |
281 case 'o': | |
124 | 282 gftp_lookup_request_option (request, "ftp_proxy_port", &tmp); |
325 | 283 g_snprintf (tempport, sizeof (tempport), "%d", (int)tmp); |
48 | 284 newval = tempport; |
285 break; | |
286 case 'a': | |
124 | 287 gftp_lookup_request_option (request, "ftp_proxy_account", &newval); |
48 | 288 break; |
289 default: | |
290 endpos++; | |
291 continue; | |
292 } | |
293 } | |
294 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'h') | |
295 { | |
296 switch (tolower ((int) *(endpos + 2))) | |
297 { | |
298 case 'u': | |
299 newval = request->username; | |
300 break; | |
301 case 'p': | |
302 newval = request->password; | |
303 break; | |
304 case 'h': | |
305 newval = request->hostname; | |
306 break; | |
307 case 'o': | |
126 | 308 g_snprintf (tempport, sizeof (tempport), "%d", request->port); |
48 | 309 newval = tempport; |
310 break; | |
311 case 'a': | |
312 newval = request->account; | |
313 break; | |
314 default: | |
315 endpos++; | |
316 continue; | |
317 } | |
318 } | |
319 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'n') | |
320 { | |
126 | 321 savechar = *endpos; |
322 *endpos = '\0'; | |
323 | |
324 len += strlen (startpos) + 2; | |
765 | 325 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1)); |
126 | 326 strcat (newstr, startpos); |
327 strcat (newstr, "\r\n"); | |
328 | |
329 *endpos = savechar; | |
48 | 330 endpos += 2; |
331 startpos = endpos; | |
332 continue; | |
333 } | |
334 else | |
335 { | |
336 endpos++; | |
337 continue; | |
338 } | |
1 | 339 |
126 | 340 savechar = *endpos; |
48 | 341 *endpos = '\0'; |
126 | 342 len += strlen (startpos); |
48 | 343 if (!newval) |
126 | 344 { |
765 | 345 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1)); |
126 | 346 strcat (newstr, startpos); |
347 } | |
48 | 348 else |
126 | 349 { |
845 | 350 utf8 = gftp_string_from_utf8 (request, -1, newval, &destlen); |
298 | 351 if (utf8 != NULL) |
352 len += strlen (utf8); | |
353 else | |
354 len += strlen (newval); | |
355 | |
765 | 356 newstr = g_realloc (newstr, (gulong) sizeof (char) * (len + 1)); |
126 | 357 strcat (newstr, startpos); |
298 | 358 |
359 if (utf8 != NULL) | |
360 { | |
361 strcat (newstr, utf8); | |
362 g_free (utf8); | |
363 } | |
364 else | |
365 strcat (newstr, newval); | |
126 | 366 } |
367 | |
368 *endpos = savechar; | |
48 | 369 endpos += 3; |
370 startpos = endpos; | |
371 } | |
126 | 372 |
48 | 373 return (newstr); |
374 } | |
375 | |
376 | |
377 static int | |
58 | 378 rfc959_getcwd (gftp_request * request) |
379 { | |
830 | 380 char *pos, *dir, *utf8; |
838 | 381 size_t destlen; |
58 | 382 int ret; |
383 | |
847 | 384 ret = rfc959_send_command (request, "PWD\r\n", -1, 1, 0); |
58 | 385 if (ret < 0) |
84 | 386 return (ret); |
58 | 387 else if (ret != '2') |
388 { | |
186 | 389 request->logging_function (gftp_logging_error, request, |
411 | 390 _("Invalid response '%c' received from server.\n"), |
391 ret); | |
58 | 392 gftp_disconnect (request); |
84 | 393 return (GFTP_ERETRYABLE); |
58 | 394 } |
395 | |
396 if ((pos = strchr (request->last_ftp_response, '"')) == NULL) | |
397 { | |
186 | 398 request->logging_function (gftp_logging_error, request, |
411 | 399 _("Invalid response '%c' received from server.\n"), |
400 ret); | |
58 | 401 gftp_disconnect (request); |
84 | 402 return (GFTP_EFATAL); |
58 | 403 } |
404 | |
405 dir = pos + 1; | |
406 | |
407 if ((pos = strchr (dir, '"')) == NULL) | |
408 { | |
186 | 409 request->logging_function (gftp_logging_error, request, |
411 | 410 _("Invalid response '%c' received from server.\n"), |
411 ret); | |
58 | 412 gftp_disconnect (request); |
84 | 413 return (GFTP_EFATAL); |
58 | 414 } |
415 | |
416 *pos = '\0'; | |
417 | |
418 if (request->directory) | |
419 g_free (request->directory); | |
420 | |
992
9c583f570950
more character set conversion on remote file names.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
988
diff
changeset
|
421 utf8 = gftp_remote_filename_to_utf8 (request, dir, &destlen); |
830 | 422 if (utf8 != NULL) |
423 request->directory = utf8; | |
424 else | |
425 request->directory = g_strdup (dir); | |
426 | |
58 | 427 return (0); |
428 } | |
429 | |
430 | |
431 static int | |
48 | 432 rfc959_chdir (gftp_request * request, const char *directory) |
433 { | |
518 | 434 int ret; |
48 | 435 |
84 | 436 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
437 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
48 | 438 |
439 if (strcmp (directory, "..") == 0) | |
847 | 440 ret = rfc959_send_command (request, "CDUP\r\n", -1, 1, 0); |
48 | 441 else |
830 | 442 ret = rfc959_generate_and_send_command (request, "CWD", directory, 1, 0); |
48 | 443 |
442 | 444 if (ret < 0) |
445 return (ret); | |
446 else if (ret != '2') | |
84 | 447 return (GFTP_ERETRYABLE); |
48 | 448 |
787 | 449 if ((ret = rfc959_getcwd (request)) < 0) |
450 return (ret); | |
48 | 451 |
452 return (0); | |
1 | 453 } |
454 | |
455 | |
456 static int | |
91 | 457 rfc959_syst (gftp_request * request) |
458 { | |
811 | 459 int ret, disable_ls_options; |
91 | 460 char *stpos, *endpos; |
461 | |
462 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
169 | 463 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
91 | 464 |
847 | 465 ret = rfc959_send_command (request, "SYST\r\n", -1, 1, 0); |
91 | 466 |
467 if (ret < 0) | |
468 return (ret); | |
469 else if (ret != '2') | |
470 return (GFTP_ERETRYABLE); | |
471 | |
472 if ((stpos = strchr (request->last_ftp_response, ' ')) == NULL) | |
473 return (GFTP_ERETRYABLE); | |
474 | |
114 | 475 stpos++; |
476 | |
91 | 477 if ((endpos = strchr (stpos, ' ')) == NULL) |
478 return (GFTP_ERETRYABLE); | |
479 | |
480 *endpos = '\0'; | |
811 | 481 disable_ls_options = 0; |
541 | 482 |
91 | 483 if (strcmp (stpos, "UNIX") == 0) |
647 | 484 request->server_type = GFTP_DIRTYPE_UNIX; |
107 | 485 else if (strcmp (stpos, "VMS") == 0) |
757 | 486 { |
811 | 487 disable_ls_options = 1; |
757 | 488 request->server_type = GFTP_DIRTYPE_VMS; |
489 } | |
367 | 490 else if (strcmp (stpos, "MVS") == 0 || |
491 strcmp (stpos, "OS/MVS") == 0) | |
358 | 492 request->server_type = GFTP_DIRTYPE_MVS; |
305 | 493 else if (strcmp (stpos, "NETWARE") == 0) |
494 request->server_type = GFTP_DIRTYPE_NOVELL; | |
136 | 495 else if (strcmp (stpos, "CRAY") == 0) |
496 request->server_type = GFTP_DIRTYPE_CRAY; | |
91 | 497 else |
122 | 498 request->server_type = GFTP_DIRTYPE_OTHER; |
91 | 499 |
811 | 500 if (strcmp (stpos, "OS/400") == 0) |
501 disable_ls_options = 1; | |
502 | |
503 if (disable_ls_options) | |
504 { | |
505 gftp_set_request_option (request, "show_hidden_files", | |
506 GINT_TO_POINTER(0)); | |
507 gftp_set_request_option (request, "resolve_symlinks", GINT_TO_POINTER(0)); | |
508 } | |
509 | |
91 | 510 return (0); |
511 } | |
512 | |
513 | |
451 | 514 int |
1 | 515 rfc959_connect (gftp_request * request) |
516 { | |
830 | 517 char tempchar, *startpos, *endpos, *tempstr, *email, *proxy_hostname; |
325 | 518 intptr_t ascii_transfers, proxy_port; |
122 | 519 rfc959_parms * parms; |
518 | 520 int ret, resp; |
1 | 521 |
84 | 522 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
523 g_return_val_if_fail (request->hostname != NULL, GFTP_EFATAL); | |
1 | 524 |
169 | 525 if (request->datafd > 0) |
58 | 526 return (0); |
527 | |
122 | 528 parms = request->protocol_data; |
529 | |
124 | 530 gftp_lookup_request_option (request, "ftp_proxy_host", &proxy_hostname); |
531 gftp_lookup_request_option (request, "ftp_proxy_port", &proxy_port); | |
122 | 532 |
7 | 533 if (request->username == NULL || *request->username == '\0') |
570 | 534 gftp_set_username (request, GFTP_ANONYMOUS_USER); |
370 | 535 |
570 | 536 if (strcasecmp (request->username, GFTP_ANONYMOUS_USER) == 0 && |
370 | 537 (request->password == NULL || *request->password == '\0')) |
7 | 538 { |
370 | 539 gftp_lookup_request_option (request, "email", &email); |
122 | 540 gftp_set_password (request, email); |
7 | 541 } |
122 | 542 |
765 | 543 if ((ret = gftp_connect_server (request, "ftp", proxy_hostname, |
544 proxy_port)) < 0) | |
177 | 545 return (ret); |
1 | 546 |
547 /* Get the banner */ | |
292 | 548 if ((ret = rfc959_read_response (request, 1)) != '2') |
1 | 549 { |
550 gftp_disconnect (request); | |
567 | 551 if (ret < 0) |
552 return (ret); | |
553 else | |
554 return (GFTP_ERETRYABLE); | |
1 | 555 } |
556 | |
389 | 557 if (parms->auth_tls_start != NULL) |
558 { | |
559 if ((ret = parms->auth_tls_start (request)) < 0) | |
560 { | |
561 gftp_disconnect (request); | |
562 return (ret); | |
563 } | |
564 } | |
565 | |
1 | 566 /* Login the proxy server if available */ |
567 if (request->use_proxy) | |
568 { | |
569 resp = '3'; | |
570 startpos = endpos = tempstr = parse_ftp_proxy_string (request); | |
571 while ((resp == '3' || resp == '2') && *startpos != '\0') | |
572 { | |
573 if (*endpos == '\n' || *endpos == '\0') | |
574 { | |
575 tempchar = *(endpos + 1); | |
576 if (*endpos != '\0') | |
577 *(endpos + 1) = '\0'; | |
847 | 578 if ((resp = rfc959_send_command (request, startpos, -1, 1, 0)) < 0) |
84 | 579 return (resp); |
1 | 580 if (*endpos != '\0') |
581 *(endpos + 1) = tempchar; | |
582 else | |
583 break; | |
584 startpos = endpos + 1; | |
585 } | |
586 endpos++; | |
587 } | |
588 g_free (tempstr); | |
589 } | |
590 else | |
591 { | |
830 | 592 resp = rfc959_generate_and_send_command (request, "USER", |
593 request->username, 1, 0); | |
1 | 594 if (resp < 0) |
443 | 595 return (resp); |
286 | 596 |
1 | 597 if (resp == '3') |
598 { | |
830 | 599 resp = rfc959_generate_and_send_command (request, "PASS", |
600 request->password, 1, 0); | |
1 | 601 if (resp < 0) |
443 | 602 return (resp); |
1 | 603 } |
286 | 604 |
570 | 605 if (resp == '3' && request->account != NULL) |
1 | 606 { |
830 | 607 resp = rfc959_generate_and_send_command (request, "ACCT", |
608 request->account, 1, 0); | |
1 | 609 if (resp < 0) |
443 | 610 return (resp); |
1 | 611 } |
612 } | |
613 | |
614 if (resp != '2') | |
615 { | |
616 gftp_disconnect (request); | |
286 | 617 |
618 if (resp == '5') | |
619 return (GFTP_EFATAL); | |
620 else | |
621 return (GFTP_ERETRYABLE); | |
1 | 622 } |
623 | |
169 | 624 if ((ret = rfc959_syst (request)) < 0 && request->datafd < 0) |
91 | 625 return (ret); |
626 | |
122 | 627 gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers); |
628 if (ascii_transfers) | |
629 { | |
630 tempstr = "TYPE A\r\n"; | |
631 parms->is_ascii_transfer = 1; | |
632 } | |
1 | 633 else |
122 | 634 { |
635 tempstr = "TYPE I\r\n"; | |
636 parms->is_ascii_transfer = 0; | |
637 } | |
1 | 638 |
847 | 639 if ((ret = rfc959_send_command (request, tempstr, -1, 1, 0)) < 0) |
84 | 640 return (ret); |
1 | 641 |
642 ret = -1; | |
643 if (request->directory != NULL && *request->directory != '\0') | |
644 { | |
645 ret = rfc959_chdir (request, request->directory); | |
169 | 646 if (request->datafd < 0) |
84 | 647 return (ret); |
1 | 648 } |
649 | |
650 if (ret != 0) | |
651 { | |
84 | 652 if ((ret = rfc959_getcwd (request)) < 0) |
653 return (ret); | |
1 | 654 } |
655 | |
169 | 656 if (request->datafd < 0) |
84 | 657 return (GFTP_EFATAL); |
1 | 658 |
659 return (0); | |
660 } | |
661 | |
662 | |
663 static void | |
816 | 664 rfc959_close_data_connection (gftp_request * request) |
1 | 665 { |
169 | 666 rfc959_parms * parms; |
667 | |
1 | 668 g_return_if_fail (request != NULL); |
669 | |
169 | 670 parms = request->protocol_data; |
816 | 671 if (parms->data_connection != -1) |
672 { | |
673 close (parms->data_connection); | |
674 parms->data_connection = -1; | |
675 } | |
676 } | |
677 | |
678 | |
679 static void | |
680 rfc959_disconnect (gftp_request * request) | |
681 { | |
682 g_return_if_fail (request != NULL); | |
169 | 683 |
818 | 684 rfc959_close_data_connection (request); |
169 | 685 if (request->datafd > 0) |
1 | 686 { |
186 | 687 request->logging_function (gftp_logging_misc, request, |
1 | 688 _("Disconnecting from site %s\n"), |
689 request->hostname); | |
169 | 690 close (request->datafd); |
691 request->datafd = -1; | |
692 } | |
1 | 693 } |
694 | |
695 | |
48 | 696 static int |
146 | 697 rfc959_ipv4_data_connection_new (gftp_request * request) |
48 | 698 { |
699 struct sockaddr_in data_addr; | |
643 | 700 intptr_t ignore_pasv_address; |
518 | 701 char *pos, *pos1, *command; |
325 | 702 intptr_t passive_transfer; |
169 | 703 rfc959_parms * parms; |
195 | 704 socklen_t data_addr_len; |
48 | 705 unsigned int temp[6]; |
706 unsigned char ad[6]; | |
518 | 707 int i, resp; |
48 | 708 |
169 | 709 parms = request->protocol_data; |
710 | |
820 | 711 parms->data_connection = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); |
712 if (parms->data_connection == -1) | |
48 | 713 { |
186 | 714 request->logging_function (gftp_logging_error, request, |
313 | 715 _("Failed to create a IPv4 socket: %s\n"), |
48 | 716 g_strerror (errno)); |
717 gftp_disconnect (request); | |
84 | 718 return (GFTP_ERETRYABLE); |
48 | 719 } |
720 | |
182 | 721 if (fcntl (parms->data_connection, F_SETFD, 1) == -1) |
722 { | |
186 | 723 request->logging_function (gftp_logging_error, request, |
182 | 724 _("Error: Cannot set close on exec flag: %s\n"), |
725 g_strerror (errno)); | |
726 | |
727 return (GFTP_ERETRYABLE); | |
728 } | |
729 | |
48 | 730 data_addr_len = sizeof (data_addr); |
731 memset (&data_addr, 0, data_addr_len); | |
732 data_addr.sin_family = AF_INET; | |
733 | |
122 | 734 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer); |
735 if (passive_transfer) | |
48 | 736 { |
847 | 737 resp = rfc959_send_command (request, "PASV\r\n", -1, 1, 1); |
443 | 738 if (resp < 0) |
739 return (resp); | |
740 else if (resp != '2') | |
48 | 741 { |
443 | 742 gftp_set_request_option (request, "passive_transfer", |
743 GINT_TO_POINTER(0)); | |
146 | 744 return (rfc959_ipv4_data_connection_new (request)); |
48 | 745 } |
58 | 746 |
48 | 747 pos = request->last_ftp_response + 4; |
748 while (!isdigit ((int) *pos) && *pos != '\0') | |
749 pos++; | |
58 | 750 |
48 | 751 if (*pos == '\0') |
752 { | |
186 | 753 request->logging_function (gftp_logging_error, request, |
58 | 754 _("Cannot find an IP address in PASV response '%s'\n"), |
755 request->last_ftp_response); | |
48 | 756 gftp_disconnect (request); |
84 | 757 return (GFTP_EFATAL); |
48 | 758 } |
58 | 759 |
48 | 760 if (sscanf (pos, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2], |
761 &temp[3], &temp[4], &temp[5]) != 6) | |
762 { | |
186 | 763 request->logging_function (gftp_logging_error, request, |
58 | 764 _("Cannot find an IP address in PASV response '%s'\n"), |
765 request->last_ftp_response); | |
48 | 766 gftp_disconnect (request); |
84 | 767 return (GFTP_EFATAL); |
48 | 768 } |
58 | 769 |
48 | 770 for (i = 0; i < 6; i++) |
771 ad[i] = (unsigned char) (temp[i] & 0xff); | |
772 | |
773 memcpy (&data_addr.sin_port, &ad[4], 2); | |
642 | 774 |
643 | 775 gftp_lookup_request_option (request, "ignore_pasv_address", |
776 &ignore_pasv_address); | |
777 if (ignore_pasv_address) | |
642 | 778 { |
944 | 779 memcpy (&data_addr.sin_addr, request->remote_addr, |
780 request->remote_addr_len); | |
642 | 781 |
782 pos = (char *) &data_addr.sin_addr; | |
677 | 783 request->logging_function (gftp_logging_error, request, |
642 | 784 _("Ignoring IP address in PASV response, connecting to %d.%d.%d.%d:%d\n"), |
785 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff, pos[3] & 0xff, | |
786 ntohs (data_addr.sin_port)); | |
787 } | |
788 else | |
789 memcpy (&data_addr.sin_addr, &ad[0], 4); | |
790 | |
169 | 791 if (connect (parms->data_connection, (struct sockaddr *) &data_addr, |
58 | 792 data_addr_len) == -1) |
48 | 793 { |
186 | 794 request->logging_function (gftp_logging_error, request, |
48 | 795 _("Cannot create a data connection: %s\n"), |
796 g_strerror (errno)); | |
797 gftp_disconnect (request); | |
84 | 798 return (GFTP_ERETRYABLE); |
48 | 799 } |
800 } | |
801 else | |
802 { | |
169 | 803 if (getsockname (request->datafd, (struct sockaddr *) &data_addr, |
58 | 804 &data_addr_len) == -1) |
805 { | |
186 | 806 request->logging_function (gftp_logging_error, request, |
58 | 807 _("Cannot get socket name: %s\n"), |
808 g_strerror (errno)); | |
809 gftp_disconnect (request); | |
84 | 810 return (GFTP_ERETRYABLE); |
58 | 811 } |
812 | |
48 | 813 data_addr.sin_port = 0; |
169 | 814 if (bind (parms->data_connection, (struct sockaddr *) &data_addr, |
58 | 815 data_addr_len) == -1) |
48 | 816 { |
186 | 817 request->logging_function (gftp_logging_error, request, |
48 | 818 _("Cannot bind a port: %s\n"), |
819 g_strerror (errno)); | |
820 gftp_disconnect (request); | |
84 | 821 return (GFTP_ERETRYABLE); |
48 | 822 } |
823 | |
169 | 824 if (getsockname (parms->data_connection, (struct sockaddr *) &data_addr, |
58 | 825 &data_addr_len) == -1) |
826 { | |
186 | 827 request->logging_function (gftp_logging_error, request, |
58 | 828 _("Cannot get socket name: %s\n"), |
829 g_strerror (errno)); | |
830 gftp_disconnect (request); | |
84 | 831 return (GFTP_ERETRYABLE); |
58 | 832 } |
833 | |
169 | 834 if (listen (parms->data_connection, 1) == -1) |
48 | 835 { |
186 | 836 request->logging_function (gftp_logging_error, request, |
48 | 837 _("Cannot listen on port %d: %s\n"), |
838 ntohs (data_addr.sin_port), | |
839 g_strerror (errno)); | |
840 gftp_disconnect (request); | |
84 | 841 return (GFTP_ERETRYABLE); |
48 | 842 } |
58 | 843 |
48 | 844 pos = (char *) &data_addr.sin_addr; |
845 pos1 = (char *) &data_addr.sin_port; | |
846 command = g_strdup_printf ("PORT %u,%u,%u,%u,%u,%u\r\n", | |
847 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff, | |
848 pos[3] & 0xff, pos1[0] & 0xff, | |
849 pos1[1] & 0xff); | |
847 | 850 resp = rfc959_send_command (request, command, -1, 1, 1); |
48 | 851 g_free (command); |
443 | 852 |
853 if (resp < 0) | |
854 return (resp); | |
855 else if (resp != '2') | |
48 | 856 { |
411 | 857 request->logging_function (gftp_logging_error, request, |
858 _("Invalid response '%c' received from server.\n"), | |
859 resp); | |
48 | 860 gftp_disconnect (request); |
84 | 861 return (GFTP_ERETRYABLE); |
48 | 862 } |
863 } | |
864 | |
865 return (0); | |
866 } | |
867 | |
868 | |
146 | 869 #ifdef HAVE_IPV6 |
870 | |
871 static int | |
872 rfc959_ipv6_data_connection_new (gftp_request * request) | |
873 { | |
874 struct sockaddr_in6 data_addr; | |
518 | 875 char *pos, buf[64], *command; |
463 | 876 intptr_t passive_transfer; |
169 | 877 rfc959_parms * parms; |
146 | 878 unsigned int port; |
518 | 879 int resp; |
146 | 880 |
169 | 881 parms = request->protocol_data; |
882 if ((parms->data_connection = socket (AF_INET6, SOCK_STREAM, IPPROTO_TCP)) < 0) | |
146 | 883 { |
186 | 884 request->logging_function (gftp_logging_error, request, |
313 | 885 _("Failed to create a IPv6 socket: %s\n"), |
146 | 886 g_strerror (errno)); |
887 gftp_disconnect (request); | |
888 return (GFTP_ERETRYABLE); | |
889 } | |
890 | |
182 | 891 if (fcntl (parms->data_connection, F_SETFD, 1) == -1) |
892 { | |
186 | 893 request->logging_function (gftp_logging_error, request, |
182 | 894 _("Error: Cannot set close on exec flag: %s\n"), |
895 g_strerror (errno)); | |
896 | |
897 return (GFTP_ERETRYABLE); | |
898 } | |
899 | |
146 | 900 /* This condition shouldn't happen. We better check anyway... */ |
944 | 901 if (sizeof (data_addr) != request->remote_addr_len) |
146 | 902 { |
186 | 903 request->logging_function (gftp_logging_error, request, |
146 | 904 _("Error: It doesn't look like we are connected via IPv6. Aborting connection.\n")); |
905 gftp_disconnect (request); | |
906 return (GFTP_EFATAL); | |
907 } | |
908 | |
944 | 909 memset (&data_addr, 0, sizeof (data_addr)); |
146 | 910 data_addr.sin6_family = AF_INET6; |
911 | |
912 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer); | |
913 if (passive_transfer) | |
914 { | |
847 | 915 resp = rfc959_send_command (request, "EPSV\r\n", -1, 1, 1); |
443 | 916 if (resp < 0) |
917 return (resp); | |
918 else if (resp != '2') | |
146 | 919 { |
920 gftp_set_request_option (request, "passive_transfer", | |
921 GINT_TO_POINTER(0)); | |
922 return (rfc959_ipv6_data_connection_new (request)); | |
923 } | |
924 | |
925 pos = request->last_ftp_response + 4; | |
926 while (*pos != '(' && *pos != '\0') | |
927 pos++; | |
928 | |
572 | 929 if (*pos == '\0' || *(pos + 1) == '\0') |
146 | 930 { |
186 | 931 request->logging_function (gftp_logging_error, request, |
146 | 932 _("Invalid EPSV response '%s'\n"), |
933 request->last_ftp_response); | |
934 gftp_disconnect (request); | |
935 return (GFTP_EFATAL); | |
936 } | |
937 | |
572 | 938 if (sscanf (pos + 1, "|||%u|", &port) != 1) |
146 | 939 { |
186 | 940 request->logging_function (gftp_logging_error, request, |
146 | 941 _("Invalid EPSV response '%s'\n"), |
942 request->last_ftp_response); | |
943 gftp_disconnect (request); | |
944 return (GFTP_EFATAL); | |
945 } | |
946 | |
944 | 947 memcpy (&data_addr, request->remote_addr, request->remote_addr_len); |
146 | 948 data_addr.sin6_port = htons (port); |
949 | |
169 | 950 if (connect (parms->data_connection, (struct sockaddr *) &data_addr, |
944 | 951 request->remote_addr_len) == -1) |
146 | 952 { |
186 | 953 request->logging_function (gftp_logging_error, request, |
146 | 954 _("Cannot create a data connection: %s\n"), |
955 g_strerror (errno)); | |
956 gftp_disconnect (request); | |
957 return (GFTP_ERETRYABLE); | |
958 } | |
959 } | |
960 else | |
961 { | |
944 | 962 memcpy (&data_addr, request->remote_addr, request->remote_addr_len); |
146 | 963 data_addr.sin6_port = 0; |
964 | |
169 | 965 if (bind (parms->data_connection, (struct sockaddr *) &data_addr, |
944 | 966 request->remote_addr_len) == -1) |
146 | 967 { |
186 | 968 request->logging_function (gftp_logging_error, request, |
146 | 969 _("Cannot bind a port: %s\n"), |
970 g_strerror (errno)); | |
971 gftp_disconnect (request); | |
972 return (GFTP_ERETRYABLE); | |
973 } | |
974 | |
169 | 975 if (getsockname (parms->data_connection, (struct sockaddr *) &data_addr, |
944 | 976 &request->remote_addr_len) == -1) |
146 | 977 { |
186 | 978 request->logging_function (gftp_logging_error, request, |
146 | 979 _("Cannot get socket name: %s\n"), |
980 g_strerror (errno)); | |
981 gftp_disconnect (request); | |
982 return (GFTP_ERETRYABLE); | |
983 } | |
984 | |
169 | 985 if (listen (parms->data_connection, 1) == -1) |
146 | 986 { |
186 | 987 request->logging_function (gftp_logging_error, request, |
146 | 988 _("Cannot listen on port %d: %s\n"), |
989 ntohs (data_addr.sin6_port), | |
990 g_strerror (errno)); | |
991 gftp_disconnect (request); | |
992 return (GFTP_ERETRYABLE); | |
993 } | |
994 | |
995 if (inet_ntop (AF_INET6, &data_addr.sin6_addr, buf, sizeof (buf)) == NULL) | |
996 { | |
186 | 997 request->logging_function (gftp_logging_error, request, |
146 | 998 _("Cannot get address of local socket: %s\n"), |
999 g_strerror (errno)); | |
1000 gftp_disconnect (request); | |
1001 return (GFTP_ERETRYABLE); | |
1002 } | |
1003 | |
1004 command = g_strdup_printf ("EPRT |2|%s|%d|\n", buf, | |
1005 ntohs (data_addr.sin6_port)); | |
1006 | |
847 | 1007 resp = rfc959_send_command (request, command, -1, 1, 1); |
146 | 1008 g_free (command); |
443 | 1009 |
1010 if (resp < 0) | |
1011 return (resp); | |
1012 else if (resp != '2') | |
146 | 1013 { |
1014 gftp_disconnect (request); | |
1015 return (GFTP_ERETRYABLE); | |
1016 } | |
1017 } | |
1018 | |
1019 return (0); | |
1020 } | |
1021 | |
1022 #endif /* HAVE_IPV6 */ | |
1023 | |
1024 | |
1025 static int | |
820 | 1026 rfc959_data_connection_new (gftp_request * request, int dont_try_to_reconnect) |
146 | 1027 { |
830 | 1028 int ret; |
1029 | |
146 | 1030 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
169 | 1031 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
146 | 1032 |
1033 #ifdef HAVE_IPV6 | |
547 | 1034 if (request->ai_family == AF_INET6) |
820 | 1035 ret = rfc959_ipv6_data_connection_new (request); |
146 | 1036 else |
820 | 1037 ret = rfc959_ipv4_data_connection_new (request); |
151 | 1038 #else |
820 | 1039 ret = rfc959_ipv4_data_connection_new (request); |
146 | 1040 #endif |
820 | 1041 |
1042 if (ret == GFTP_ETIMEDOUT && !dont_try_to_reconnect) | |
1043 { | |
1044 ret = gftp_connect (request); | |
1045 if (ret < 0) | |
1046 return (ret); | |
1047 | |
1048 return (rfc959_data_connection_new (request, 1)); | |
1049 } | |
1050 else | |
1051 return (ret); | |
146 | 1052 } |
1053 | |
1054 | |
48 | 1055 static int |
1056 rfc959_accept_active_connection (gftp_request * request) | |
1057 { | |
325 | 1058 int infd, ret; |
1059 intptr_t passive_transfer; | |
169 | 1060 rfc959_parms * parms; |
146 | 1061 #ifdef HAVE_IPV6 |
339 | 1062 struct sockaddr_in6 cli_addr; |
146 | 1063 #else |
339 | 1064 struct sockaddr_in cli_addr; |
146 | 1065 #endif |
195 | 1066 socklen_t cli_addr_len; |
48 | 1067 |
169 | 1068 parms = request->protocol_data; |
1069 | |
84 | 1070 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
169 | 1071 g_return_val_if_fail (parms->data_connection > 0, GFTP_EFATAL); |
122 | 1072 |
1073 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer); | |
1074 g_return_val_if_fail (!passive_transfer, GFTP_EFATAL); | |
48 | 1075 |
1076 cli_addr_len = sizeof (cli_addr); | |
58 | 1077 |
169 | 1078 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 0)) < 0) |
84 | 1079 return (ret); |
58 | 1080 |
169 | 1081 if ((infd = accept (parms->data_connection, (struct sockaddr *) &cli_addr, |
48 | 1082 &cli_addr_len)) == -1) |
1083 { | |
186 | 1084 request->logging_function (gftp_logging_error, request, |
48 | 1085 _("Cannot accept connection from server: %s\n"), |
1086 g_strerror (errno)); | |
1087 gftp_disconnect (request); | |
84 | 1088 return (GFTP_ERETRYABLE); |
48 | 1089 } |
1090 | |
169 | 1091 close (parms->data_connection); |
816 | 1092 parms->data_connection = infd; |
48 | 1093 |
169 | 1094 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0) |
84 | 1095 return (ret); |
58 | 1096 |
48 | 1097 return (0); |
1098 } | |
1099 | |
1100 | |
765 | 1101 static unsigned int |
254 | 1102 rfc959_is_ascii_transfer (gftp_request * request, const char *filename) |
122 | 1103 { |
1104 gftp_config_list_vars * tmplistvar; | |
1105 gftp_file_extensions * tempext; | |
325 | 1106 intptr_t ascii_transfers; |
122 | 1107 GList * templist; |
518 | 1108 size_t stlen; |
122 | 1109 |
1110 gftp_lookup_global_option ("ext", &tmplistvar); | |
254 | 1111 gftp_lookup_request_option (request, "ascii_transfers", &ascii_transfers); |
122 | 1112 |
1113 stlen = strlen (filename); | |
1114 for (templist = tmplistvar->list; templist != NULL; templist = templist->next) | |
1115 { | |
1116 tempext = templist->data; | |
1117 | |
1118 if (stlen >= tempext->stlen && | |
1119 strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0) | |
1120 { | |
1121 if (toupper (*tempext->ascii_binary == 'A')) | |
254 | 1122 ascii_transfers = 1; |
1123 else if (toupper (*tempext->ascii_binary == 'B')) | |
1124 ascii_transfers = 0; | |
122 | 1125 break; |
1126 } | |
1127 } | |
1128 | |
254 | 1129 return (ascii_transfers); |
122 | 1130 } |
1131 | |
1132 | |
309 | 1133 static int |
122 | 1134 rfc959_set_data_type (gftp_request * request, const char *filename) |
1135 { | |
765 | 1136 unsigned int new_ascii; |
122 | 1137 rfc959_parms * parms; |
1138 char *tempstr; | |
765 | 1139 int ret; |
122 | 1140 |
309 | 1141 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
122 | 1142 |
1143 parms = request->protocol_data; | |
254 | 1144 new_ascii = rfc959_is_ascii_transfer (request, filename); |
122 | 1145 |
169 | 1146 if (request->datafd > 0 && new_ascii != parms->is_ascii_transfer) |
122 | 1147 { |
1148 if (new_ascii) | |
1149 { | |
1150 tempstr = "TYPE A\r\n"; | |
1151 parms->is_ascii_transfer = 1; | |
1152 } | |
1153 else | |
1154 { | |
1155 tempstr = "TYPE I\r\n"; | |
254 | 1156 parms->is_ascii_transfer = 0; |
122 | 1157 } |
1158 | |
847 | 1159 if ((ret = rfc959_send_command (request, tempstr, -1, 1, 0)) < 0) |
309 | 1160 return (ret); |
122 | 1161 } |
1162 | |
309 | 1163 return (0); |
122 | 1164 } |
1165 | |
1166 | |
893 | 1167 static int |
1168 rfc959_setup_file_transfer (gftp_request * request, const char *filename, | |
1169 off_t startsize, char *transfer_command) | |
1 | 1170 { |
325 | 1171 intptr_t passive_transfer; |
169 | 1172 rfc959_parms * parms; |
893 | 1173 char *command; |
518 | 1174 int ret; |
1 | 1175 |
169 | 1176 parms = request->protocol_data; |
1 | 1177 |
309 | 1178 if ((ret = rfc959_set_data_type (request, filename)) < 0) |
1179 return (ret); | |
122 | 1180 |
169 | 1181 if (parms->data_connection < 0 && |
820 | 1182 (ret = rfc959_data_connection_new (request, 0)) < 0) |
1 | 1183 return (ret); |
1184 | |
169 | 1185 if ((ret = gftp_fd_set_sockblocking (request, parms->data_connection, 1)) < 0) |
84 | 1186 return (ret); |
1 | 1187 |
1188 if (startsize > 0) | |
1189 { | |
532 | 1190 command = g_strdup_printf ("REST " GFTP_OFF_T_PRINTF_MOD "\r\n", |
1191 startsize); | |
847 | 1192 ret = rfc959_send_command (request, command, -1, 1, 0); |
1 | 1193 g_free (command); |
1194 | |
518 | 1195 if (ret < 0) |
1196 return (ret); | |
1197 else if (ret != '3') | |
1 | 1198 { |
816 | 1199 rfc959_close_data_connection (request); |
84 | 1200 return (GFTP_ERETRYABLE); |
1 | 1201 } |
1202 } | |
1203 | |
893 | 1204 ret = rfc959_generate_and_send_command (request, transfer_command, filename, |
1205 1, 0); | |
442 | 1206 if (ret < 0) |
1207 return (ret); | |
1208 else if (ret != '1') | |
58 | 1209 { |
816 | 1210 rfc959_close_data_connection (request); |
858 | 1211 |
1212 if (ret == '5') | |
1213 return (GFTP_EFATAL); | |
1214 else | |
1215 return (GFTP_ERETRYABLE); | |
58 | 1216 } |
1 | 1217 |
122 | 1218 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer); |
1219 if (!passive_transfer && | |
1 | 1220 (ret = rfc959_accept_active_connection (request)) < 0) |
1221 return (ret); | |
1222 | |
893 | 1223 return (0); |
1224 } | |
1225 | |
1226 | |
1227 static off_t | |
895 | 1228 rfc959_get_file (gftp_request * request, const char *filename, |
893 | 1229 off_t startsize) |
1230 { | |
1231 char *tempstr; | |
1232 int ret; | |
1233 | |
1234 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
1235 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
1236 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); | |
1237 | |
1238 ret = rfc959_setup_file_transfer (request, filename, startsize, "RETR"); | |
1239 if (ret < 0) | |
1240 return (ret); | |
1241 | |
1 | 1242 if ((tempstr = strrchr (request->last_ftp_response, '(')) == NULL) |
1243 { | |
1244 tempstr = request->last_ftp_response + 4; | |
1245 while (!isdigit ((int) *tempstr) && *tempstr != '\0') | |
1246 tempstr++; | |
1247 } | |
1248 else | |
1249 tempstr++; | |
1250 | |
244 | 1251 return (gftp_parse_file_size (tempstr) + startsize); |
1 | 1252 } |
1253 | |
1254 | |
1255 static int | |
895 | 1256 rfc959_put_file (gftp_request * request, const char *filename, |
1 | 1257 off_t startsize, off_t totalsize) |
1258 { | |
169 | 1259 rfc959_parms * parms; |
426 | 1260 int ret; |
1 | 1261 |
84 | 1262 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1263 g_return_val_if_fail (filename != NULL, GFTP_EFATAL); | |
169 | 1264 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1265 |
309 | 1266 if ((ret = rfc959_set_data_type (request, filename)) < 0) |
1267 return (ret); | |
122 | 1268 |
895 | 1269 parms = request->protocol_data; |
169 | 1270 if (parms->data_connection < 0 && |
820 | 1271 (ret = rfc959_data_connection_new (request, 0)) < 0) |
1 | 1272 return (ret); |
1273 | |
893 | 1274 return (rfc959_setup_file_transfer (request, filename, startsize, "STOR")); |
1 | 1275 } |
1276 | |
58 | 1277 |
765 | 1278 static off_t |
1 | 1279 rfc959_transfer_file (gftp_request *fromreq, const char *fromfile, |
1280 off_t fromsize, gftp_request *toreq, | |
1281 const char *tofile, off_t tosize) | |
1282 { | |
1283 char *tempstr, *pos, *endpos; | |
426 | 1284 rfc959_parms * parms; |
84 | 1285 int ret; |
1 | 1286 |
84 | 1287 g_return_val_if_fail (fromreq != NULL, GFTP_EFATAL); |
1288 g_return_val_if_fail (fromfile != NULL, GFTP_EFATAL); | |
1289 g_return_val_if_fail (toreq != NULL, GFTP_EFATAL); | |
1290 g_return_val_if_fail (tofile != NULL, GFTP_EFATAL); | |
169 | 1291 g_return_val_if_fail (fromreq->datafd > 0, GFTP_EFATAL); |
1292 g_return_val_if_fail (toreq->datafd > 0, GFTP_EFATAL); | |
1 | 1293 |
847 | 1294 if ((ret = rfc959_send_command (fromreq, "PASV\r\n", -1, 1, 0)) < 0) |
84 | 1295 return (ret); |
442 | 1296 else if (ret != '2') |
1297 return (GFTP_ERETRYABLE); | |
1 | 1298 |
1299 pos = fromreq->last_ftp_response + 4; | |
1300 while (!isdigit ((int) *pos) && *pos != '\0') | |
1301 pos++; | |
1302 if (*pos == '\0') | |
84 | 1303 return (GFTP_EFATAL); |
1 | 1304 |
1305 endpos = pos; | |
1306 while (*endpos != ')' && *endpos != '\0') | |
1307 endpos++; | |
1308 if (*endpos == ')') | |
1309 *endpos = '\0'; | |
1310 | |
1311 tempstr = g_strconcat ("PORT ", pos, "\r\n", NULL); | |
847 | 1312 ret = rfc959_send_command (toreq, tempstr, -1, 1, 0); |
1 | 1313 g_free (tempstr); |
1314 | |
442 | 1315 if (ret < 0) |
1316 return (ret); | |
1317 else if (ret != '2') | |
1318 return (GFTP_ERETRYABLE); | |
1319 | |
830 | 1320 ret = rfc959_generate_and_send_command (fromreq, "RETR", fromfile, 0, 0); |
443 | 1321 if (ret < 0) |
1322 return (ret); | |
1323 | |
830 | 1324 ret = rfc959_generate_and_send_command (toreq, "STOR", tofile, 0, 0); |
443 | 1325 if (ret < 0) |
1326 return (ret); | |
1327 | |
292 | 1328 if ((ret = rfc959_read_response (fromreq, 1)) < 0) |
84 | 1329 return (ret); |
1330 | |
292 | 1331 if ((ret = rfc959_read_response (toreq, 1)) < 0) |
84 | 1332 return (ret); |
1 | 1333 |
426 | 1334 parms = fromreq->protocol_data; |
1335 parms->is_fxp_transfer = 1; | |
1336 | |
1337 parms = toreq->protocol_data; | |
1338 parms->is_fxp_transfer = 1; | |
1339 | |
1 | 1340 return (0); |
1341 } | |
1342 | |
1343 | |
1344 static int | |
1345 rfc959_end_transfer (gftp_request * request) | |
1346 { | |
169 | 1347 rfc959_parms * parms; |
84 | 1348 int ret; |
1349 | |
1350 g_return_val_if_fail (request != NULL, GFTP_EFATAL); | |
169 | 1351 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1352 |
169 | 1353 parms = request->protocol_data; |
426 | 1354 parms->is_fxp_transfer = 0; |
292 | 1355 |
816 | 1356 rfc959_close_data_connection (request); |
84 | 1357 |
292 | 1358 ret = rfc959_read_response (request, 1); |
84 | 1359 |
1360 if (ret < 0) | |
1361 return (ret); | |
1362 else if (ret == '2') | |
1363 return (0); | |
1364 else | |
1365 return (GFTP_ERETRYABLE); | |
1 | 1366 } |
1367 | |
1368 | |
1369 static int | |
40 | 1370 rfc959_abort_transfer (gftp_request * request) |
1371 { | |
1372 int ret; | |
1373 | |
84 | 1374 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
169 | 1375 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
40 | 1376 |
847 | 1377 if ((ret = rfc959_send_command (request, "ABOR\r\n", -1, 0, 0)) < 0) |
292 | 1378 return (ret); |
1379 | |
816 | 1380 rfc959_close_data_connection (request); |
40 | 1381 |
169 | 1382 if (request->datafd > 0) |
40 | 1383 { |
292 | 1384 if ((ret = rfc959_read_response (request, 0)) < 0) |
40 | 1385 gftp_disconnect (request); |
1386 } | |
292 | 1387 |
40 | 1388 return (0); |
1389 } | |
1390 | |
1391 | |
1392 static int | |
1 | 1393 rfc959_list_files (gftp_request * request) |
1394 { | |
325 | 1395 intptr_t show_hidden_files, resolve_symlinks, passive_transfer; |
1 | 1396 char *tempstr, parms[3]; |
518 | 1397 int ret; |
1 | 1398 |
84 | 1399 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
169 | 1400 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1401 |
820 | 1402 if ((ret = rfc959_data_connection_new (request, 0)) < 0) |
1 | 1403 return (ret); |
1404 | |
122 | 1405 gftp_lookup_request_option (request, "show_hidden_files", &show_hidden_files); |
1406 gftp_lookup_request_option (request, "resolve_symlinks", &resolve_symlinks); | |
1407 gftp_lookup_request_option (request, "passive_transfer", &passive_transfer); | |
1408 | |
1 | 1409 *parms = '\0'; |
1410 strcat (parms, show_hidden_files ? "a" : ""); | |
1411 strcat (parms, resolve_symlinks ? "L" : ""); | |
1412 tempstr = g_strconcat ("LIST", *parms != '\0' ? " -" : "", parms, "\r\n", | |
1413 NULL); | |
1414 | |
847 | 1415 ret = rfc959_send_command (request, tempstr, -1, 1, 0); |
1 | 1416 g_free (tempstr); |
1417 | |
442 | 1418 if (ret < 0) |
1419 return (ret); | |
1420 else if (ret != '1') | |
411 | 1421 { |
1422 request->logging_function (gftp_logging_error, request, | |
1423 _("Invalid response '%c' received from server.\n"), | |
1424 ret); | |
1425 return (GFTP_ERETRYABLE); | |
1426 } | |
1 | 1427 |
1428 ret = 0; | |
122 | 1429 if (!passive_transfer) |
1 | 1430 ret = rfc959_accept_active_connection (request); |
1431 | |
1432 return (ret); | |
1433 } | |
1434 | |
1435 | |
122 | 1436 static ssize_t |
1437 rfc959_get_next_file_chunk (gftp_request * request, char *buf, size_t size) | |
1438 { | |
301 | 1439 ssize_t num_read, ret; |
169 | 1440 rfc959_parms * parms; |
299 | 1441 int i, j; |
122 | 1442 |
169 | 1443 parms = request->protocol_data; |
426 | 1444 if (parms->is_fxp_transfer) |
1445 return (GFTP_ENOTRANS); | |
299 | 1446 |
390 | 1447 num_read = parms->data_conn_read (request, buf, size, parms->data_connection); |
122 | 1448 if (num_read < 0) |
1449 return (num_read); | |
1450 | |
301 | 1451 ret = num_read; |
299 | 1452 if (parms->is_ascii_transfer) |
122 | 1453 { |
1454 for (i = 0, j = 0; i < num_read; i++) | |
1455 { | |
1456 if (buf[i] != '\r') | |
1457 buf[j++] = buf[i]; | |
1458 else | |
301 | 1459 ret--; |
122 | 1460 } |
1461 } | |
1462 | |
301 | 1463 return (ret); |
122 | 1464 } |
1465 | |
1466 | |
1467 static ssize_t | |
1468 rfc959_put_next_file_chunk (gftp_request * request, char *buf, size_t size) | |
1469 { | |
818 | 1470 ssize_t num_wrote, ret; |
169 | 1471 rfc959_parms * parms; |
818 | 1472 char *tempstr, *pos; |
521 | 1473 size_t rsize, i, j; |
122 | 1474 |
169 | 1475 parms = request->protocol_data; |
1476 | |
426 | 1477 if (parms->is_fxp_transfer) |
1478 return (GFTP_ENOTRANS); | |
1479 | |
299 | 1480 if (parms->is_ascii_transfer) |
122 | 1481 { |
818 | 1482 rsize = size; |
1483 for (i = 1; i < size; i++) | |
122 | 1484 { |
818 | 1485 if (buf[i] == '\n' && buf[i - 1] != '\r') |
122 | 1486 rsize++; |
1487 } | |
1488 | |
1489 if (rsize != size) | |
1490 { | |
944 | 1491 tempstr = g_malloc0 (rsize); |
122 | 1492 |
1493 for (i = 0, j = 0; i < size; i++) | |
1494 { | |
1495 if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r') | |
1496 tempstr[j++] = '\r'; | |
1497 tempstr[j++] = buf[i]; | |
1498 } | |
1499 } | |
1500 else | |
1501 tempstr = buf; | |
1502 } | |
1503 else | |
1504 { | |
1505 rsize = size; | |
1506 tempstr = buf; | |
1507 } | |
1508 | |
818 | 1509 /* I need to ensure that the entire buffer has been transfered properly due |
1510 to the ascii conversion that may occur. | |
1511 FIXME - the ascii conversion doesn't occur properly when the \n occurs | |
1512 at the beginning of the buffer. I need to remember the last character | |
1513 in the previous buffer */ | |
1514 | |
1515 ret = rsize; | |
1516 pos = tempstr; | |
1517 while (rsize > 0) | |
1518 { | |
1519 num_wrote = parms->data_conn_write (request, pos, rsize, | |
1520 parms->data_connection); | |
1521 if (num_wrote < 0) | |
1522 { | |
1523 ret = num_wrote; | |
1524 break; | |
1525 } | |
1526 | |
1527 pos += num_wrote; | |
1528 rsize -= num_wrote; | |
1529 } | |
122 | 1530 |
1531 if (tempstr != buf) | |
1532 g_free (tempstr); | |
1533 | |
818 | 1534 return (ret); |
122 | 1535 } |
1536 | |
1537 | |
485 | 1538 static ssize_t |
1539 rfc959_get_next_dirlist_line (gftp_request * request, int fd, | |
1540 char *buf, size_t buflen) | |
1541 { | |
1542 ssize_t (*oldread_func) (gftp_request * request, void *ptr, size_t size, | |
1543 int fd); | |
1544 rfc959_parms * parms; | |
1545 ssize_t len; | |
1546 | |
1547 parms = request->protocol_data; | |
1548 | |
1549 oldread_func = request->read_function; | |
1550 request->read_function = parms->data_conn_read; | |
1551 len = gftp_get_line (request, &parms->dataconn_rbuf, buf, buflen, fd); | |
1552 request->read_function = oldread_func; | |
1553 | |
1554 return (len); | |
1555 } | |
1556 | |
1 | 1557 int |
58 | 1558 rfc959_get_next_file (gftp_request * request, gftp_file * fle, int fd) |
1 | 1559 { |
58 | 1560 rfc959_parms * parms; |
249 | 1561 char tempstr[1024]; |
516 | 1562 size_t stlen; |
58 | 1563 ssize_t len; |
1 | 1564 |
84 | 1565 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1566 g_return_val_if_fail (fle != NULL, GFTP_EFATAL); | |
1567 g_return_val_if_fail (fd > 0, GFTP_EFATAL); | |
1 | 1568 |
1569 if (request->last_dir_entry) | |
1570 { | |
1571 g_free (request->last_dir_entry); | |
1572 request->last_dir_entry = NULL; | |
1573 } | |
58 | 1574 |
1575 parms = request->protocol_data; | |
1576 | |
169 | 1577 if (fd == request->datafd) |
1578 fd = parms->data_connection; | |
1579 | |
1 | 1580 do |
1581 { | |
485 | 1582 len = rfc959_get_next_dirlist_line (request, fd, tempstr, |
1583 sizeof (tempstr)); | |
389 | 1584 if (len <= 0) |
1 | 1585 { |
598 | 1586 gftp_file_destroy (fle, 0); |
518 | 1587 return (len); |
1 | 1588 } |
1589 | |
485 | 1590 if (gftp_parse_ls (request, tempstr, fle, fd) != 0) |
1 | 1591 { |
58 | 1592 if (strncmp (tempstr, "total", strlen ("total")) != 0 && |
1593 strncmp (tempstr, _("total"), strlen (_("total"))) != 0) | |
186 | 1594 request->logging_function (gftp_logging_error, request, |
1 | 1595 _("Warning: Cannot parse listing %s\n"), |
1596 tempstr); | |
598 | 1597 gftp_file_destroy (fle, 0); |
1 | 1598 continue; |
1599 } | |
1600 else | |
1601 break; | |
1602 } | |
1603 while (1); | |
1604 | |
516 | 1605 stlen = strlen (tempstr); |
1 | 1606 if (!request->cached) |
1607 { | |
60 | 1608 request->last_dir_entry = g_strdup_printf ("%s\n", tempstr); |
516 | 1609 request->last_dir_entry_len = stlen + 1; |
1 | 1610 } |
1611 return (len); | |
1612 } | |
1613 | |
1614 | |
1615 static off_t | |
1616 rfc959_get_file_size (gftp_request * request, const char *filename) | |
1617 { | |
1618 int ret; | |
1619 | |
1620 g_return_val_if_fail (request != NULL, 0); | |
1621 g_return_val_if_fail (filename != NULL, 0); | |
169 | 1622 g_return_val_if_fail (request->datafd > 0, 0); |
1 | 1623 |
830 | 1624 ret = rfc959_generate_and_send_command (request, "SIZE", filename, 1, 0); |
1 | 1625 if (ret < 0) |
84 | 1626 return (ret); |
1 | 1627 |
1628 if (*request->last_ftp_response != '2') | |
1629 return (0); | |
830 | 1630 |
1 | 1631 return (strtol (request->last_ftp_response + 4, NULL, 10)); |
1632 } | |
1633 | |
1634 | |
1635 static int | |
1636 rfc959_rmdir (gftp_request * request, const char *directory) | |
1637 { | |
518 | 1638 int ret; |
1 | 1639 |
84 | 1640 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1641 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
169 | 1642 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1643 |
830 | 1644 ret = rfc959_generate_and_send_command (request, "RMD", directory, 1, 0); |
84 | 1645 if (ret < 0) |
1646 return (ret); | |
1647 else if (ret == '2') | |
1648 return (0); | |
1649 else | |
1650 return (GFTP_ERETRYABLE); | |
1 | 1651 } |
1652 | |
1653 | |
1654 static int | |
1655 rfc959_rmfile (gftp_request * request, const char *file) | |
1656 { | |
518 | 1657 int ret; |
1 | 1658 |
84 | 1659 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1660 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
169 | 1661 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1662 |
830 | 1663 ret = rfc959_generate_and_send_command (request, "DELE", file, 1, 0); |
84 | 1664 if (ret < 0) |
1665 return (ret); | |
1666 else if (ret == '2') | |
1667 return (0); | |
1668 else | |
1669 return (GFTP_ERETRYABLE); | |
1 | 1670 } |
1671 | |
1672 | |
1673 static int | |
1674 rfc959_mkdir (gftp_request * request, const char *directory) | |
1675 { | |
518 | 1676 int ret; |
1 | 1677 |
84 | 1678 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1679 g_return_val_if_fail (directory != NULL, GFTP_EFATAL); | |
169 | 1680 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1681 |
830 | 1682 ret = rfc959_generate_and_send_command (request, "MKD", directory, 1, 0); |
84 | 1683 if (ret < 0) |
1684 return (ret); | |
1685 else if (ret == '2') | |
1686 return (0); | |
1687 else | |
1688 return (GFTP_ERETRYABLE); | |
1 | 1689 } |
1690 | |
1691 | |
1692 static int | |
1693 rfc959_rename (gftp_request * request, const char *oldname, | |
1694 const char *newname) | |
1695 { | |
518 | 1696 int ret; |
1 | 1697 |
84 | 1698 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1699 g_return_val_if_fail (oldname != NULL, GFTP_EFATAL); | |
1700 g_return_val_if_fail (newname != NULL, GFTP_EFATAL); | |
169 | 1701 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1702 |
830 | 1703 ret = rfc959_generate_and_send_command (request, "RNFR", oldname, 1, 0); |
84 | 1704 if (ret < 0) |
1705 return (ret); | |
278 | 1706 else if (ret != '3') |
84 | 1707 return (GFTP_ERETRYABLE); |
1 | 1708 |
830 | 1709 ret = rfc959_generate_and_send_command (request, "RNTO", newname, 1, 0); |
84 | 1710 if (ret < 0) |
1711 return (ret); | |
1712 else if (ret == '2') | |
1713 return (0); | |
1714 else | |
1715 return (GFTP_ERETRYABLE); | |
1 | 1716 } |
1717 | |
1718 | |
1719 static int | |
499 | 1720 rfc959_chmod (gftp_request * request, const char *file, mode_t mode) |
1 | 1721 { |
865 | 1722 char *tempstr, *utf8; |
838 | 1723 size_t destlen; |
518 | 1724 int ret; |
1 | 1725 |
84 | 1726 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1727 g_return_val_if_fail (file != NULL, GFTP_EFATAL); | |
169 | 1728 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1729 |
988
63555c9744c2
remote charset should be specified by each bookmark entry.
Yoshiki Yazawa <yaz@honeyplanet.jp>
parents:
949
diff
changeset
|
1730 utf8 = gftp_remote_filename_from_utf8 (request, file, &destlen); |
830 | 1731 if (utf8 != NULL) |
1732 { | |
1733 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, utf8); | |
1734 g_free (utf8); | |
1735 } | |
1736 else | |
1737 tempstr = g_strdup_printf ("SITE CHMOD %o %s\r\n", mode, file); | |
541 | 1738 |
949 | 1739 ret = rfc959_send_command (request, tempstr, -1, 1, 0); |
1 | 1740 g_free (tempstr); |
84 | 1741 |
1742 if (ret < 0) | |
1743 return (ret); | |
1744 else if (ret == '2') | |
1745 return (0); | |
1746 else | |
1747 return (GFTP_ERETRYABLE); | |
1 | 1748 } |
1749 | |
1750 | |
1751 static int | |
478 | 1752 rfc959_site (gftp_request * request, int specify_site, const char *command) |
1 | 1753 { |
830 | 1754 char *tempstr, *utf8; |
847 | 1755 size_t len; |
518 | 1756 int ret; |
1 | 1757 |
84 | 1758 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1759 g_return_val_if_fail (command != NULL, GFTP_EFATAL); | |
169 | 1760 g_return_val_if_fail (request->datafd > 0, GFTP_EFATAL); |
1 | 1761 |
847 | 1762 utf8 = gftp_string_from_utf8 (request, -1, command, &len); |
830 | 1763 if (utf8 != NULL) |
1764 { | |
1765 if (specify_site) | |
847 | 1766 { |
1767 len += 7; | |
1768 tempstr = g_strconcat ("SITE ", utf8, "\r\n", NULL); | |
1769 } | |
830 | 1770 else |
847 | 1771 { |
1772 len += 2; | |
1773 tempstr = g_strconcat (utf8, "\r\n", NULL); | |
1774 } | |
830 | 1775 |
1776 g_free (utf8); | |
1777 } | |
478 | 1778 else |
830 | 1779 { |
1780 if (specify_site) | |
847 | 1781 { |
1782 len = strlen (command) + 7; | |
1783 tempstr = g_strconcat ("SITE ", command, "\r\n", NULL); | |
1784 } | |
830 | 1785 else |
847 | 1786 { |
1787 len = strlen (command) + 2; | |
1788 tempstr = g_strconcat (command, "\r\n", NULL); | |
1789 } | |
830 | 1790 } |
478 | 1791 |
847 | 1792 ret = rfc959_send_command (request, tempstr, len, 1, 0); |
1 | 1793 g_free (tempstr); |
84 | 1794 |
1795 if (ret < 0) | |
1796 return (ret); | |
1797 else if (ret == '2') | |
1798 return (0); | |
1799 else | |
1800 return (GFTP_ERETRYABLE); | |
58 | 1801 } |
1802 | |
1803 | |
513 | 1804 static int |
58 | 1805 rfc959_set_config_options (gftp_request * request) |
1806 { | |
122 | 1807 char *proxy_config; |
177 | 1808 int ret; |
58 | 1809 |
122 | 1810 gftp_lookup_request_option (request, "proxy_config", &proxy_config); |
1811 if (strcmp (proxy_config, "http") == 0) | |
58 | 1812 { |
177 | 1813 if ((ret = gftp_protocols[GFTP_HTTP_NUM].init (request)) < 0) |
1814 return (ret); | |
173 | 1815 |
122 | 1816 gftp_set_request_option (request, "proxy_config", "ftp"); |
58 | 1817 } |
177 | 1818 |
1819 return (0); | |
122 | 1820 } |
58 | 1821 |
1822 | |
122 | 1823 void |
1824 rfc959_register_module (void) | |
1825 { | |
1826 gftp_register_config_vars (config_vars); | |
1 | 1827 } |
1828 | |
1829 | |
516 | 1830 static void |
201 | 1831 rfc959_request_destroy (gftp_request * request) |
1832 { | |
1833 rfc959_parms * parms; | |
1834 | |
1835 parms = request->protocol_data; | |
1836 | |
1837 if (parms->datafd_rbuf != NULL) | |
1838 gftp_free_getline_buffer (&parms->datafd_rbuf); | |
1839 | |
1840 if (parms->dataconn_rbuf != NULL) | |
1841 gftp_free_getline_buffer (&parms->dataconn_rbuf); | |
1842 } | |
1843 | |
1844 | |
516 | 1845 static void |
309 | 1846 rfc959_copy_param_options (gftp_request * dest_request, |
1847 gftp_request * src_request) | |
1848 { | |
1849 rfc959_parms * dparms, * sparms; | |
1850 | |
1851 dparms = dest_request->protocol_data; | |
1852 sparms = src_request->protocol_data; | |
1853 | |
432 | 1854 dparms->data_connection = -1; |
309 | 1855 dparms->is_ascii_transfer = sparms->is_ascii_transfer; |
432 | 1856 dparms->is_fxp_transfer = sparms->is_fxp_transfer; |
1857 dparms->auth_tls_start = sparms->auth_tls_start; | |
1858 dparms->data_conn_read = sparms->data_conn_read; | |
1859 dparms->data_conn_write = sparms->data_conn_write; | |
1860 | |
1861 dest_request->read_function = src_request->read_function; | |
1862 dest_request->write_function = src_request->write_function; | |
309 | 1863 } |
1864 | |
1865 | |
173 | 1866 int |
48 | 1867 rfc959_init (gftp_request * request) |
1 | 1868 { |
169 | 1869 rfc959_parms * parms; |
227 | 1870 struct hostent *hent; |
1871 struct utsname unme; | |
1872 struct passwd *pw; | |
1873 char *tempstr; | |
169 | 1874 |
173 | 1875 g_return_val_if_fail (request != NULL, GFTP_EFATAL); |
1 | 1876 |
227 | 1877 gftp_lookup_global_option ("email", &tempstr); |
1878 if (tempstr == NULL || *tempstr == '\0') | |
1879 { | |
1880 /* If there is no email address specified, then we'll just use the | |
1881 currentuser@currenthost */ | |
1882 uname (&unme); | |
1883 pw = getpwuid (geteuid ()); | |
1884 hent = gethostbyname (unme.nodename); | |
1885 if (strchr (unme.nodename, '.') == NULL && hent != NULL) | |
1886 tempstr = g_strconcat (pw->pw_name, "@", hent->h_name, NULL); | |
1887 else | |
1888 tempstr = g_strconcat (pw->pw_name, "@", unme.nodename, NULL); | |
1889 gftp_set_global_option ("email", tempstr); | |
1890 g_free (tempstr); | |
1891 } | |
1892 | |
48 | 1893 request->protonum = GFTP_FTP_NUM; |
1894 request->init = rfc959_init; | |
309 | 1895 request->copy_param_options = rfc959_copy_param_options; |
201 | 1896 request->destroy = rfc959_request_destroy; |
168 | 1897 request->read_function = gftp_fd_read; |
1898 request->write_function = gftp_fd_write; | |
48 | 1899 request->connect = rfc959_connect; |
168 | 1900 request->post_connect = NULL; |
48 | 1901 request->disconnect = rfc959_disconnect; |
1902 request->get_file = rfc959_get_file; | |
1903 request->put_file = rfc959_put_file; | |
1904 request->transfer_file = rfc959_transfer_file; | |
122 | 1905 request->get_next_file_chunk = rfc959_get_next_file_chunk; |
1906 request->put_next_file_chunk = rfc959_put_next_file_chunk; | |
48 | 1907 request->end_transfer = rfc959_end_transfer; |
1908 request->abort_transfer = rfc959_abort_transfer; | |
500 | 1909 request->stat_filename = NULL; |
48 | 1910 request->list_files = rfc959_list_files; |
1911 request->get_next_file = rfc959_get_next_file; | |
485 | 1912 request->get_next_dirlist_line = rfc959_get_next_dirlist_line; |
48 | 1913 request->get_file_size = rfc959_get_file_size; |
1914 request->chdir = rfc959_chdir; | |
1915 request->rmdir = rfc959_rmdir; | |
1916 request->rmfile = rfc959_rmfile; | |
1917 request->mkdir = rfc959_mkdir; | |
1918 request->rename = rfc959_rename; | |
1919 request->chmod = rfc959_chmod; | |
818 | 1920 request->set_file_time = NULL; |
48 | 1921 request->site = rfc959_site; |
1922 request->parse_url = NULL; | |
63 | 1923 request->swap_socks = NULL; |
58 | 1924 request->set_config_options = rfc959_set_config_options; |
48 | 1925 request->url_prefix = "ftp"; |
1926 request->need_hostport = 1; | |
650 | 1927 request->need_username = 1; |
553 | 1928 request->need_password = 1; |
48 | 1929 request->use_cache = 1; |
1930 request->always_connected = 0; | |
832 | 1931 request->use_local_encoding = 0; |
169 | 1932 |
58 | 1933 request->protocol_data = g_malloc0 (sizeof (rfc959_parms)); |
169 | 1934 parms = request->protocol_data; |
1935 parms->data_connection = -1; | |
389 | 1936 parms->auth_tls_start = NULL; |
390 | 1937 parms->data_conn_read = gftp_fd_read; |
1938 parms->data_conn_write = gftp_fd_write; | |
169 | 1939 |
177 | 1940 return (gftp_set_config_options (request)); |
1 | 1941 } |
1942 |