comparison lib/protocols.c @ 1:8b1883341c6f

Initial revision
author masneyb
date Mon, 05 Aug 2002 19:46:57 +0000
parents
children a171df6764a7
comparison
equal deleted inserted replaced
0:674ed97069fd 1:8b1883341c6f
1 /*****************************************************************************/
2 /* protocols.c - Skeleton functions for the protocols gftp supports */
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"
21
22 static time_t parse_time ( char **str );
23 static int gftp_parse_ls_eplf ( char *str,
24 gftp_file * fle );
25 static int gftp_parse_ls_unix ( char *str,
26 int cols,
27 gftp_file * fle );
28 static int gftp_parse_ls_nt ( char *str,
29 gftp_file * fle );
30 static int gftp_parse_ls_novell ( char *str,
31 gftp_file * fle );
32 static char *copy_token ( char **dest,
33 char *source );
34 static char *goto_next_token ( char *pos );
35 static GList * gftp_get_dir_listing ( gftp_transfer * transfer,
36 int getothdir );
37 static GHashTable * gftp_gen_dir_hash ( gftp_request * request );
38 static void gftp_destroy_dir_hash ( GHashTable * dirhash );
39 static void destroy_hash_ent ( gpointer key,
40 gpointer value,
41 gpointer user_data );
42
43 gftp_request *
44 gftp_request_new (void)
45 {
46 gftp_request *request;
47
48 request = g_malloc0 (sizeof (*request));
49 request->sockfd = NULL;
50 request->datafd = NULL;
51 request->data_type = GFTP_TYPE_BINARY;
52 return (request);
53 }
54
55
56 void
57 gftp_request_destroy (gftp_request * request)
58 {
59 g_return_if_fail (request != NULL);
60
61 gftp_disconnect (request);
62
63 if (request->destroy != NULL)
64 request->destroy (request);
65
66 if (request->hostname)
67 g_free (request->hostname);
68 if (request->username)
69 g_free (request->username);
70 if (request->password)
71 {
72 memset (request->password, 0, strlen (request->password));
73 g_free (request->password);
74 }
75 if (request->account)
76 {
77 memset (request->account, 0, strlen (request->account));
78 g_free (request->account);
79 }
80 if (request->directory)
81 g_free (request->directory);
82 if (request->proxy_config)
83 g_free (request->proxy_config);
84 if (request->proxy_hostname)
85 g_free (request->proxy_hostname);
86 if (request->proxy_username)
87 g_free (request->proxy_username);
88 if (request->proxy_password)
89 g_free (request->proxy_password);
90 if (request->proxy_account)
91 g_free (request->proxy_account);
92 if (request->last_ftp_response)
93 g_free (request->last_ftp_response);
94 if (request->protocol_data)
95 g_free (request->protocol_data);
96 if (request->sftpserv_path)
97 g_free (request->sftpserv_path);
98 memset (request, 0, sizeof (*request));
99 g_free (request);
100 }
101
102
103 void
104 gftp_file_destroy (gftp_file * file)
105 {
106 g_return_if_fail (file != NULL);
107
108 if (file->file)
109 g_free (file->file);
110 if (file->user)
111 g_free (file->user);
112 if (file->group)
113 g_free (file->group);
114 if (file->attribs)
115 g_free (file->attribs);
116 if (file->destfile)
117 g_free (file->destfile);
118 memset (file, 0, sizeof (*file));
119 }
120
121
122 int
123 gftp_connect (gftp_request * request)
124 {
125 g_return_val_if_fail (request != NULL, -2);
126
127 if (request->connect == NULL)
128 return (-2);
129
130 if (request->sftpserv_path == NULL)
131 {
132 switch (request->protonum)
133 {
134 case GFTP_SSH_NUM:
135 request->sftpserv_path = g_strconcat (ssh1_sftp_path, NULL);
136 break;
137 case GFTP_SSHV2_NUM:
138 request->sftpserv_path = g_strconcat (ssh2_sftp_path, NULL);
139 break;
140 }
141 }
142
143 gftp_set_config_options (request);
144
145 return (request->connect (request));
146 }
147
148
149 void
150 gftp_disconnect (gftp_request * request)
151 {
152 g_return_if_fail (request != NULL);
153
154 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
155 if (request->hostp)
156 freeaddrinfo (request->hostp);
157 #endif
158 request->hostp = NULL;
159
160 if (request->sftpserv_path != NULL)
161 {
162 g_free (request->sftpserv_path);
163 request->sftpserv_path = NULL;
164 }
165
166 request->cached = 0;
167 if (request->disconnect == NULL)
168 return;
169 request->disconnect (request);
170 }
171
172
173 size_t
174 gftp_get_file (gftp_request * request, const char *filename, FILE * fd,
175 size_t startsize)
176 {
177 g_return_val_if_fail (request != NULL, -2);
178
179 request->cached = 0;
180 if (request->get_file == NULL)
181 return (-2);
182 return (request->get_file (request, filename, fd, startsize));
183 }
184
185
186 int
187 gftp_put_file (gftp_request * request, const char *filename, FILE * fd,
188 size_t startsize, size_t totalsize)
189 {
190 g_return_val_if_fail (request != NULL, -2);
191
192 request->cached = 0;
193 if (request->put_file == NULL)
194 return (-2);
195 return (request->put_file (request, filename, fd, startsize, totalsize));
196 }
197
198
199 long
200 gftp_transfer_file (gftp_request * fromreq, const char *fromfile,
201 FILE * fromfd, size_t fromsize,
202 gftp_request * toreq, const char *tofile,
203 FILE * tofd, size_t tosize)
204 {
205 long size;
206
207 g_return_val_if_fail (fromreq != NULL, -2);
208 g_return_val_if_fail (fromfile != NULL, -2);
209 g_return_val_if_fail (toreq != NULL, -2);
210 g_return_val_if_fail (tofile != NULL, -2);
211
212 if (strcmp (fromreq->protocol_name, toreq->protocol_name) == 0)
213 {
214 if (fromreq->transfer_file == NULL)
215 return (-2);
216 return (fromreq->transfer_file (fromreq, fromfile, fromsize, toreq,
217 tofile, tosize));
218 }
219
220 fromreq->cached = 0;
221 toreq->cached = 0;
222 if ((size = gftp_get_file (fromreq, fromfile, fromfd, tosize)) < 0)
223 return (-2);
224
225 if (gftp_put_file (toreq, tofile, tofd, tosize, size) != 0)
226 {
227 gftp_end_transfer (fromreq);
228 return (-2);
229 }
230
231 return (size);
232 }
233
234
235 size_t
236 gftp_get_next_file_chunk (gftp_request * request, char *buf, size_t size)
237 {
238 struct timeval tv;
239 fd_set fset;
240 size_t len;
241
242 g_return_val_if_fail (request != NULL, -2);
243 g_return_val_if_fail (buf != NULL, -2);
244
245 if (request->get_next_file_chunk != NULL)
246 return (request->get_next_file_chunk (request, buf, size));
247
248 FD_ZERO (&fset);
249 FD_SET (fileno (request->datafd), &fset);
250 tv.tv_sec = request->network_timeout;
251 tv.tv_usec = 0;
252 if (select (fileno (request->datafd) + 1, &fset, NULL, NULL, &tv) <= 0)
253 {
254 request->logging_function (gftp_logging_error, request->user_data,
255 _("Connection to %s timed out\n"),
256 request->hostname);
257 gftp_disconnect (request);
258 return (-1);
259 }
260
261 if ((len = read (fileno (request->datafd), buf, size)) == -1)
262 {
263 request->logging_function (gftp_logging_error, request->user_data,
264 _("Error reading from host %s: %s\n"),
265 request->hostname,
266 g_strerror (errno));
267 gftp_disconnect (request);
268 return (-1);
269 }
270 return (len);
271 }
272
273
274 size_t
275 gftp_put_next_file_chunk (gftp_request * request, char *buf, size_t size)
276 {
277 struct timeval tv;
278 size_t len, ret;
279 fd_set fset;
280 char *pos;
281
282 g_return_val_if_fail (request != NULL, -2);
283
284 ret = size;
285 if (request->put_next_file_chunk != NULL)
286 return (request->put_next_file_chunk (request, buf, size));
287
288 if (size == 0)
289 return (0);
290
291 pos = buf;
292 while (size > 0)
293 {
294 FD_ZERO (&fset);
295 FD_SET (fileno (request->datafd), &fset);
296 tv.tv_sec = request->network_timeout;
297 tv.tv_usec = 0;
298 if (!select (fileno (request->datafd) + 1, NULL, &fset, NULL, &tv))
299 {
300 request->logging_function (gftp_logging_error, request->user_data,
301 _("Connection to %s timed out\n"),
302 request->hostname);
303 gftp_disconnect (request);
304 return (-1);
305 }
306
307 if ((len = write (fileno (request->datafd), pos, size)) < 0)
308 {
309 request->logging_function (gftp_logging_error, request->user_data,
310 _("Error writing to host %s: %s\n"),
311 request->hostname,
312 g_strerror (errno));
313 gftp_disconnect (request);
314 return (-1);
315 }
316 size -= len;
317 pos += len;
318 }
319
320 return (ret);
321 }
322
323
324 int
325 gftp_end_transfer (gftp_request * request)
326 {
327 int ret;
328
329 g_return_val_if_fail (request != NULL, -2);
330
331 if (request->end_transfer == NULL)
332 return (-2);
333
334 ret = 0;
335 if (request->cachefd != NULL)
336 {
337 fclose (request->cachefd);
338 request->cachefd = NULL;
339 }
340
341 if (!request->cached)
342 ret = request->end_transfer (request);
343
344 if (request->last_dir_entry)
345 {
346 g_free (request->last_dir_entry);
347 request->last_dir_entry = NULL;
348 request->last_dir_entry_len = 0;
349 }
350
351 return (ret);
352 }
353
354
355 int
356 gftp_list_files (gftp_request * request)
357 {
358 FILE * fd;
359
360 g_return_val_if_fail (request != NULL, -2);
361
362 request->cached = 0;
363 if (request->use_cache && (fd = gftp_find_cache_entry (request)) != NULL)
364 {
365 request->logging_function (gftp_logging_misc, request->user_data,
366 _("Loading directory listing %s from cache\n"),
367 request->directory);
368
369 request->cachefd = fd;
370 request->cached = 1;
371 return (0);
372 }
373 else if (request->use_cache)
374 {
375 request->cachefd = gftp_new_cache_entry (request);
376 request->cached = 0;
377 }
378
379 if (request->list_files == NULL)
380 return (-2);
381 return (request->list_files (request));
382 }
383
384
385 int
386 gftp_get_next_file (gftp_request * request, char *filespec, gftp_file * fle)
387 {
388 FILE * fd;
389 int ret;
390
391 g_return_val_if_fail (request != NULL, -2);
392
393 if (request->get_next_file == NULL)
394 return (-2);
395
396 if (request->cached && request->cachefd != NULL)
397 fd = request->cachefd;
398 else
399 fd = request->datafd;
400
401 memset (fle, 0, sizeof (*fle));
402 do
403 {
404 gftp_file_destroy (fle);
405 ret = request->get_next_file (request, fle, fd);
406
407 if (ret >= 0 && !request->cached && request->cachefd != NULL &&
408 request->last_dir_entry != NULL)
409 {
410 fwrite (request->last_dir_entry, 1, request->last_dir_entry_len,
411 request->cachefd);
412 if (ferror (request->cachefd))
413 {
414 request->logging_function (gftp_logging_error, request->user_data,
415 _("Error: Cannot write to cache: %s\n"),
416 g_strerror (errno));
417 fclose (request->cachefd);
418 request->cachefd = NULL;
419 }
420 }
421 } while (ret > 0 && !gftp_match_filespec (fle->file, filespec));
422
423 return (ret);
424 }
425
426
427 int
428 gftp_parse_url (gftp_request * request, const char *url)
429 {
430 char *pos, *endpos, *endhostpos, *str, tempchar;
431 const char *stpos;
432 int len, i;
433
434 g_return_val_if_fail (request != NULL, -2);
435 g_return_val_if_fail (url != NULL, -2);
436
437 for (stpos = url; *stpos == ' '; stpos++);
438
439 if ((pos = strstr (stpos, "://")) != NULL)
440 {
441 *pos = '\0';
442
443 for (i = 0; gftp_protocols[i].url_prefix; i++)
444 {
445 if (strcmp (gftp_protocols[i].url_prefix, stpos) == 0)
446 break;
447 }
448
449 if (gftp_protocols[i].url_prefix == NULL)
450 return (-2);
451 *pos = ':';
452 }
453 else
454 {
455 for (i = 0; gftp_protocols[i].url_prefix; i++)
456 {
457 if (strcmp (gftp_protocols[i].name, default_protocol) == 0)
458 break;
459 }
460
461 if (gftp_protocols[i].url_prefix == NULL)
462 i = GFTP_FTP_NUM;
463 }
464
465 gftp_protocols[i].init (request);
466
467 if (request->parse_url != NULL)
468 return (request->parse_url (request, url));
469
470 if (i == GFTP_LOCAL_NUM)
471 {
472 request->directory = g_malloc (strlen (stpos + 6) + 1);
473 strcpy (request->directory, stpos + 6);
474 return (0);
475 }
476
477 for (; *stpos == ' '; stpos++);
478 str = g_malloc (strlen (stpos) + 1);
479 strcpy (str, stpos);
480 for (pos = str + strlen (str) - 1; *pos == ' '; pos--)
481 *pos = '\0';
482
483 pos = str;
484 len = strlen (request->url_prefix);
485 if (strncmp (pos, request->url_prefix, len) == 0
486 && strncmp (pos + len, "://", 3) == 0)
487 pos += len + 3;
488
489 if ((endhostpos = strchr (pos, '@')) != NULL)
490 {
491 /* A user/password was entered */
492 if ((endpos = strchr (pos, ':')) == NULL || endhostpos < endpos)
493 {
494 /* No password was entered */
495 gftp_set_password (request, "");
496 endpos = endhostpos;
497 }
498
499 *endpos = '\0';
500 gftp_set_username (request, pos);
501
502 pos = endpos + 1;
503 if ((endpos = strchr (pos, '@')) != NULL)
504 {
505 if (strchr (endpos + 1, '@') != NULL)
506 endpos = strchr (endpos + 1, '@');
507 *endpos = '\0';
508 gftp_set_password (request, pos);
509
510 pos = endpos + 1;
511 }
512 }
513 else
514 {
515 gftp_set_username (request, "anonymous");
516 if (request->password)
517 {
518 g_free (request->password);
519 request->password = NULL;
520 }
521 gftp_set_password (request, emailaddr);
522 }
523
524 /* Now get the hostname and an optional port and optional directory */
525 endhostpos = pos + strlen (pos);
526 if ((endpos = strchr (pos, ':')) != NULL)
527 endhostpos = endpos;
528 else if ((endpos = strchr (pos, '/')) != NULL)
529 endhostpos = endpos;
530 tempchar = *endhostpos;
531 *endhostpos = '\0';
532 gftp_set_hostname (request, pos);
533 *endhostpos = tempchar;
534
535 if ((endpos = strchr (pos, ':')) != NULL)
536 {
537 /* A port was entered */
538 pos = endpos + 1;
539 gftp_set_port (request, strtol (pos, NULL, 10));
540 }
541 if ((endpos = strchr (pos, '/')) != NULL)
542 gftp_set_directory (request, endpos);
543 g_free (str);
544 return (0);
545 }
546
547
548 int
549 gftp_set_data_type (gftp_request * request, int data_type)
550 {
551 g_return_val_if_fail (request != NULL, -2);
552
553 if (request->set_data_type == NULL)
554 return (-2);
555 return (request->set_data_type (request, data_type));
556 }
557
558
559 void
560 gftp_set_hostname (gftp_request * request, const char *hostname)
561 {
562 g_return_if_fail (request != NULL);
563 g_return_if_fail (hostname != NULL);
564
565 if (request->hostname)
566 g_free (request->hostname);
567 request->hostname = g_malloc (strlen (hostname) + 1);
568 strcpy (request->hostname, hostname);
569 }
570
571
572 void
573 gftp_set_username (gftp_request * request, const char *username)
574 {
575 g_return_if_fail (request != NULL);
576 g_return_if_fail (username != NULL);
577
578 if (request->username)
579 g_free (request->username);
580 request->username = g_malloc (strlen (username) + 1);
581 strcpy (request->username, username);
582 }
583
584
585 void
586 gftp_set_password (gftp_request * request, const char *password)
587 {
588 g_return_if_fail (request != NULL);
589 g_return_if_fail (password != NULL);
590
591 if (request->password)
592 g_free (request->password);
593 request->password = g_malloc (strlen (password) + 1);
594 strcpy (request->password, password);
595 }
596
597
598 void
599 gftp_set_account (gftp_request * request, const char *account)
600 {
601 g_return_if_fail (request != NULL);
602 g_return_if_fail (account != NULL);
603
604 if (request->account)
605 g_free (request->account);
606 request->account = g_malloc (strlen (account) + 1);
607 strcpy (request->account, account);
608 }
609
610
611 int
612 gftp_set_directory (gftp_request * request, const char *directory)
613 {
614 g_return_val_if_fail (request != NULL, -2);
615 g_return_val_if_fail (directory != NULL, -2);
616
617
618 if (request->sockfd == NULL)
619 {
620 if (directory != request->directory)
621 {
622 if (request->directory)
623 g_free (request->directory);
624 request->directory = g_malloc (strlen (directory) + 1);
625 strcpy (request->directory, directory);
626 }
627 return (0);
628 }
629 else if (request->chdir == NULL)
630 return (-2);
631 return (request->chdir (request, directory));
632 }
633
634
635 void
636 gftp_set_port (gftp_request * request, unsigned int port)
637 {
638 g_return_if_fail (request != NULL);
639
640 request->port = port;
641 }
642
643
644 void
645 gftp_set_proxy_hostname (gftp_request * request, const char *hostname)
646 {
647 g_return_if_fail (request != NULL);
648 g_return_if_fail (hostname != NULL);
649
650 if (request->proxy_hostname)
651 g_free (request->proxy_hostname);
652 request->proxy_hostname = g_malloc (strlen (hostname) + 1);
653 strcpy (request->proxy_hostname, hostname);
654 }
655
656
657 void
658 gftp_set_proxy_username (gftp_request * request, const char *username)
659 {
660 g_return_if_fail (request != NULL);
661 g_return_if_fail (username != NULL);
662
663 if (request->proxy_username)
664 g_free (request->proxy_username);
665 request->proxy_username = g_malloc (strlen (username) + 1);
666 strcpy (request->proxy_username, username);
667 }
668
669
670 void
671 gftp_set_proxy_password (gftp_request * request, const char *password)
672 {
673 g_return_if_fail (request != NULL);
674 g_return_if_fail (password != NULL);
675
676 if (request->proxy_password)
677 g_free (request->proxy_password);
678 request->proxy_password = g_malloc (strlen (password) + 1);
679 strcpy (request->proxy_password, password);
680 }
681
682
683 void
684 gftp_set_proxy_account (gftp_request * request, const char *account)
685 {
686 g_return_if_fail (request != NULL);
687 g_return_if_fail (account != NULL);
688
689 if (request->proxy_account)
690 g_free (request->proxy_account);
691 request->proxy_account = g_malloc (strlen (account) + 1);
692 strcpy (request->proxy_account, account);
693 }
694
695
696 void
697 gftp_set_proxy_port (gftp_request * request, unsigned int port)
698 {
699 g_return_if_fail (request != NULL);
700
701 request->proxy_port = port;
702 }
703
704
705 int
706 gftp_remove_directory (gftp_request * request, const char *directory)
707 {
708 g_return_val_if_fail (request != NULL, -2);
709
710 if (request->rmdir == NULL)
711 return (-2);
712 return (request->rmdir (request, directory));
713 }
714
715
716 int
717 gftp_remove_file (gftp_request * request, const char *file)
718 {
719 g_return_val_if_fail (request != NULL, -2);
720
721 if (request->rmfile == NULL)
722 return (-2);
723 return (request->rmfile (request, file));
724 }
725
726
727 int
728 gftp_make_directory (gftp_request * request, const char *directory)
729 {
730 g_return_val_if_fail (request != NULL, -2);
731
732 if (request->mkdir == NULL)
733 return (-2);
734 return (request->mkdir (request, directory));
735 }
736
737
738 int
739 gftp_rename_file (gftp_request * request, const char *oldname,
740 const char *newname)
741 {
742 g_return_val_if_fail (request != NULL, -2);
743
744 if (request->rename == NULL)
745 return (-2);
746 return (request->rename (request, oldname, newname));
747 }
748
749
750 int
751 gftp_chmod (gftp_request * request, const char *file, int mode)
752 {
753 g_return_val_if_fail (request != NULL, -2);
754
755 if (request->chmod == NULL)
756 return (-2);
757 return (request->chmod (request, file, mode));
758 }
759
760
761 int
762 gftp_set_file_time (gftp_request * request, const char *file, time_t datetime)
763 {
764 g_return_val_if_fail (request != NULL, -2);
765
766 if (request->set_file_time == NULL)
767 return (-2);
768 return (request->set_file_time (request, file, datetime));
769 }
770
771
772 char
773 gftp_site_cmd (gftp_request * request, const char *command)
774 {
775 g_return_val_if_fail (request != NULL, -2);
776
777 if (request->site == NULL)
778 return (-2);
779 return (request->site (request, command));
780 }
781
782
783 void
784 gftp_set_proxy_config (gftp_request * request, const char *proxy_config)
785 {
786 int len;
787
788 g_return_if_fail (request != NULL);
789 g_return_if_fail (proxy_config != NULL);
790
791 if (request->proxy_config != NULL)
792 g_free (request->proxy_config);
793
794 len = strlen (proxy_config);
795
796 if (len > 0 && (proxy_config[len - 1] != 'n' ||
797 proxy_config[len - 2] != '%'))
798 len += 2;
799
800 request->proxy_config = g_malloc (len + 1);
801 strcpy (request->proxy_config, proxy_config);
802 if (len != strlen (proxy_config))
803 {
804 request->proxy_config[len - 2] = '%';
805 request->proxy_config[len - 1] = 'n';
806 request->proxy_config[len] = '\0';
807 }
808 }
809
810
811 long
812 gftp_get_file_size (gftp_request * request, const char *filename)
813 {
814 g_return_val_if_fail (request != NULL, 0);
815
816 if (request->get_file_size == NULL)
817 return (0);
818 return (request->get_file_size (request, filename));
819 }
820
821
822 int
823 gftp_need_proxy (gftp_request * request, char *service)
824 {
825 gftp_proxy_hosts * hostname;
826 unsigned char addy[4];
827 struct sockaddr *addr;
828 GList * templist;
829 gint32 netaddr;
830 char *pos;
831 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
832 struct addrinfo hints;
833 int port, errnum;
834 char serv[8];
835
836 request->hostp = NULL;
837 if (proxy_hosts == NULL)
838 return (request->proxy_hostname != NULL
839 && *request->proxy_hostname != '\0'
840 && request->proxy_config != NULL
841 && *request->proxy_config != '\0');
842
843 memset (&hints, 0, sizeof (hints));
844 hints.ai_flags = AI_CANONNAME;
845 hints.ai_family = AF_INET;
846 hints.ai_socktype = SOCK_STREAM;
847
848 port = request->use_proxy ? request->proxy_port : request->port;
849 if (port == 0)
850 strcpy (serv, service);
851 else
852 snprintf (serv, sizeof (serv), "%d", port);
853
854 request->logging_function (gftp_logging_misc, request->user_data,
855 _("Looking up %s\n"), request->hostname);
856
857 if ((errnum = getaddrinfo (request->hostname, serv, &hints,
858 &request->hostp)) != 0)
859 {
860 request->logging_function (gftp_logging_error, request->user_data,
861 _("Cannot look up hostname %s: %s\n"),
862 request->hostname, gai_strerror (errnum));
863 return (-1);
864 }
865
866 addr = request->hostp->ai_addr;
867
868 #else /* !HAVE_GETADDRINFO */
869
870 request->hostp = NULL;
871 if (proxy_hosts == NULL)
872 return (request->proxy_hostname != NULL
873 && *request->proxy_hostname != '\0'
874 && request->proxy_config != NULL
875 && *request->proxy_config != '\0');
876
877 request->logging_function (gftp_logging_misc, request->user_data,
878 _("Looking up %s\n"), request->hostname);
879
880 if (!(request->hostp = r_gethostbyname (request->hostname, &request->host,
881 NULL)))
882 {
883 request->logging_function (gftp_logging_error, request->user_data,
884 _("Cannot look up hostname %s: %s\n"),
885 request->hostname, g_strerror (errno));
886 return (-1);
887 }
888
889 addr = (struct sockaddr *) request->host.h_addr_list[0];
890
891 #endif /* HAVE_GETADDRINFO */
892
893 templist = proxy_hosts;
894 while (templist != NULL)
895 {
896 hostname = templist->data;
897 if (hostname->domain &&
898 strlen (request->hostname) > strlen (hostname->domain))
899 {
900 pos = request->hostname + strlen (request->hostname) -
901 strlen (hostname->domain);
902 if (strcmp (hostname->domain, pos) == 0)
903 return (0);
904 }
905
906 if (hostname->ipv4_network_address != 0)
907 {
908 memcpy (addy, addr, sizeof (addy));
909 netaddr =
910 (((addy[0] & 0xff) << 24) | ((addy[1] & 0xff) << 16) |
911 ((addy[2] & 0xff) << 8) | (addy[3] & 0xff)) &
912 hostname->ipv4_netmask;
913 if (netaddr == hostname->ipv4_network_address)
914 return (0);
915 }
916 templist = templist->next;
917 }
918 return (request->proxy_hostname != NULL && *request->proxy_hostname != '\0'
919 && request->proxy_config != NULL && *request->proxy_config != '\0');
920 }
921
922
923 char *
924 gftp_convert_ascii (char *buf, ssize_t *len, int direction)
925 {
926 ssize_t i, j, newsize;
927 char *tempstr;
928
929 if (direction == GFTP_DIRECTION_DOWNLOAD)
930 {
931 for (i = 0, j = 0; i < *len; i++)
932 {
933 if (buf[i] != '\r')
934 buf[j++] = buf[i];
935 else
936 --*len;
937 }
938 tempstr = buf;
939 }
940 else
941 {
942 newsize = 0;
943 for (i = 0; i < *len; i++)
944 {
945 newsize++;
946 if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
947 newsize++;
948 }
949 tempstr = g_malloc (newsize);
950
951 for (i = 0, j = 0; i < *len; i++)
952 {
953 if (i > 0 && buf[i] == '\n' && buf[i - 1] != '\r')
954 tempstr[j++] = '\r';
955 tempstr[j++] = buf[i];
956 }
957 *len = newsize;
958 }
959 return (tempstr);
960 }
961
962
963 int
964 gftp_parse_ls (const char *lsoutput, gftp_file * fle)
965 {
966 int result, cols;
967 char *str, *pos;
968
969 g_return_val_if_fail (lsoutput != NULL, -2);
970 g_return_val_if_fail (fle != NULL, -2);
971
972 str = g_malloc (strlen (lsoutput) + 1);
973 strcpy (str, lsoutput);
974 memset (fle, 0, sizeof (*fle));
975
976 if (str[strlen (str) - 1] == '\n')
977 str[strlen (str) - 1] = '\0';
978 if (str[strlen (str) - 1] == '\r')
979 str[strlen (str) - 1] = '\0';
980 if (*lsoutput == '+') /* EPLF format */
981 result = gftp_parse_ls_eplf (str, fle);
982 else if (isdigit ((int) str[0]) && str[2] == '-') /* DOS/WinNT format */
983 result = gftp_parse_ls_nt (str, fle);
984 else if (str[1] == ' ' && str[2] == '[') /* Novell format */
985 result = gftp_parse_ls_novell (str, fle);
986 else
987 {
988 /* UNIX/MacOS format */
989
990 /* If there is no space between the attribs and links field, just make one */
991 if (strlen (str) > 10)
992 str[10] = ' ';
993
994 /* Determine the number of columns */
995 cols = 0;
996 pos = str;
997 while (*pos != '\0')
998 {
999 while (*pos != '\0' && *pos != ' ' && *pos != '\t')
1000 {
1001 if (*pos == ':')
1002 break;
1003 pos++;
1004 }
1005
1006 cols++;
1007
1008 if (*pos == ':')
1009 {
1010 cols++;
1011 break;
1012 }
1013
1014 while (*pos == ' ' || *pos == '\t')
1015 pos++;
1016 }
1017
1018 if (cols > 6)
1019 result = gftp_parse_ls_unix (str, cols, fle);
1020 else
1021 result = -2;
1022 }
1023 g_free (str);
1024
1025 if (fle->attribs == NULL)
1026 return (result);
1027
1028 if (*fle->attribs == 'd')
1029 fle->isdir = 1;
1030 if (*fle->attribs == 'l')
1031 fle->islink = 1;
1032 if (strchr (fle->attribs, 'x') != NULL && !fle->isdir && !fle->islink)
1033 fle->isexe = 1;
1034 if (*fle->attribs == 'b')
1035 fle->isblock = 1;
1036 if (*fle->attribs == 'c')
1037 fle->ischar = 1;
1038 if (*fle->attribs == 's')
1039 fle->issocket = 1;
1040 if (*fle->attribs == 'p')
1041 fle->isfifo = 1;
1042
1043 return (result);
1044 }
1045
1046
1047 static time_t
1048 parse_time (char **str)
1049 {
1050 const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
1051 "Aug", "Sep", "Oct", "Nov", "Dec"
1052 };
1053 char *startpos, *endpos, *datepos;
1054 struct tm curtime, tt;
1055 time_t t;
1056 int i;
1057
1058 startpos = *str;
1059 memset (&tt, 0, sizeof (tt));
1060 tt.tm_isdst = -1;
1061 if (isdigit ((int) startpos[0]) && startpos[2] == '-')
1062 {
1063 /* This is how DOS will return the date/time */
1064 /* 07-06-99 12:57PM */
1065 if ((endpos = strchr (startpos, '-')) == NULL)
1066 {
1067 g_free (str);
1068 return (0);
1069 }
1070 tt.tm_mon = strtol (startpos, NULL, 10) - 1;
1071
1072 startpos = endpos + 1;
1073 if ((endpos = strchr (startpos, '-')) == NULL)
1074 {
1075 g_free (str);
1076 return (0);
1077 }
1078 tt.tm_mday = strtol (startpos, NULL, 10);
1079
1080 startpos = endpos + 1;
1081 if ((endpos = strchr (startpos, ' ')) == NULL)
1082 {
1083 g_free (str);
1084 return (0);
1085 }
1086 tt.tm_year = strtol (startpos, NULL, 10);
1087
1088 while (*endpos == ' ')
1089 endpos++;
1090
1091 startpos = endpos + 1;
1092 if ((endpos = strchr (startpos, ':')) == NULL)
1093 {
1094 g_free (str);
1095 return (0);
1096 }
1097 tt.tm_hour = strtol (startpos, NULL, 10);
1098
1099 startpos = endpos + 1;
1100 while ((*endpos != 'A') && (*endpos != 'P'))
1101 endpos++;
1102 if (*endpos == 'P')
1103 {
1104 if (tt.tm_hour == 12)
1105 tt.tm_hour = 0;
1106 else
1107 tt.tm_hour += 12;
1108 }
1109 tt.tm_min = strtol (startpos, NULL, 10);
1110 }
1111 else
1112 {
1113 /* This is how most UNIX, Novell, and MacOS ftp servers send their time */
1114 /* Jul 06 12:57 */
1115 t = time (NULL);
1116 curtime = *localtime (&t);
1117
1118 /* Get the month */
1119 if ((endpos = strchr (startpos, ' ')) == NULL)
1120 return (0);
1121 for (i = 0; i < 12; i++)
1122 {
1123 if (strncmp (months[i], startpos, 3) == 0)
1124 {
1125 tt.tm_mon = i;
1126 break;
1127 }
1128 }
1129
1130 /* Skip the blanks till we get to the next entry */
1131 startpos = endpos + 1;
1132 while (*startpos == ' ')
1133 startpos++;
1134
1135 /* Get the day */
1136 if ((endpos = strchr (startpos, ' ')) == NULL)
1137 return (0);
1138 tt.tm_mday = strtol (startpos, NULL, 10);
1139
1140 /* Skip the blanks till we get to the next entry */
1141 startpos = endpos + 1;
1142 while (*startpos == ' ')
1143 startpos++;
1144
1145 if ((datepos = strchr (startpos, ':')) != NULL)
1146 {
1147 /* No year was specified. We will use the current year */
1148 tt.tm_year = curtime.tm_year;
1149
1150 /* If the date is in the future, than the year is from last year */
1151 if ((tt.tm_mon > curtime.tm_mon) ||
1152 ((tt.tm_mon == curtime.tm_mon) && tt.tm_mday > curtime.tm_mday))
1153 tt.tm_year--;
1154
1155 /* Get the hours and the minutes */
1156 tt.tm_hour = strtol (startpos, NULL, 10);
1157 tt.tm_min = strtol (datepos + 1, NULL, 10);
1158 }
1159 else
1160 {
1161 /* Get the year. The hours and minutes will be assumed to be 0 */
1162 tt.tm_year = strtol (startpos, NULL, 10) - 1900;
1163 }
1164 }
1165 *str = startpos;
1166 return (mktime (&tt));
1167 }
1168
1169
1170 static int
1171 gftp_parse_ls_eplf (char *str, gftp_file * fle)
1172 {
1173 char *startpos;
1174
1175 startpos = str;
1176 fle->attribs = g_malloc (11);
1177 strcpy (fle->attribs, "----------");
1178 while (startpos)
1179 {
1180 startpos++;
1181 switch (*startpos)
1182 {
1183 case '/':
1184 *fle->attribs = 'd';
1185 break;
1186 case 's':
1187 fle->size = strtol (startpos + 1, NULL, 10);
1188 break;
1189 case 'm':
1190 fle->datetime = strtol (startpos + 1, NULL, 10);
1191 break;
1192 }
1193 startpos = strchr (startpos, ',');
1194 }
1195 if ((startpos = strchr (str, 9)) == NULL)
1196 return (-2);
1197 fle->file = g_malloc (strlen (startpos));
1198 strcpy (fle->file, startpos + 1);
1199 fle->user = g_malloc (8);
1200 strcpy (fle->user, _("unknown"));
1201 fle->group = g_malloc (8);
1202 strcpy (fle->group, _("unknown"));
1203 return (0);
1204 }
1205
1206
1207 static int
1208 gftp_parse_ls_unix (char *str, int cols, gftp_file * fle)
1209 {
1210 char *endpos, *startpos;
1211
1212 startpos = str;
1213 /* Copy file attributes */
1214 if ((startpos = copy_token (&fle->attribs, startpos)) == NULL)
1215 return (-2);
1216
1217 if (cols >= 9)
1218 {
1219 /* Skip the number of links */
1220 startpos = goto_next_token (startpos);
1221
1222 /* Copy the user that owns this file */
1223 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
1224 return (-2);
1225
1226 /* Copy the group that owns this file */
1227 if ((startpos = copy_token (&fle->group, startpos)) == NULL)
1228 return (-2);
1229 }
1230 else
1231 {
1232 fle->group = g_malloc (8);
1233 strcpy (fle->group, _("unknown"));
1234 if (cols == 8)
1235 {
1236 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
1237 return (-2);
1238 }
1239 else
1240 {
1241 fle->user = g_malloc (8);
1242 strcpy (fle->user, _("unknown"));
1243 }
1244 startpos = goto_next_token (startpos);
1245 }
1246
1247 /* See if this is a Cray directory listing. It has the following format:
1248 drwx------ 2 feiliu g913 DK common 4096 Sep 24 2001 wv */
1249 if (cols == 11 && strstr (str, "->") == NULL)
1250 {
1251 startpos = goto_next_token (startpos);
1252 startpos = goto_next_token (startpos);
1253 }
1254
1255 /* See if this is a block or character device. We will store the major number
1256 in the high word and the minor number in the low word. */
1257 if ((fle->attribs[0] == 'b' || fle->attribs[0] == 'u' ||
1258 fle->attribs[0] == 'c') &&
1259 ((endpos = strchr (startpos, ',')) != NULL))
1260 {
1261 fle->size = strtol (startpos, NULL, 10) << 16;
1262
1263 startpos = endpos + 1;
1264 while (*startpos == ' ')
1265 startpos++;
1266
1267 /* Get the minor number */
1268 if ((endpos = strchr (startpos, ' ')) == NULL)
1269 return (-2);
1270 fle->size |= strtol (startpos, NULL, 10);
1271 }
1272 else
1273 {
1274 /* This is a regular file */
1275 if ((endpos = strchr (startpos, ' ')) == NULL)
1276 return (-2);
1277 fle->size = strtol (startpos, NULL, 10);
1278 }
1279
1280 /* Skip the blanks till we get to the next entry */
1281 startpos = endpos + 1;
1282 while (*startpos == ' ')
1283 startpos++;
1284
1285 if ((fle->datetime = parse_time (&startpos)) == 0)
1286 return (-2);
1287
1288 /* Skip the blanks till we get to the next entry */
1289 startpos = goto_next_token (startpos);
1290
1291 /* Parse the filename. If this file is a symbolic link, remove the -> part */
1292 if (fle->attribs[0] == 'l' && ((endpos = strstr (startpos, "->")) != NULL))
1293 *(endpos - 1) = '\0';
1294 fle->file = g_malloc (strlen (startpos) + 1);
1295
1296 strcpy (fle->file, startpos);
1297
1298 /* Uncomment this if you want to strip the spaces off of the end of the file.
1299 I don't want to do this by default since there are valid filenames with
1300 spaces at the end of them. Some broken FTP servers like the Paradyne IPC
1301 DSLAMS append a bunch of spaces at the end of the file.
1302 for (endpos = fle->file + strlen (fle->file) - 1;
1303 *endpos == ' ';
1304 *endpos-- = '\0');
1305 */
1306
1307 return (0);
1308 }
1309
1310
1311 static int
1312 gftp_parse_ls_nt (char *str, gftp_file * fle)
1313 {
1314 char *startpos;
1315
1316 startpos = str;
1317 if ((fle->datetime = parse_time (&startpos)) == 0)
1318 return (-2);
1319
1320 /* No such thing on Windoze.. */
1321 fle->user = g_malloc (8);
1322 strcpy (fle->user, _("unknown"));
1323 fle->group = g_malloc (8);
1324 strcpy (fle->group, _("unknown"));
1325
1326 startpos = goto_next_token (startpos);
1327 fle->attribs = g_malloc (11);
1328 if (startpos[0] == '<')
1329 strcpy (fle->attribs, "drwxrwxrwx");
1330 else
1331 {
1332 strcpy (fle->attribs, "-rw-rw-rw-");
1333 fle->size = strtol (startpos, NULL, 10);
1334 }
1335 startpos = goto_next_token (startpos);
1336 fle->file = g_malloc (strlen (startpos) + 1);
1337 strcpy (fle->file, startpos);
1338 return (0);
1339 }
1340
1341
1342 static int
1343 gftp_parse_ls_novell (char *str, gftp_file * fle)
1344 {
1345 char *startpos;
1346
1347 if (str[12] != ' ')
1348 return (-2);
1349 str[12] = '\0';
1350 fle->attribs = g_malloc (13);
1351 strcpy (fle->attribs, str);
1352 startpos = str + 13;
1353
1354 while ((*startpos == ' ' || *startpos == '\t') && *startpos != '\0')
1355 startpos++;
1356
1357 if ((startpos = copy_token (&fle->user, startpos)) == NULL)
1358 return (-2);
1359
1360 fle->group = g_malloc (8);
1361 strcpy (fle->group, _("unknown"));
1362
1363 fle->size = strtol (startpos, NULL, 10);
1364
1365 startpos = goto_next_token (startpos);
1366 if ((fle->datetime = parse_time (&startpos)) == 0)
1367 return (-2);
1368
1369 startpos = goto_next_token (startpos);
1370 fle->file = g_malloc (strlen (startpos) + 1);
1371 strcpy (fle->file, startpos);
1372 return (0);
1373 }
1374
1375
1376 static char *
1377 copy_token (char **dest, char *source)
1378 {
1379 /* This function is used internally by gftp_parse_ls () */
1380 char *endpos;
1381
1382 endpos = source;
1383 while (*endpos != ' ' && *endpos != '\t' && *endpos != '\0')
1384 endpos++;
1385 if (*endpos == '\0')
1386 return (NULL);
1387 *endpos = '\0';
1388 *dest = g_malloc (endpos - source + 1);
1389 strcpy (*dest, source);
1390
1391 /* Skip the blanks till we get to the next entry */
1392 source = endpos + 1;
1393 while ((*source == ' ' || *source == '\t') && *source != '\0')
1394 source++;
1395 return (source);
1396 }
1397
1398
1399 static char *
1400 goto_next_token (char *pos)
1401 {
1402 while (*pos != ' ' && *pos != '\t' && *pos != '\0')
1403 pos++;
1404 if (pos == '\0')
1405 return (pos);
1406 while ((*pos == ' ' || *pos == '\t') && *pos != '\0')
1407 pos++;
1408 return (pos);
1409 }
1410
1411
1412 static GList *
1413 gftp_get_dir_listing (gftp_transfer * transfer, int getothdir)
1414 {
1415 unsigned long *newsize;
1416 GHashTable * dirhash;
1417 GList * templist;
1418 gftp_file * fle;
1419 char *newname;
1420
1421 if (getothdir && transfer->toreq)
1422 dirhash = gftp_gen_dir_hash (transfer->toreq);
1423 else
1424 dirhash = NULL;
1425
1426 if (gftp_list_files (transfer->fromreq) != 0)
1427 return (NULL);
1428
1429 fle = g_malloc (sizeof (*fle));
1430 templist = NULL;
1431 while (gftp_get_next_file (transfer->fromreq, NULL, fle) > 0)
1432 {
1433 if (strcmp (fle->file, ".") == 0 || strcmp (fle->file, "..") == 0)
1434 {
1435 gftp_file_destroy (fle);
1436 continue;
1437 }
1438
1439 if (dirhash &&
1440 (newsize = g_hash_table_lookup (dirhash, fle->file)) != NULL)
1441 fle->startsize = *newsize;
1442
1443 if (transfer->toreq)
1444 fle->destfile = g_strconcat (transfer->toreq->directory, "/",
1445 fle->file, NULL);
1446 newname = g_strconcat (transfer->fromreq->directory, "/", fle->file, NULL);
1447 g_free (fle->file);
1448 fle->file = newname;
1449
1450 templist = g_list_append (templist, fle);
1451
1452 fle = g_malloc (sizeof (*fle));
1453 }
1454 gftp_end_transfer (transfer->fromreq);
1455
1456 gftp_file_destroy (fle);
1457 g_free (fle);
1458
1459 if (dirhash)
1460 gftp_destroy_dir_hash (dirhash);
1461
1462
1463 return (templist);
1464 }
1465
1466
1467 int
1468 gftp_get_all_subdirs (gftp_transfer * transfer,
1469 void (*update_func) (gftp_transfer * transfer))
1470 {
1471 char *oldfromdir, *oldtodir, *newname;
1472 GList * templist, * lastlist;
1473 int forcecd, remotechanged;
1474 unsigned long *newsize;
1475 GHashTable * dirhash;
1476 gftp_file * curfle;
1477
1478 g_return_val_if_fail (transfer != NULL, -1);
1479 g_return_val_if_fail (transfer->fromreq != NULL, -1);
1480 g_return_val_if_fail (transfer->files != NULL, -1);
1481
1482 if (transfer->toreq != NULL)
1483 dirhash = gftp_gen_dir_hash (transfer->toreq);
1484 else
1485 dirhash = NULL;
1486
1487 for (lastlist = transfer->files; ; lastlist = lastlist->next)
1488 {
1489 curfle = lastlist->data;
1490 if (dirhash &&
1491 (newsize = g_hash_table_lookup (dirhash, curfle->file)) != NULL)
1492 curfle->startsize = *newsize;
1493
1494 if (transfer->toreq)
1495 curfle->destfile = g_strconcat (transfer->toreq->directory, "/",
1496 curfle->file, NULL);
1497 newname = g_strconcat (transfer->fromreq->directory, transfer->fromreq->directory[strlen (transfer->fromreq->directory) - 1] == '/' ? "" : "/", curfle->file, NULL);
1498 g_free (curfle->file);
1499 curfle->file = newname;
1500
1501 if (lastlist->next == NULL)
1502 break;
1503 }
1504
1505 if (dirhash)
1506 gftp_destroy_dir_hash (dirhash);
1507
1508 oldfromdir = oldtodir = NULL;
1509 remotechanged = 0;
1510 forcecd = 0;
1511 for (templist = transfer->files; templist != NULL; templist = templist->next)
1512 {
1513 curfle = templist->data;
1514
1515 if (curfle->isdir)
1516 {
1517 oldfromdir = transfer->fromreq->directory;
1518 transfer->fromreq->directory = curfle->file;
1519
1520 if (transfer->toreq)
1521 {
1522 oldtodir = transfer->toreq->directory;
1523 transfer->toreq->directory = curfle->destfile;
1524 }
1525 forcecd = 1;
1526 if (gftp_set_directory (transfer->fromreq,
1527 transfer->fromreq->directory) == 0)
1528 {
1529 if (curfle->startsize > 0 && transfer->toreq)
1530 {
1531 remotechanged = 1;
1532 if (gftp_set_directory (transfer->toreq,
1533 transfer->toreq->directory) != 0)
1534 curfle->startsize = 0;
1535 }
1536
1537 lastlist->next = gftp_get_dir_listing (transfer,
1538 curfle->startsize > 0);
1539 if (lastlist->next != NULL)
1540 {
1541 lastlist->next->prev = lastlist;
1542 for (; lastlist->next != NULL; lastlist = lastlist->next);
1543 }
1544 transfer->numdirs++;
1545 if (update_func)
1546 update_func (transfer);
1547 }
1548 else
1549 curfle->transfer_action = GFTP_TRANS_ACTION_SKIP;
1550
1551 transfer->fromreq->directory = oldfromdir;
1552 if (transfer->toreq)
1553 transfer->toreq->directory = oldtodir;
1554 }
1555 else
1556 {
1557 curfle->ascii = gftp_get_file_transfer_mode (curfle->file,
1558 transfer->fromreq->data_type) == GFTP_TYPE_ASCII;
1559 transfer->numfiles++;
1560 }
1561 }
1562
1563 if (forcecd)
1564 gftp_set_directory (transfer->fromreq, transfer->fromreq->directory);
1565 if (remotechanged && transfer->toreq)
1566 gftp_set_directory (transfer->toreq, transfer->toreq->directory);
1567
1568 if (update_func)
1569 {
1570 transfer->numfiles = transfer->numdirs = -1;
1571 update_func (transfer);
1572 }
1573 return (0);
1574 }
1575
1576
1577 static GHashTable *
1578 gftp_gen_dir_hash (gftp_request * request)
1579 {
1580 unsigned long *newsize;
1581 GHashTable * dirhash;
1582 gftp_file * fle;
1583 char * newname;
1584
1585
1586 dirhash = g_hash_table_new (string_hash_function, string_hash_compare);
1587 if (gftp_list_files (request) == 0)
1588 {
1589 fle = g_malloc0 (sizeof (*fle));
1590 while (gftp_get_next_file (request, NULL, fle) > 0)
1591 {
1592 newname = fle->file;
1593 newsize = g_malloc (sizeof (unsigned long));
1594 *newsize = fle->size;
1595 g_hash_table_insert (dirhash, newname, newsize);
1596 fle->file = NULL;
1597 gftp_file_destroy (fle);
1598 }
1599 gftp_end_transfer (request);
1600 g_free (fle);
1601 }
1602 else
1603 {
1604 g_hash_table_destroy (dirhash);
1605 dirhash = NULL;
1606 }
1607 return (dirhash);
1608 }
1609
1610
1611 static void
1612 gftp_destroy_dir_hash (GHashTable * dirhash)
1613 {
1614 g_hash_table_foreach (dirhash, destroy_hash_ent, NULL);
1615 g_hash_table_destroy (dirhash);
1616 }
1617
1618
1619 static void
1620 destroy_hash_ent (gpointer key, gpointer value, gpointer user_data)
1621 {
1622
1623 g_free (key);
1624 g_free (value);
1625 }
1626
1627
1628 int
1629 gftp_get_file_transfer_mode (char *filename, int def)
1630 {
1631 gftp_file_extensions * tempext;
1632 GList * templist;
1633 int stlen, ret;
1634
1635 if (!use_default_dl_types)
1636 return (def);
1637
1638 ret = def;
1639 stlen = strlen (filename);
1640 for (templist = registered_exts; templist != NULL; templist = templist->next)
1641 {
1642 tempext = templist->data;
1643
1644 if (stlen >= tempext->stlen &&
1645 strcmp (&filename[stlen - tempext->stlen], tempext->ext) == 0)
1646 {
1647 if (toupper (*tempext->ascii_binary == 'A'))
1648 ret = GFTP_TYPE_ASCII;
1649 else if (toupper (*tempext->ascii_binary == 'B'))
1650 ret = GFTP_TYPE_BINARY;
1651 break;
1652 }
1653 }
1654
1655 return (ret);
1656 }
1657
1658
1659 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
1660 int
1661 get_port (struct addrinfo *addr)
1662 {
1663 struct sockaddr_in * saddr;
1664 int port;
1665
1666 if (addr->ai_family == AF_INET)
1667 {
1668 saddr = (struct sockaddr_in *) addr->ai_addr;
1669 port = ntohs (saddr->sin_port);
1670 }
1671 else
1672 port = 0;
1673
1674 return (port);
1675 }
1676 #endif
1677
1678
1679 int
1680 gftp_connect_server (gftp_request * request, char *service)
1681 {
1682 char *connect_host, *disphost;
1683 int port, sock;
1684 #if defined (HAVE_GETADDRINFO) && defined (HAVE_GAI_STRERROR)
1685 struct addrinfo hints, *res;
1686 char serv[8];
1687 int errnum;
1688
1689 if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
1690 return (-1);
1691 else if (request->use_proxy == 1)
1692 request->hostp = NULL;
1693
1694 memset (&hints, 0, sizeof (hints));
1695 hints.ai_flags = AI_CANONNAME;
1696 hints.ai_family = AF_INET;
1697 hints.ai_socktype = SOCK_STREAM;
1698
1699 connect_host = request->use_proxy ? request->proxy_hostname :
1700 request->hostname;
1701 port = request->use_proxy ? request->proxy_port : request->port;
1702
1703 if (request->hostp == NULL)
1704 {
1705 if (port == 0)
1706 strcpy (serv, service);
1707 else
1708 snprintf (serv, sizeof (serv), "%d", port);
1709
1710 request->logging_function (gftp_logging_misc, request->user_data,
1711 _("Looking up %s\n"), connect_host);
1712 if ((errnum = getaddrinfo (connect_host, serv, &hints,
1713 &request->hostp)) != 0)
1714 {
1715 request->logging_function (gftp_logging_error, request->user_data,
1716 _("Cannot look up hostname %s: %s\n"),
1717 connect_host, gai_strerror (errnum));
1718 return (-1);
1719 }
1720 }
1721
1722 disphost = connect_host;
1723 for (res = request->hostp; res != NULL; res = res->ai_next)
1724 {
1725 disphost = res->ai_canonname ? res->ai_canonname : connect_host;
1726 port = get_port (res);
1727 if ((sock = socket (res->ai_family, res->ai_socktype,
1728 res->ai_protocol)) < 0)
1729 {
1730 request->logging_function (gftp_logging_error, request->user_data,
1731 _("Failed to create a socket: %s\n"),
1732 g_strerror (errno));
1733 continue;
1734 }
1735
1736 request->logging_function (gftp_logging_misc, request->user_data,
1737 _("Trying %s:%d\n"), disphost, port);
1738
1739 if (connect (sock, res->ai_addr, res->ai_addrlen) == -1)
1740 {
1741 request->logging_function (gftp_logging_error, request->user_data,
1742 _("Cannot connect to %s: %s\n"),
1743 disphost, g_strerror (errno));
1744 close (sock);
1745 continue;
1746 }
1747 break;
1748 }
1749
1750 if (res == NULL)
1751 {
1752 if (request->hostp != NULL)
1753 {
1754 freeaddrinfo (request->hostp);
1755 request->hostp = NULL;
1756 }
1757 return (-1);
1758 }
1759
1760 #else /* !HAVE_GETADDRINFO */
1761 struct sockaddr_in remote_address;
1762 struct servent serv_struct;
1763 int curhost;
1764
1765 if ((request->use_proxy = gftp_need_proxy (request, service)) < 0)
1766 return (-1);
1767 else if (request->use_proxy == 1)
1768 request->hostp = NULL;
1769
1770 if ((sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
1771 {
1772 request->logging_function (gftp_logging_error, request->user_data,
1773 _("Failed to create a socket: %s\n"),
1774 g_strerror (errno));
1775 return (-1);
1776 }
1777
1778 memset (&remote_address, 0, sizeof (remote_address));
1779 remote_address.sin_family = AF_INET;
1780
1781 connect_host = request->use_proxy ? request->proxy_hostname :
1782 request->hostname;
1783 port = htons (request->use_proxy ? request->proxy_port : request->port);
1784
1785 if (port == 0)
1786 {
1787 if (!r_getservbyname (service, "tcp", &serv_struct, NULL))
1788 {
1789 port = htons (21);
1790 request->port = 21;
1791 }
1792 else
1793 {
1794 port = serv_struct.s_port;
1795 request->port = ntohs (serv_struct.s_port);
1796 }
1797 }
1798 remote_address.sin_port = port;
1799
1800 if (request->hostp == NULL)
1801 {
1802 request->logging_function (gftp_logging_misc, request->user_data,
1803 _("Looking up %s\n"), connect_host);
1804 if (!(request->hostp = r_gethostbyname (connect_host, &request->host,
1805 NULL)))
1806 {
1807 request->logging_function (gftp_logging_error, request->user_data,
1808 _("Cannot look up hostname %s: %s\n"),
1809 connect_host, g_strerror (errno));
1810 close (sock);
1811 return (-1);
1812 }
1813 }
1814
1815 disphost = NULL;
1816 for (curhost = 0; request->host.h_addr_list[curhost] != NULL; curhost++)
1817 {
1818 disphost = request->host.h_name;
1819 memcpy (&remote_address.sin_addr, request->host.h_addr_list[curhost],
1820 request->host.h_length);
1821 request->logging_function (gftp_logging_misc, request->user_data,
1822 _("Trying %s:%d\n"),
1823 request->host.h_name, ntohs (port));
1824
1825 if (connect (sock, (struct sockaddr *) &remote_address,
1826 sizeof (remote_address)) == -1)
1827 {
1828 request->logging_function (gftp_logging_error, request->user_data,
1829 _("Cannot connect to %s: %s\n"),
1830 connect_host, g_strerror (errno));
1831 }
1832 break;
1833 }
1834
1835 if (request->host.h_addr_list[curhost] == NULL)
1836 {
1837 close (sock);
1838 return (-1);
1839 }
1840 port = ntohs (port);
1841 #endif /* HAVE_GETADDRINFO */
1842
1843 if (!request->use_proxy && disphost != NULL)
1844 {
1845 g_free (request->hostname);
1846 request->hostname = g_malloc (strlen (disphost) + 1);
1847 strcpy (request->hostname, disphost);
1848 connect_host = request->hostname;
1849 }
1850
1851 request->logging_function (gftp_logging_misc, request->user_data,
1852 _("Connected to %s:%d\n"), connect_host, port);
1853 return (sock);
1854 }
1855
1856
1857 void
1858 gftp_set_config_options (gftp_request * request)
1859 {
1860 request->transfer_type = passive_transfer ? gftp_transfer_passive : gftp_transfer_active;
1861 request->network_timeout = network_timeout;
1862 request->retries = retries;
1863 request->sleep_time = sleep_time;
1864 request->maxkbs = maxkbs;
1865
1866 if (request->protonum == GFTP_SSHV2_NUM ||
1867 request->protonum == GFTP_SSH_NUM)
1868 request->need_userpass = ssh_need_userpass;
1869
1870 /* Set up the proxy server settings. If we are using a HTTP proxy for FTP,
1871 then set up the HTTP proxy settings */
1872 if ((strcmp (request->protocol_name, "FTP") == 0 ||
1873 strcmp (request->protocol_name, "HTTP") == 0) &&
1874 proxy_config != NULL)
1875 {
1876 if (strcmp (request->protocol_name, "FTP") == 0 &&
1877 strcmp (proxy_config, "http") != 0)
1878 {
1879 gftp_set_proxy_hostname (request, firewall_host);
1880 gftp_set_proxy_port (request, firewall_port);
1881 gftp_set_proxy_username (request, firewall_username);
1882 gftp_set_proxy_password (request, firewall_password);
1883 gftp_set_proxy_account (request, firewall_account);
1884 gftp_set_proxy_config (request, proxy_config);
1885 }
1886 else
1887 {
1888 gftp_set_proxy_hostname (request, http_proxy_host);
1889 gftp_set_proxy_port (request, http_proxy_port);
1890 gftp_set_proxy_username (request, http_proxy_username);
1891 gftp_set_proxy_password (request, http_proxy_password);
1892
1893
1894 if (request->proxy_config == NULL)
1895 {
1896 if (strcmp (GFTP_GET_PROTOCOL_NAME (request), "FTP") == 0)
1897 {
1898 gftp_protocols[GFTP_HTTP_NUM].init (request);
1899 request->proxy_config = g_malloc (4);
1900 strcpy (request->proxy_config, "ftp");
1901 }
1902 else
1903 {
1904 request->proxy_config = g_malloc (5);
1905 strcpy (request->proxy_config, "http");
1906 }
1907 }
1908 }
1909 }
1910 }
1911
1912
1913 void
1914 gftp_set_sftpserv_path (gftp_request * request, char *path)
1915 {
1916 g_return_if_fail (request != NULL);
1917
1918 if (request->sftpserv_path)
1919 g_free (request->sftpserv_path);
1920
1921 if (path != NULL && *path != '\0')
1922 {
1923 request->sftpserv_path = g_malloc (strlen (path) + 1);
1924 strcpy (request->sftpserv_path, path);
1925 }
1926 else
1927 request->sftpserv_path = NULL;
1928 }
1929
1930
1931 void
1932 print_file_list (GList * list)
1933 {
1934 gftp_file * tempfle;
1935 GList * templist;
1936
1937 printf ("--START OF FILE LISTING - TOP TO BOTTOM--\n");
1938 for (templist = list; ; templist = templist->next)
1939 {
1940 tempfle = templist->data;
1941 printf ("%s:%s:%ld:%ld:%s:%s:%s\n", tempfle->file, tempfle->destfile,
1942 tempfle->size, tempfle->startsize, tempfle->user, tempfle->group,
1943 tempfle->attribs);
1944 if (templist->next == NULL)
1945 break;
1946 }
1947
1948 printf ("--START OF FILE LISTING - BOTTOM TO TOP--\n");
1949 for (; ; templist = templist->prev)
1950 {
1951 tempfle = templist->data;
1952 printf ("%s:%s:%ld:%ld:%s:%s:%s\n", tempfle->file, tempfle->destfile,
1953 tempfle->size, tempfle->startsize, tempfle->user, tempfle->group,
1954 tempfle->attribs);
1955 if (templist == list)
1956 break;
1957 }
1958 printf ("--END OF FILE LISTING--\n");
1959 }
1960