Handle hostnames with upper-case letters
[webmin.git] / fsdump / ftp.pl
1 #!/usr/local/bin/perl
2 # Pass data from stdin to an FTP server
3
4 $no_acl_check++;
5 require './fsdump-lib.pl';
6
7 # Parse args, and get password
8 select(STDERR); $| = 1; select(STDOUT);
9 $host = $ARGV[0];
10 $user = $ARGV[2];
11 if ($ARGV[3] =~ /touch/) {
12         $touched = 1;
13         }
14 $| = 1;
15 if (defined($ENV{'DUMP_PASSWORD'})) {
16         $pass = $ENV{'DUMP_PASSWORD'};
17         }
18 else {
19         open(TTY, "+</dev/tty");
20         print TTY "Password: ";
21         $pass = <TTY>;
22         $pass =~ s/\r|\n//g;
23         close(TTY);
24         }
25
26 # Read rmt protocol messages
27 while(1) {
28         $line = <STDIN>;
29         $line =~ s/\r|\n//g;
30         if ($line =~ /^O(.*)/) {
31                 # File to open specified .. connect to FTP server
32                 $file = $1;
33                 $perms = <STDIN>;
34                 $perms = int($perms);
35                 &open_socket($host, 21, "SOCK", \$err);
36                 &error_exit("FTP connection failed : $err") if ($err);
37                 &ftp_command("", 2, \$err) ||
38                         &error_exit("FTP prompt failed : $err");
39
40                 # Login to server
41                 @urv = &ftp_command("USER $user", [ 2, 3 ], \$err);
42                 @urv || &error_exit("FTP login failed : $err");
43                 if (int($urv[1]/100) == 3) {
44                         &ftp_command("PASS $pass", 2, \$err) ||
45                                 &error_exit("FTP login failed : $err");
46                         }
47                 &ftp_command("TYPE I", 2, \$err) ||
48                         &error_exit("FTP file type failed : $err");
49
50                 # Work out what we are doing
51                 $mode = 0;
52                 if (($perms & 0100) || ($perms & 01000) ||
53                     (($perms & 01) || ($perms & 02)) && $touched) {
54                         # Writing new file
55                         $mode = 1;
56                         }
57                 elsif ($perms & 02000) {
58                         # Appending to a file
59                         $mode = 2;
60                         }
61                 elsif (!$perms) {
62                         # Reading from file
63                         $mode = 0;
64                         }
65                 else {
66                         &error_exit("Unknown permissions $perms");
67                         }
68                 print "A0\n";
69                 }
70         elsif ($line =~ /^W(\d+)/) {
71                 # Write to FTP server
72                 $len = $1;
73                 if ($opened != 1) {
74                         &open_ftp_file($mode);
75                         }
76                 #$opened || &error_exit("FTP connection not opened yet");
77                 read(STDIN, $buf, $len);
78                 $wrote = (print CON $buf);
79                 print "A".($wrote ? $len : 0)."\n";
80                 }
81         elsif ($line =~ /^R(\d+)/) {
82                 # Read from to FTP server
83                 if ($opened != 2) {
84                         &open_ftp_file(0);
85                         }
86                 $len = $1;
87                 $read = read(CON, $buf, $len);
88                 if ($read >= 0) {
89                         print "A".$read."\n";
90                         print $buf;
91                         }
92                 else {
93                         print "E",int($!),"\n";
94                         print "Read failed : $!\n";
95                         }
96                 }
97         elsif ($line =~ /^C/) {
98                 # Close FTP connection
99                 if ($opened) {
100                         # Finish transfer
101                         close(CON);
102                         &ftp_command("", 2, \$err) ||
103                                 &error_exit("FTP close failed : $err");
104                         }
105                 &ftp_command("QUIT", 2, \$err) ||
106                         &error_exit("FTP quit failed : $err");
107                 close(SOCK);
108                 print "A0\n";
109                 $opened = 0;
110                 }
111         elsif (!$line) {
112                 # All done!
113                 last;
114                 }
115         else {
116                 print "E1\nUnknown command $line\n";
117                 }
118         }
119
120 sub error_exit
121 {
122 local $err = &html_tags_to_text(join("", @_));
123 print STDERR $err,"\n";
124 print "E1\n$err\n";
125 exit(1);
126 }
127
128 sub html_tags_to_text
129 {
130 local ($rv) = @_;
131 $rv =~ s/<tt>|<\/tt>//g;
132 $rv =~ s/<b>|<\/b>//g;
133 $rv =~ s/<i>|<\/i>//g;
134 $rv =~ s/<u>|<\/u>//g;
135 $rv =~ s/<pre>|<\/pre>//g;
136 $rv =~ s/<br>/\n/g;
137 $rv =~ s/<p>/\n\n/g;
138 return $rv;
139 }
140
141 sub open_ftp_file
142 {
143 local ($mode) = @_;
144
145 # Open passive port
146 local $pasv = &ftp_command("PASV", 2, \$err);
147 $pasv || &error_exit("FTP port failed : $err");
148 $pasv =~ /\(([0-9,]+)\)/;
149 local @n = split(/,/ , $1);
150 &open_socket("$n[0].$n[1].$n[2].$n[3]", $n[4]*256 + $n[5],
151              CON, \$err) ||
152         &error_exit("FTP port failed : $err");
153
154 if ($mode == 0) {
155         # Read from file
156         &ftp_command("RETR $file", 1, \$err) ||
157                 &error_exit("FTP read failed : $err");
158         $opened = 2;
159         }
160 elsif ($mode == 1) {
161         # Create new file if requested by the client, or if
162         # the touch command was specified by the caller
163         &ftp_command("STOR $file", 1, \$err) ||
164                 &error_exit("FTP write failed : $err");
165         $touched = 0;
166         $opened = 1;
167         }
168 elsif ($mode == 2) {
169         # Otherwise append to the file
170         &ftp_command("APPE $file", 1, \$err) ||
171                 &error_exit("FTP write failed : $err");
172         $opened = 1;
173         }
174 else {
175         $opened = 0;
176         }
177 }
178