Mercurial > gftp.yaz
annotate lib/rfc959.c @ 60:8a9324fb63a4
2002-11-21 Brian Masney <masneyb@gftp.org>
* lib/protocols.c (gftp_get_next_line) - fixed several bugs
* lib/cache.c - Don't do a cache lookup in gftp_new_cache_entry(). In
gftp_find_cache_entry(), don't log an error to the user if we can't
open up the cache file
* lib/rfc959.c lib/rfc2068.c lib/protocols.c - small cache fixes
* lib/cache.c lib/rfc2068.c lib/rfc959.c - pass full buffer size
instead of buffer size - 1 to gftp_get_line
author | masneyb |
---|---|
date | Fri, 22 Nov 2002 00:54:38 +0000 |
parents | c01d91c10f6c |
children | 41b71c4e5076 |
rev | line source |
---|---|
1 | 1 /*****************************************************************************/ |
2 /* rfc959.c - General purpose routines for the FTP protocol (RFC 959) */ | |
3 /* Copyright (C) 1998-2002 Brian Masney <masneyb@gftp.org> */ | |
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" | |
33 | 21 static const char cvsid[] = "$Id$"; |
1 | 22 |
58 | 23 typedef struct rfc959_params_tag |
24 { | |
25 gftp_getline_buffer * sockfd_rbuf, | |
26 * datafd_rbuf; | |
27 } rfc959_parms; | |
28 | |
29 | |
48 | 30 static int |
31 rfc959_read_response (gftp_request * request) | |
32 { | |
33 char tempstr[255], code[4]; | |
58 | 34 rfc959_parms * parms; |
35 ssize_t num_read; | |
48 | 36 |
37 g_return_val_if_fail (request != NULL, -2); | |
38 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 39 g_return_val_if_fail (request->sockfd > 0, -2); |
48 | 40 |
41 *code = '\0'; | |
42 if (request->last_ftp_response) | |
43 { | |
44 g_free (request->last_ftp_response); | |
45 request->last_ftp_response = NULL; | |
46 } | |
47 | |
58 | 48 parms = request->protocol_data; |
49 | |
48 | 50 do |
51 { | |
58 | 52 if ((num_read = gftp_get_line (request, &parms->sockfd_rbuf, tempstr, |
60 | 53 sizeof (tempstr), request->sockfd)) <= 0) |
48 | 54 break; |
58 | 55 |
48 | 56 if (isdigit ((int) *tempstr) && isdigit ((int) *(tempstr + 1)) |
57 && isdigit ((int) *(tempstr + 2))) | |
58 { | |
59 strncpy (code, tempstr, 3); | |
60 code[3] = ' '; | |
61 } | |
62 request->logging_function (gftp_logging_recv, request->user_data, | |
63 "%s\n", tempstr); | |
64 } | |
65 while (strncmp (code, tempstr, 4) != 0); | |
66 | |
58 | 67 if (num_read < 0) |
68 return (-1); | |
48 | 69 |
70 request->last_ftp_response = g_malloc (strlen (tempstr) + 1); | |
71 strcpy (request->last_ftp_response, tempstr); | |
72 | |
73 if (request->last_ftp_response[0] == '4' && | |
74 request->last_ftp_response[1] == '2') | |
75 gftp_disconnect (request); | |
76 | |
77 return (*request->last_ftp_response); | |
78 } | |
79 | |
80 | |
81 static int | |
82 rfc959_send_command (gftp_request * request, const char *command) | |
83 { | |
84 g_return_val_if_fail (request != NULL, -2); | |
85 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
86 g_return_val_if_fail (command != NULL, -2); | |
58 | 87 g_return_val_if_fail (request->sockfd > 0, -2); |
48 | 88 |
89 if (strncmp (command, "PASS", 4) == 0) | |
90 { | |
91 request->logging_function (gftp_logging_send, request->user_data, | |
92 "PASS xxxx\n"); | |
93 } | |
94 else if (strncmp (command, "ACCT", 4) == 0) | |
95 { | |
96 request->logging_function (gftp_logging_send, request->user_data, | |
97 "ACCT xxxx\n"); | |
98 } | |
99 else | |
100 { | |
101 request->logging_function (gftp_logging_send, request->user_data, "%s", | |
102 command); | |
103 } | |
104 | |
58 | 105 if (gftp_write (request, command, strlen (command), |
106 request->sockfd) < 0) | |
48 | 107 return (-1); |
108 | |
109 return (rfc959_read_response (request)); | |
110 } | |
111 | |
112 | |
113 static char * | |
114 parse_ftp_proxy_string (gftp_request * request) | |
115 { | |
116 char *startpos, *endpos, *oldstr, *newstr, *newval, *tempport; | |
117 | |
118 g_return_val_if_fail (request != NULL, NULL); | |
119 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, NULL); | |
1 | 120 |
48 | 121 newstr = g_malloc (1); |
122 *newstr = '\0'; | |
123 startpos = endpos = request->proxy_config; | |
124 while (*endpos != '\0') | |
125 { | |
126 tempport = NULL; | |
127 if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'p') | |
128 { | |
129 switch (tolower ((int) *(endpos + 2))) | |
130 { | |
131 case 'u': | |
132 newval = request->proxy_username; | |
133 break; | |
134 case 'p': | |
135 newval = request->proxy_password; | |
136 break; | |
137 case 'h': | |
138 newval = request->proxy_hostname; | |
139 break; | |
140 case 'o': | |
141 tempport = g_strdup_printf ("%d", request->proxy_port); | |
142 newval = tempport; | |
143 break; | |
144 case 'a': | |
145 newval = request->proxy_account; | |
146 break; | |
147 default: | |
148 endpos++; | |
149 continue; | |
150 } | |
151 } | |
152 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'h') | |
153 { | |
154 switch (tolower ((int) *(endpos + 2))) | |
155 { | |
156 case 'u': | |
157 newval = request->username; | |
158 break; | |
159 case 'p': | |
160 newval = request->password; | |
161 break; | |
162 case 'h': | |
163 newval = request->hostname; | |
164 break; | |
165 case 'o': | |
166 tempport = g_strdup_printf ("%d", request->port); | |
167 newval = tempport; | |
168 break; | |
169 case 'a': | |
170 newval = request->account; | |
171 break; | |
172 default: | |
173 endpos++; | |
174 continue; | |
175 } | |
176 } | |
177 else if (*endpos == '%' && tolower ((int) *(endpos + 1)) == 'n') | |
178 { | |
179 *endpos = '\0'; | |
180 oldstr = newstr; | |
181 newstr = g_strconcat (oldstr, startpos, "\r\n", NULL); | |
182 g_free (oldstr); | |
183 endpos += 2; | |
184 startpos = endpos; | |
185 continue; | |
186 } | |
187 else | |
188 { | |
189 endpos++; | |
190 continue; | |
191 } | |
1 | 192 |
48 | 193 *endpos = '\0'; |
194 oldstr = newstr; | |
195 if (!newval) | |
196 newstr = g_strconcat (oldstr, startpos, NULL); | |
197 else | |
198 newstr = g_strconcat (oldstr, startpos, newval, NULL); | |
199 if (tempport) | |
200 { | |
201 g_free (tempport); | |
202 tempport = NULL; | |
203 } | |
204 g_free (oldstr); | |
205 endpos += 3; | |
206 startpos = endpos; | |
207 } | |
208 return (newstr); | |
209 } | |
210 | |
211 | |
212 static int | |
58 | 213 rfc959_getcwd (gftp_request * request) |
214 { | |
215 char *pos, *dir; | |
216 int ret; | |
217 | |
218 ret = rfc959_send_command (request, "PWD\r\n"); | |
219 if (ret < 0) | |
220 return (-1); | |
221 else if (ret != '2') | |
222 { | |
223 request->logging_function (gftp_logging_error, request->user_data, | |
224 _("Received invalid response to PWD command: '%s'\n"), | |
225 request->last_ftp_response); | |
226 gftp_disconnect (request); | |
227 return (-2); | |
228 } | |
229 | |
230 if ((pos = strchr (request->last_ftp_response, '"')) == NULL) | |
231 { | |
232 request->logging_function (gftp_logging_error, request->user_data, | |
233 _("Received invalid response to PWD command: '%s'\n"), | |
234 request->last_ftp_response); | |
235 gftp_disconnect (request); | |
236 return (-2); | |
237 } | |
238 | |
239 dir = pos + 1; | |
240 | |
241 if ((pos = strchr (dir, '"')) == NULL) | |
242 { | |
243 request->logging_function (gftp_logging_error, request->user_data, | |
244 _("Received invalid response to PWD command: '%s'\n"), | |
245 request->last_ftp_response); | |
246 gftp_disconnect (request); | |
247 return (-2); | |
248 } | |
249 | |
250 *pos = '\0'; | |
251 | |
252 if (request->directory) | |
253 g_free (request->directory); | |
254 | |
255 request->directory = g_malloc (strlen (dir) + 1); | |
256 strcpy (request->directory, dir); | |
257 return (0); | |
258 } | |
259 | |
260 | |
261 static int | |
48 | 262 rfc959_chdir (gftp_request * request, const char *directory) |
263 { | |
58 | 264 char ret, *tempstr; |
48 | 265 |
266 g_return_val_if_fail (request != NULL, -2); | |
267 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
268 g_return_val_if_fail (directory != NULL, -2); | |
269 | |
270 if (strcmp (directory, "..") == 0) | |
271 ret = rfc959_send_command (request, "CDUP\r\n"); | |
272 else | |
273 { | |
274 tempstr = g_strconcat ("CWD ", directory, "\r\n", NULL); | |
275 ret = rfc959_send_command (request, tempstr); | |
276 g_free (tempstr); | |
277 } | |
278 | |
279 if (ret != '2') | |
280 return (-2); | |
281 | |
282 if (directory != request->directory) | |
283 { | |
58 | 284 if (rfc959_getcwd (request) < 0) |
285 return (-1); | |
48 | 286 } |
287 | |
288 return (0); | |
1 | 289 } |
290 | |
291 | |
292 static int | |
293 rfc959_connect (gftp_request * request) | |
294 { | |
58 | 295 char tempchar, *startpos, *endpos, *tempstr; |
296 int ret, resp; | |
1 | 297 |
298 g_return_val_if_fail (request != NULL, -2); | |
299 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
300 g_return_val_if_fail (request->hostname != NULL, -2); | |
301 | |
58 | 302 if (request->sockfd > 0) |
303 return (0); | |
304 | |
7 | 305 if (request->username == NULL || *request->username == '\0') |
306 { | |
307 gftp_set_username (request, "anonymous"); | |
308 gftp_set_password (request, emailaddr); | |
309 } | |
310 else if (strcasecmp (request->username, "anonymous") == 0) | |
311 gftp_set_password (request, emailaddr); | |
312 | |
58 | 313 if ((request->sockfd = gftp_connect_server (request, "ftp")) < 0) |
1 | 314 return (-1); |
315 | |
316 /* Get the banner */ | |
317 if (rfc959_read_response (request) != '2') | |
318 { | |
319 gftp_disconnect (request); | |
320 return (-2); | |
321 } | |
322 | |
323 /* Login the proxy server if available */ | |
324 if (request->use_proxy) | |
325 { | |
326 resp = '3'; | |
327 startpos = endpos = tempstr = parse_ftp_proxy_string (request); | |
328 while ((resp == '3' || resp == '2') && *startpos != '\0') | |
329 { | |
330 if (*endpos == '\n' || *endpos == '\0') | |
331 { | |
332 tempchar = *(endpos + 1); | |
333 if (*endpos != '\0') | |
334 *(endpos + 1) = '\0'; | |
335 if ((resp = rfc959_send_command (request, startpos)) < 0) | |
336 return (-2); | |
337 if (*endpos != '\0') | |
338 *(endpos + 1) = tempchar; | |
339 else | |
340 break; | |
341 startpos = endpos + 1; | |
342 } | |
343 endpos++; | |
344 } | |
345 g_free (tempstr); | |
346 } | |
347 else | |
348 { | |
349 tempstr = g_strconcat ("USER ", request->username, "\r\n", NULL); | |
350 resp = rfc959_send_command (request, tempstr); | |
351 g_free (tempstr); | |
352 if (resp < 0) | |
353 return (-2); | |
354 if (resp == '3') | |
355 { | |
356 tempstr = g_strconcat ("PASS ", request->password, "\r\n", NULL); | |
357 resp = rfc959_send_command (request, tempstr); | |
358 g_free (tempstr); | |
359 if (resp < 0) | |
360 return (-2); | |
361 } | |
362 if (resp == '3' && request->account) | |
363 { | |
364 tempstr = g_strconcat ("ACCT ", request->account, "\r\n", NULL); | |
365 resp = rfc959_send_command (request, tempstr); | |
366 g_free (tempstr); | |
367 if (resp < 0) | |
368 return (-2); | |
369 } | |
370 } | |
371 | |
372 if (resp != '2') | |
373 { | |
374 gftp_disconnect (request); | |
375 return (-2); | |
376 } | |
377 | |
378 if (request->data_type == GFTP_TYPE_BINARY) | |
379 tempstr = "TYPE I\r\n"; | |
380 else | |
381 tempstr = "TYPE A\r\n"; | |
382 | |
383 if (rfc959_send_command (request, tempstr) < 0) | |
384 return (-2); | |
385 | |
386 ret = -1; | |
387 if (request->directory != NULL && *request->directory != '\0') | |
388 { | |
389 ret = rfc959_chdir (request, request->directory); | |
58 | 390 if (request->sockfd < 0) |
1 | 391 return (-2); |
392 } | |
393 | |
394 if (ret != 0) | |
395 { | |
58 | 396 if (rfc959_getcwd (request) < 0) |
397 return (-1); | |
1 | 398 } |
399 | |
58 | 400 if (request->sockfd < 0) |
1 | 401 return (-2); |
402 | |
403 return (0); | |
404 } | |
405 | |
406 | |
407 static void | |
408 rfc959_disconnect (gftp_request * request) | |
409 { | |
410 g_return_if_fail (request != NULL); | |
411 g_return_if_fail (request->protonum == GFTP_FTP_NUM); | |
412 | |
58 | 413 if (request->sockfd > 0) |
1 | 414 { |
415 request->logging_function (gftp_logging_misc, request->user_data, | |
416 _("Disconnecting from site %s\n"), | |
417 request->hostname); | |
58 | 418 close (request->sockfd); |
419 request->sockfd = -1; | |
420 if (request->datafd > 0) | |
1 | 421 { |
58 | 422 close (request->datafd); |
423 request->datafd = -1; | |
1 | 424 } |
425 } | |
426 } | |
427 | |
428 | |
48 | 429 static int |
430 rfc959_data_connection_new (gftp_request * request) | |
431 { | |
432 char *pos, *pos1, resp, *command; | |
433 struct sockaddr_in data_addr; | |
434 size_t data_addr_len; | |
435 unsigned int temp[6]; | |
436 unsigned char ad[6]; | |
58 | 437 int i; |
48 | 438 |
439 g_return_val_if_fail (request != NULL, -2); | |
440 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 441 g_return_val_if_fail (request->sockfd > 0, -2); |
48 | 442 |
58 | 443 if ((request->datafd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) |
48 | 444 { |
445 request->logging_function (gftp_logging_error, request->user_data, | |
446 _("Failed to create a socket: %s\n"), | |
447 g_strerror (errno)); | |
448 gftp_disconnect (request); | |
449 return (-1); | |
450 } | |
451 | |
452 data_addr_len = sizeof (data_addr); | |
453 memset (&data_addr, 0, data_addr_len); | |
454 data_addr.sin_family = AF_INET; | |
455 | |
456 if (request->transfer_type == gftp_transfer_passive) | |
457 { | |
458 if ((resp = rfc959_send_command (request, "PASV\r\n")) != '2') | |
459 { | |
58 | 460 if (request->sockfd < 0) |
48 | 461 return (-2); |
462 | |
463 request->transfer_type = gftp_transfer_active; | |
464 return (rfc959_data_connection_new (request)); | |
465 } | |
58 | 466 |
48 | 467 pos = request->last_ftp_response + 4; |
468 while (!isdigit ((int) *pos) && *pos != '\0') | |
469 pos++; | |
58 | 470 |
48 | 471 if (*pos == '\0') |
472 { | |
58 | 473 request->logging_function (gftp_logging_error, request->user_data, |
474 _("Cannot find an IP address in PASV response '%s'\n"), | |
475 request->last_ftp_response); | |
48 | 476 gftp_disconnect (request); |
477 return (-2); | |
478 } | |
58 | 479 |
48 | 480 if (sscanf (pos, "%u,%u,%u,%u,%u,%u", &temp[0], &temp[1], &temp[2], |
481 &temp[3], &temp[4], &temp[5]) != 6) | |
482 { | |
58 | 483 request->logging_function (gftp_logging_error, request->user_data, |
484 _("Cannot find an IP address in PASV response '%s'\n"), | |
485 request->last_ftp_response); | |
48 | 486 gftp_disconnect (request); |
487 return (-2); | |
488 } | |
58 | 489 |
48 | 490 for (i = 0; i < 6; i++) |
491 ad[i] = (unsigned char) (temp[i] & 0xff); | |
492 | |
493 memcpy (&data_addr.sin_addr, &ad[0], 4); | |
494 memcpy (&data_addr.sin_port, &ad[4], 2); | |
58 | 495 if (connect (request->datafd, (struct sockaddr *) &data_addr, |
496 data_addr_len) == -1) | |
48 | 497 { |
498 request->logging_function (gftp_logging_error, request->user_data, | |
499 _("Cannot create a data connection: %s\n"), | |
500 g_strerror (errno)); | |
501 gftp_disconnect (request); | |
502 return (-1); | |
503 } | |
504 } | |
505 else | |
506 { | |
58 | 507 if (getsockname (request->sockfd, (struct sockaddr *) &data_addr, |
508 &data_addr_len) == -1) | |
509 { | |
510 request->logging_function (gftp_logging_error, request->user_data, | |
511 _("Cannot get socket name: %s\n"), | |
512 g_strerror (errno)); | |
513 gftp_disconnect (request); | |
514 return (-1); | |
515 } | |
516 | |
48 | 517 data_addr.sin_port = 0; |
58 | 518 if (bind (request->datafd, (struct sockaddr *) &data_addr, |
519 data_addr_len) == -1) | |
48 | 520 { |
521 request->logging_function (gftp_logging_error, request->user_data, | |
522 _("Cannot bind a port: %s\n"), | |
523 g_strerror (errno)); | |
524 gftp_disconnect (request); | |
525 return (-1); | |
526 } | |
527 | |
58 | 528 if (getsockname (request->datafd, (struct sockaddr *) &data_addr, |
529 &data_addr_len) == -1) | |
530 { | |
531 request->logging_function (gftp_logging_error, request->user_data, | |
532 _("Cannot get socket name: %s\n"), | |
533 g_strerror (errno)); | |
534 gftp_disconnect (request); | |
535 return (-1); | |
536 } | |
537 | |
538 if (listen (request->datafd, 1) == -1) | |
48 | 539 { |
540 request->logging_function (gftp_logging_error, request->user_data, | |
541 _("Cannot listen on port %d: %s\n"), | |
542 ntohs (data_addr.sin_port), | |
543 g_strerror (errno)); | |
544 gftp_disconnect (request); | |
545 return (-1); | |
546 } | |
58 | 547 |
48 | 548 pos = (char *) &data_addr.sin_addr; |
549 pos1 = (char *) &data_addr.sin_port; | |
550 command = g_strdup_printf ("PORT %u,%u,%u,%u,%u,%u\r\n", | |
551 pos[0] & 0xff, pos[1] & 0xff, pos[2] & 0xff, | |
552 pos[3] & 0xff, pos1[0] & 0xff, | |
553 pos1[1] & 0xff); | |
554 resp = rfc959_send_command (request, command); | |
555 g_free (command); | |
556 if (resp != '2') | |
557 { | |
558 gftp_disconnect (request); | |
559 return (-2); | |
560 } | |
561 } | |
562 | |
563 return (0); | |
564 } | |
565 | |
566 | |
567 static int | |
568 rfc959_accept_active_connection (gftp_request * request) | |
569 { | |
570 struct sockaddr_in cli_addr; | |
571 size_t cli_addr_len; | |
572 int infd; | |
573 | |
574 g_return_val_if_fail (request != NULL, -2); | |
575 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 576 g_return_val_if_fail (request->datafd > 0, -2); |
48 | 577 g_return_val_if_fail (request->transfer_type == gftp_transfer_active, -2); |
578 | |
579 cli_addr_len = sizeof (cli_addr); | |
58 | 580 |
581 if (gftp_set_sockblocking (request, request->datafd, 0) == -1) | |
582 return (-1); | |
583 | |
584 if ((infd = accept (request->datafd, (struct sockaddr *) &cli_addr, | |
48 | 585 &cli_addr_len)) == -1) |
586 { | |
587 request->logging_function (gftp_logging_error, request->user_data, | |
588 _("Cannot accept connection from server: %s\n"), | |
589 g_strerror (errno)); | |
590 gftp_disconnect (request); | |
591 return (-1); | |
592 } | |
593 | |
58 | 594 close (request->datafd); |
48 | 595 |
58 | 596 request->datafd = infd; |
597 if (gftp_set_sockblocking (request, request->datafd, 1) == -1) | |
598 return (-1); | |
599 | |
48 | 600 return (0); |
601 } | |
602 | |
603 | |
58 | 604 static off_t |
605 rfc959_get_file (gftp_request * request, const char *filename, int fd, | |
1 | 606 off_t startsize) |
607 { | |
608 char *command, *tempstr, resp; | |
58 | 609 int ret; |
1 | 610 |
611 g_return_val_if_fail (request != NULL, -2); | |
612 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
613 g_return_val_if_fail (filename != NULL, -2); | |
58 | 614 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 615 |
58 | 616 if (fd > 0) |
1 | 617 request->datafd = fd; |
618 | |
58 | 619 if (request->datafd < 0 && |
1 | 620 (ret = rfc959_data_connection_new (request)) < 0) |
621 return (ret); | |
622 | |
58 | 623 if (gftp_set_sockblocking (request, request->datafd, 1) == -1) |
624 return (-1); | |
1 | 625 |
626 if (startsize > 0) | |
627 { | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
628 #if defined (_LARGEFILE_SOURCE) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
629 command = g_strdup_printf ("REST %lld\r\n", startsize); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
630 #else |
1 | 631 command = g_strdup_printf ("REST %ld\r\n", startsize); |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
632 #endif |
1 | 633 resp = rfc959_send_command (request, command); |
634 g_free (command); | |
635 | |
636 if (resp != '3') | |
637 { | |
58 | 638 close (request->datafd); |
639 request->datafd = -1; | |
1 | 640 return (-2); |
641 } | |
642 } | |
643 | |
644 tempstr = g_strconcat ("RETR ", filename, "\r\n", NULL); | |
645 ret = rfc959_send_command (request, tempstr); | |
646 g_free (tempstr); | |
647 | |
648 if (ret != '1') | |
58 | 649 { |
650 close (request->datafd); | |
651 request->datafd = -1; | |
652 return (-2); | |
653 } | |
1 | 654 |
655 if (request->transfer_type == gftp_transfer_active && | |
656 (ret = rfc959_accept_active_connection (request)) < 0) | |
657 return (ret); | |
658 | |
659 if ((tempstr = strrchr (request->last_ftp_response, '(')) == NULL) | |
660 { | |
661 tempstr = request->last_ftp_response + 4; | |
662 while (!isdigit ((int) *tempstr) && *tempstr != '\0') | |
663 tempstr++; | |
664 } | |
665 else | |
666 tempstr++; | |
667 | |
668 return (strtol (tempstr, NULL, 10) + startsize); | |
669 } | |
670 | |
671 | |
672 static int | |
58 | 673 rfc959_put_file (gftp_request * request, const char *filename, int fd, |
1 | 674 off_t startsize, off_t totalsize) |
675 { | |
676 char *command, *tempstr, resp; | |
58 | 677 int ret; |
1 | 678 |
679 g_return_val_if_fail (request != NULL, -2); | |
680 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
681 g_return_val_if_fail (filename != NULL, -2); | |
58 | 682 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 683 |
58 | 684 if (fd > 0) |
1 | 685 fd = request->datafd; |
686 | |
58 | 687 if (request->datafd < 0 && |
1 | 688 (ret = rfc959_data_connection_new (request)) < 0) |
689 return (ret); | |
690 | |
58 | 691 if (gftp_set_sockblocking (request, request->datafd, 1) == -1) |
692 return (-1); | |
1 | 693 |
694 if (startsize > 0) | |
695 { | |
14
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
696 #if defined (_LARGEFILE_SOURCE) |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
697 command = g_strdup_printf ("REST %lld\r\n", startsize); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
698 #else |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
699 command = g_strdup_printf ("REST %ld\r\n", startsize); |
83090328581e
* More largefile support. Hopefully all that is left is the configure stuff
masneyb
parents:
7
diff
changeset
|
700 #endif |
1 | 701 resp = rfc959_send_command (request, command); |
702 g_free (command); | |
703 if (resp != '3') | |
704 { | |
58 | 705 close (request->datafd); |
706 request->datafd = -1; | |
1 | 707 return (-2); |
708 } | |
709 } | |
710 | |
711 tempstr = g_strconcat ("STOR ", filename, "\r\n", NULL); | |
712 ret = rfc959_send_command (request, tempstr); | |
713 g_free (tempstr); | |
714 if (ret != '1') | |
58 | 715 { |
716 close (request->datafd); | |
717 request->datafd = -1; | |
718 return (-2); | |
719 } | |
1 | 720 |
721 if (request->transfer_type == gftp_transfer_active && | |
722 (ret = rfc959_accept_active_connection (request)) < 0) | |
723 return (ret); | |
724 | |
725 return (0); | |
726 } | |
727 | |
58 | 728 |
1 | 729 static long |
730 rfc959_transfer_file (gftp_request *fromreq, const char *fromfile, | |
731 off_t fromsize, gftp_request *toreq, | |
732 const char *tofile, off_t tosize) | |
733 { | |
734 char *tempstr, *pos, *endpos; | |
735 | |
736 g_return_val_if_fail (fromreq != NULL, -2); | |
737 g_return_val_if_fail (fromfile != NULL, -2); | |
738 g_return_val_if_fail (toreq != NULL, -2); | |
739 g_return_val_if_fail (tofile != NULL, -2); | |
58 | 740 g_return_val_if_fail (fromreq->sockfd > 0, -2); |
741 g_return_val_if_fail (toreq->sockfd > 0, -2); | |
1 | 742 |
743 fromreq->transfer_type = gftp_transfer_passive; | |
744 toreq->transfer_type = gftp_transfer_active; | |
745 | |
58 | 746 if (rfc959_send_command (fromreq, "PASV\r\n") != '2') |
1 | 747 return (-2); |
748 | |
749 pos = fromreq->last_ftp_response + 4; | |
750 while (!isdigit ((int) *pos) && *pos != '\0') | |
751 pos++; | |
752 if (*pos == '\0') | |
753 return (-2); | |
754 | |
755 endpos = pos; | |
756 while (*endpos != ')' && *endpos != '\0') | |
757 endpos++; | |
758 if (*endpos == ')') | |
759 *endpos = '\0'; | |
760 | |
761 tempstr = g_strconcat ("PORT ", pos, "\r\n", NULL); | |
15
82fabd6ef1c4
FXP fixes (from Tobias Gruetzmacher <tobias@portfolio16.de>)
masneyb
parents:
14
diff
changeset
|
762 if (rfc959_send_command (toreq, tempstr) != '2') |
82fabd6ef1c4
FXP fixes (from Tobias Gruetzmacher <tobias@portfolio16.de>)
masneyb
parents:
14
diff
changeset
|
763 { |
82fabd6ef1c4
FXP fixes (from Tobias Gruetzmacher <tobias@portfolio16.de>)
masneyb
parents:
14
diff
changeset
|
764 g_free (tempstr); |
82fabd6ef1c4
FXP fixes (from Tobias Gruetzmacher <tobias@portfolio16.de>)
masneyb
parents:
14
diff
changeset
|
765 return (-2); |
82fabd6ef1c4
FXP fixes (from Tobias Gruetzmacher <tobias@portfolio16.de>)
masneyb
parents:
14
diff
changeset
|
766 } |
1 | 767 g_free (tempstr); |
768 | |
769 tempstr = g_strconcat ("RETR ", fromfile, "\r\n", NULL); | |
58 | 770 if (gftp_write (fromreq, tempstr, strlen (tempstr), |
771 fromreq->sockfd) < 0) | |
772 { | |
773 g_free (tempstr); | |
774 return (-2); | |
775 } | |
1 | 776 g_free (tempstr); |
777 | |
778 tempstr = g_strconcat ("STOR ", tofile, "\r\n", NULL); | |
58 | 779 if (gftp_write (toreq, tempstr, strlen (tempstr), toreq->sockfd) < 0) |
780 { | |
781 g_free (tempstr); | |
782 return (-2); | |
783 } | |
1 | 784 g_free (tempstr); |
785 | |
786 if (rfc959_read_response (fromreq) < 0) | |
787 return (-2); | |
788 if (rfc959_read_response (toreq) < 0) | |
789 return (-2); | |
790 | |
791 return (0); | |
792 } | |
793 | |
794 | |
795 static int | |
796 rfc959_end_transfer (gftp_request * request) | |
797 { | |
798 g_return_val_if_fail (request != NULL, -2); | |
799 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 800 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 801 |
58 | 802 if (request->datafd > 0) |
1 | 803 { |
58 | 804 close (request->datafd); |
805 request->datafd = -1; | |
1 | 806 } |
807 return (rfc959_read_response (request) == '2' ? 0 : -2); | |
808 } | |
809 | |
810 | |
811 static int | |
40 | 812 rfc959_abort_transfer (gftp_request * request) |
813 { | |
814 int ret; | |
815 | |
816 g_return_val_if_fail (request != NULL, -2); | |
817 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 818 g_return_val_if_fail (request->sockfd > 0, -2); |
40 | 819 |
58 | 820 if (request->datafd > 0) |
40 | 821 { |
58 | 822 close (request->datafd); |
823 request->datafd = -1; | |
40 | 824 } |
825 | |
826 /* We need to read two lines of output. The first one is acknowleging | |
827 the transfer and the second line acknowleges the ABOR command */ | |
58 | 828 if (rfc959_send_command (request, "ABOR\r\n") < 0) |
829 return (-2); | |
40 | 830 |
58 | 831 if (request->sockfd > 0) |
40 | 832 { |
58 | 833 if ((ret = rfc959_read_response (request)) < 0) |
40 | 834 gftp_disconnect (request); |
835 } | |
836 | |
837 return (0); | |
838 } | |
839 | |
840 | |
841 static int | |
1 | 842 rfc959_list_files (gftp_request * request) |
843 { | |
844 char *tempstr, parms[3]; | |
845 int ret; | |
846 | |
847 g_return_val_if_fail (request != NULL, -2); | |
848 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
58 | 849 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 850 |
851 if ((ret = rfc959_data_connection_new (request)) < 0) | |
852 return (ret); | |
853 | |
854 *parms = '\0'; | |
855 strcat (parms, show_hidden_files ? "a" : ""); | |
856 strcat (parms, resolve_symlinks ? "L" : ""); | |
857 tempstr = g_strconcat ("LIST", *parms != '\0' ? " -" : "", parms, "\r\n", | |
858 NULL); | |
859 | |
860 ret = rfc959_send_command (request, tempstr); | |
861 g_free (tempstr); | |
862 | |
863 if (ret != '1') | |
864 return (-2); | |
865 | |
866 ret = 0; | |
867 if (request->transfer_type == gftp_transfer_active) | |
868 ret = rfc959_accept_active_connection (request); | |
869 | |
870 return (ret); | |
871 } | |
872 | |
873 | |
874 int | |
58 | 875 rfc959_get_next_file (gftp_request * request, gftp_file * fle, int fd) |
1 | 876 { |
58 | 877 rfc959_parms * parms; |
1 | 878 char tempstr[255]; |
58 | 879 ssize_t len; |
1 | 880 |
881 g_return_val_if_fail (request != NULL, -2); | |
882 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
883 g_return_val_if_fail (fle != NULL, -2); | |
58 | 884 g_return_val_if_fail (fd > 0, -2); |
1 | 885 |
886 if (request->last_dir_entry) | |
887 { | |
888 g_free (request->last_dir_entry); | |
889 request->last_dir_entry = NULL; | |
890 } | |
58 | 891 |
892 parms = request->protocol_data; | |
893 | |
1 | 894 do |
895 { | |
58 | 896 if ((len = gftp_get_line (request, &parms->datafd_rbuf, |
60 | 897 tempstr, sizeof (tempstr), fd)) <= 0) |
1 | 898 { |
899 gftp_file_destroy (fle); | |
58 | 900 return ((int) len); |
1 | 901 } |
902 | |
903 if (gftp_parse_ls (tempstr, fle) != 0) | |
904 { | |
58 | 905 if (strncmp (tempstr, "total", strlen ("total")) != 0 && |
906 strncmp (tempstr, _("total"), strlen (_("total"))) != 0) | |
907 request->logging_function (gftp_logging_error, request->user_data, | |
1 | 908 _("Warning: Cannot parse listing %s\n"), |
909 tempstr); | |
910 gftp_file_destroy (fle); | |
911 continue; | |
912 } | |
913 else | |
914 break; | |
915 } | |
916 while (1); | |
917 | |
918 len = strlen (tempstr); | |
919 if (!request->cached) | |
920 { | |
60 | 921 request->last_dir_entry = g_strdup_printf ("%s\n", tempstr); |
922 request->last_dir_entry_len = len + 1; | |
1 | 923 } |
924 return (len); | |
925 } | |
926 | |
927 | |
928 static int | |
929 rfc959_set_data_type (gftp_request * request, int data_type) | |
930 { | |
931 char *tempstr; | |
932 | |
933 g_return_val_if_fail (request != NULL, -2); | |
934 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
935 | |
58 | 936 if (request->sockfd > 0 && request->data_type != data_type) |
1 | 937 { |
938 if (data_type == GFTP_TYPE_BINARY) | |
939 tempstr = "TYPE I\r\n"; | |
940 else | |
941 tempstr = "TYPE A\r\n"; | |
942 | |
943 if (rfc959_send_command (request, tempstr) != '2') | |
944 return (-2); | |
945 } | |
946 request->data_type = data_type; | |
947 return (0); | |
948 } | |
949 | |
950 | |
951 static off_t | |
952 rfc959_get_file_size (gftp_request * request, const char *filename) | |
953 { | |
954 char *tempstr; | |
955 int ret; | |
956 | |
957 g_return_val_if_fail (request != NULL, 0); | |
958 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
959 g_return_val_if_fail (filename != NULL, 0); | |
58 | 960 g_return_val_if_fail (request->sockfd > 0, 0); |
1 | 961 |
962 tempstr = g_strconcat ("SIZE ", filename, "\r\n", NULL); | |
963 ret = rfc959_send_command (request, tempstr); | |
964 g_free (tempstr); | |
965 if (ret < 0) | |
966 return (-2); | |
967 | |
968 if (*request->last_ftp_response != '2') | |
969 return (0); | |
970 return (strtol (request->last_ftp_response + 4, NULL, 10)); | |
971 } | |
972 | |
973 | |
974 static int | |
975 rfc959_rmdir (gftp_request * request, const char *directory) | |
976 { | |
977 char *tempstr, ret; | |
978 | |
979 g_return_val_if_fail (request != NULL, -2); | |
980 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
981 g_return_val_if_fail (directory != NULL, -2); | |
58 | 982 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 983 |
984 tempstr = g_strconcat ("RMD ", directory, "\r\n", NULL); | |
985 ret = rfc959_send_command (request, tempstr); | |
986 g_free (tempstr); | |
987 return (ret == '2' ? 0 : -2); | |
988 } | |
989 | |
990 | |
991 static int | |
992 rfc959_rmfile (gftp_request * request, const char *file) | |
993 { | |
994 char *tempstr, ret; | |
995 | |
996 g_return_val_if_fail (request != NULL, -2); | |
997 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
998 g_return_val_if_fail (file != NULL, -2); | |
58 | 999 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 1000 |
1001 tempstr = g_strconcat ("DELE ", file, "\r\n", NULL); | |
1002 ret = rfc959_send_command (request, tempstr); | |
1003 g_free (tempstr); | |
1004 return (ret == '2' ? 0 : -2); | |
1005 } | |
1006 | |
1007 | |
1008 static int | |
1009 rfc959_mkdir (gftp_request * request, const char *directory) | |
1010 { | |
1011 char *tempstr, ret; | |
1012 | |
1013 g_return_val_if_fail (request != NULL, -2); | |
1014 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
1015 g_return_val_if_fail (directory != NULL, -2); | |
58 | 1016 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 1017 |
1018 tempstr = g_strconcat ("MKD ", directory, "\r\n", NULL); | |
1019 ret = rfc959_send_command (request, tempstr); | |
1020 g_free (tempstr); | |
1021 return (ret == '2' ? 0 : -2); | |
1022 } | |
1023 | |
1024 | |
1025 static int | |
1026 rfc959_rename (gftp_request * request, const char *oldname, | |
1027 const char *newname) | |
1028 { | |
1029 char *tempstr, ret; | |
1030 | |
1031 g_return_val_if_fail (request != NULL, -2); | |
1032 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
1033 g_return_val_if_fail (oldname != NULL, -2); | |
1034 g_return_val_if_fail (newname != NULL, -2); | |
58 | 1035 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 1036 |
1037 tempstr = g_strconcat ("RNFR ", oldname, "\r\n", NULL); | |
1038 ret = rfc959_send_command (request, tempstr); | |
1039 g_free (tempstr); | |
1040 if (ret != '3') | |
1041 return (-2); | |
1042 | |
1043 tempstr = g_strconcat ("RNTO ", newname, "\r\n", NULL); | |
1044 ret = rfc959_send_command (request, tempstr); | |
1045 g_free (tempstr); | |
1046 return (ret == '2' ? 0 : -2); | |
1047 } | |
1048 | |
1049 | |
1050 static int | |
1051 rfc959_chmod (gftp_request * request, const char *file, int mode) | |
1052 { | |
1053 char *tempstr, ret; | |
1054 | |
1055 g_return_val_if_fail (request != NULL, -2); | |
1056 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
1057 g_return_val_if_fail (file != NULL, -2); | |
58 | 1058 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 1059 |
1060 tempstr = g_malloc (strlen (file) + (mode / 10) + 16); | |
1061 sprintf (tempstr, "SITE CHMOD %d %s\r\n", mode, file); | |
1062 ret = rfc959_send_command (request, tempstr); | |
1063 g_free (tempstr); | |
1064 return (ret == '2' ? 0 : -2); | |
1065 } | |
1066 | |
1067 | |
1068 static int | |
1069 rfc959_site (gftp_request * request, const char *command) | |
1070 { | |
1071 char *tempstr, ret; | |
1072 | |
1073 g_return_val_if_fail (request != NULL, -2); | |
1074 g_return_val_if_fail (request->protonum == GFTP_FTP_NUM, -2); | |
1075 g_return_val_if_fail (command != NULL, -2); | |
58 | 1076 g_return_val_if_fail (request->sockfd > 0, -2); |
1 | 1077 |
1078 tempstr = g_strconcat ("SITE ", command, "\r\n", NULL); | |
1079 ret = rfc959_send_command (request, tempstr); | |
1080 g_free (tempstr); | |
58 | 1081 return (request->sockfd > 0 ? ret : -2); |
1082 } | |
1083 | |
1084 | |
1085 static void | |
1086 rfc959_set_config_options (gftp_request * request) | |
1087 { | |
1088 request->transfer_type = passive_transfer ? gftp_transfer_passive : gftp_transfer_active; | |
1089 | |
1090 if (strcmp (proxy_config, "http") != 0) | |
1091 { | |
1092 gftp_set_proxy_hostname (request, firewall_host); | |
1093 gftp_set_proxy_port (request, firewall_port); | |
1094 gftp_set_proxy_username (request, firewall_username); | |
1095 gftp_set_proxy_password (request, firewall_password); | |
1096 gftp_set_proxy_account (request, firewall_account); | |
1097 gftp_set_proxy_config (request, proxy_config); | |
1098 } | |
1099 else | |
1100 { | |
1101 gftp_set_proxy_hostname (request, http_proxy_host); | |
1102 gftp_set_proxy_port (request, http_proxy_port); | |
1103 gftp_set_proxy_username (request, http_proxy_username); | |
1104 gftp_set_proxy_password (request, http_proxy_password); | |
1105 | |
1106 | |
1107 if (request->proxy_config == NULL) | |
1108 { | |
1109 gftp_protocols[GFTP_HTTP_NUM].init (request); | |
1110 request->proxy_config = g_strdup ("ftp"); | |
1111 } | |
1112 } | |
1 | 1113 } |
1114 | |
1115 | |
48 | 1116 void |
1117 rfc959_init (gftp_request * request) | |
1 | 1118 { |
48 | 1119 g_return_if_fail (request != NULL); |
1 | 1120 |
48 | 1121 request->protonum = GFTP_FTP_NUM; |
1122 request->init = rfc959_init; | |
1123 request->destroy = NULL; | |
1124 request->connect = rfc959_connect; | |
1125 request->disconnect = rfc959_disconnect; | |
1126 request->get_file = rfc959_get_file; | |
1127 request->put_file = rfc959_put_file; | |
1128 request->transfer_file = rfc959_transfer_file; | |
1129 request->get_next_file_chunk = NULL; | |
1130 request->put_next_file_chunk = NULL; | |
1131 request->end_transfer = rfc959_end_transfer; | |
1132 request->abort_transfer = rfc959_abort_transfer; | |
1133 request->list_files = rfc959_list_files; | |
1134 request->get_next_file = rfc959_get_next_file; | |
1135 request->set_data_type = rfc959_set_data_type; | |
1136 request->get_file_size = rfc959_get_file_size; | |
1137 request->chdir = rfc959_chdir; | |
1138 request->rmdir = rfc959_rmdir; | |
1139 request->rmfile = rfc959_rmfile; | |
1140 request->mkdir = rfc959_mkdir; | |
1141 request->rename = rfc959_rename; | |
1142 request->chmod = rfc959_chmod; | |
1143 request->set_file_time = NULL; | |
1144 request->site = rfc959_site; | |
1145 request->parse_url = NULL; | |
58 | 1146 request->set_config_options = rfc959_set_config_options; |
48 | 1147 request->url_prefix = "ftp"; |
1148 request->protocol_name = "FTP"; | |
1149 request->need_hostport = 1; | |
1150 request->need_userpass = 1; | |
1151 request->use_cache = 1; | |
1152 request->use_threads = 1; | |
1153 request->always_connected = 0; | |
58 | 1154 request->protocol_data = g_malloc0 (sizeof (rfc959_parms)); |
48 | 1155 gftp_set_config_options (request); |
1 | 1156 } |
1157 |