/Anton.Dobrov/Perl/perlTask/ftp-client/Manage_ftp.pm
Perl | 267 lines | 251 code | 15 blank | 1 comment | 44 complexity | 8d9147f4f47fc9a88af39770edcf17b3 MD5 | raw file
1#!/usr/bin/perl 2 3sub open_connection 4{ 5 return "exist" if ($REMOTE_SOCK); 6 my $paddr = inet_aton($_[0]); 7 socket REMOTE_SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp') or die "Cannot create socket\n"; 8 connect REMOTE_SOCK, sockaddr_in(21, $paddr) or die "Cannot connect to server '$_[0]'\n"; 9 $REMOTE_SOCK = 1; 10 $server_name = $_[0]; 11 my $str = listen_sock(*REMOTE_SOCK, $mode{'-T'}); 12 if ($str =~ /^404/) 13 { 14 print $str if $mode{'-v'}; 15 print " Server is hidden or simply offended at all.\n If you want to know what really happened,\n run the program without a parameter '-v'\n" unless $mode{'-v'}; 16 exit; 17 } 18 print $str if $mode{'-v'}; 19 if ($mode{'-a'}) 20 { 21 send REMOTE_SOCK, "USER anonymous".$EOL, 0; 22 send REMOTE_SOCK, "PASS Password".$EOL, 0; 23 } 24 else 25 { 26 print "User: " unless $mode{'-X'}; 27 $str = <STDIN>; 28 chomp $str; 29 send REMOTE_SOCK, "USER $str".$EOL, 0; 30 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 31 print "Password: " unless $mode{'-X'}; 32 if ($mode{'-X'}) 33 { 34 $str = <STDIN>; 35 } 36 else 37 { 38 ReadMode 2, STDIN; 39 $str = ReadLine(0); 40 ReadMode 0; 41 print "\n"; 42 } 43 chomp $str; 44 send REMOTE_SOCK, "PASS $str".$EOL, 0; 45 } 46 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 47 feat(); 48 send REMOTE_SOCK, "OPTS UTF8 ON".$EOL, 0 if $feat{'UTF8'}; 49 send REMOTE_SOCK, "TYPE I".$EOL, 0; 50 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 51 listen_sock(*REMOTE_SOCK, $mode{'-T'}) unless $mode{'-v'}; 52 return 1; 53} 54 55sub user 56{ 57 return "no_connect" unless $REMOTE_SOCK; 58 chomp $_[0]; 59 send REMOTE_SOCK, "USER $_[0]".$EOL, 0; 60 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 61 print "Password: " unless $mode{'-X'}; 62 if ($mode{'-X'}) 63 { 64 $str = <STDIN>; 65 } 66 else 67 { 68 ReadMode 2, STDIN; 69 $str = ReadLine(0); 70 ReadMode 0; 71 print "\n"; 72 } 73 chomp $str; 74 send REMOTE_SOCK, "PASS $str".$EOL, 0; 75 send REMOTE_SOCK, "OPTS UTF8 ON".$EOL, 0 if $feat{'UTF8'}; 76 send REMOTE_SOCK, "TYPE I".$EOL, 0; 77 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 78 listen_sock(*REMOTE_SOCK, $mode{'-T'}) unless $mode{'-v'}; 79 return 1; 80} 81 82sub ls 83{ 84 return "no_connect" unless $REMOTE_SOCK; 85 my ($ip, $port) = get_pasv(); 86 return 1 if ($ip == 530); 87 my $paddr = inet_aton($ip); 88 socket LIST_SOCK, PF_INET, SOCK_STREAM, getprotobyname('tcp') or die "Cannot create socket\n"; 89 connect LIST_SOCK, sockaddr_in($port, $paddr) or die "Cannot connect to server '$ip'\n"; 90 send REMOTE_SOCK, "$_[0]".$EOL, 0; 91 if ($mode{'-v'}) 92 { 93 print listen_sock(*LIST_SOCK, $mode{'-T'}); 94 } 95 else 96 { 97 my $ls = listen_sock(*LIST_SOCK, $mode{'-T'}); 98 print "$_\n", grep {$_ !~ /^[0-9]{3} /} (split /(\n)|(\r\n)/, $ls); 99 } 100 shutdown LIST_SOCK, 2; 101 return 1; 102} 103 104sub mv 105{ 106 $_[0] =~ /('|"|)?(.*?)\1 ('|"|)?(.*?)\3/g; 107 my ($param1, $param2) = ($2, $4); 108 return "no_connect" unless REMOTE_SOCK; 109 send REMOTE_SOCK, "RNFR $param1".$EOL, 0; 110 send REMOTE_SOCK, "RNTO $param2".$EOL, 0; 111 return 1; 112} 113 114sub size 115{ 116 return "no_connect" unless REMOTE_SOCK; 117 return "This command is not supported by server\n" unless $feat{'SIZE'}; 118 my $flag = 0; 119 /()/; 120 $flag = shift if ($_[0] =~ /^-h (.*)/); 121 send REMOTE_SOCK, "SIZE @{_}${1}".$EOL, 0; 122 my $str = listen_sock(*REMOTE_SOCK, $mode{'-T'}); 123 $str =~ /([0-9]{3}) ([0-9]*)/; 124 if ($1 != 213) 125 { 126 print $str if $mode{'-v'}; 127 return 1; 128 } 129 unless ($flag) 130 { 131 print $2, " B\n"; 132 return 1; 133 } 134 my $size = $2; 135 my @units = ('B', 'KB', 'MB', 'GB', 'TB', 'PB'); 136 my $units = 0; 137 while ($size >= 1024 && $units < 5) 138 { 139 $size /= 1024; 140 $units++; 141 } 142 print '', (sprintf "%.2f", $size), " $units[$units]\n"; 143 return 1; 144} 145 146sub simple_manipulation 147{ 148 return "no_connect" unless $REMOTE_SOCK; 149 my $todo = shift; 150 send REMOTE_SOCK, "$todo @_".$EOL, 0; 151 return 1; 152} 153 154sub disconnect 155{ 156 return "no_connect" unless $REMOTE_SOCK; 157 send REMOTE_SOCK, "QUIT".$EOL, 0; 158 print listen_sock(*REMOTE_SOCK, $mode{'-T'}) if $mode{'-v'}; 159 shutdown REMOTE_SOCK, 2; 160 $REMOTE_SOCK = 0; 161 return 1; 162} 163 164sub get_pasv 165{ 166 return "no_connect" unless $REMOTE_SOCK; 167 send REMOTE_SOCK, "PASV".$EOL, 0; 168 while (1) 169 { 170 my $str = listen_sock(*REMOTE_SOCK, $mode{'-T'}); 171 return 1 if $str =~ /530/; 172 print $str if $mode{'-v'}; 173 return ("$1.$2.$3.$4", ($5*256+$6)) if $str =~ /(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)/; 174 } 175} 176 177sub feat 178{ 179 return "no_connect" unless $REMOTE_SOCK; 180 send REMOTE_SOCK, "FEAT".$EOL, 0; 181 my $str = listen_sock(*REMOTE_SOCK, $mode{'-T'}); 182 $feat{$_} = 1 foreach (grep {/(SIZE)|(UTF8)/} (split " ", $str)); 183 184 return 1; 185} 186 187sub listen_sock 188{ 189 local *SOURCE = $_[0]; 190 my $timeout = $_[1]; 191 my ($buf, $res, $write_command, $rin, $rout) = ('defined :)', ''); 192 vec ($rin, fileno(SOURCE), 1) = 1; 193 while ($buf ne '') 194 { 195 my $nfound = select($rout = $rin, '', '', $timeout); 196 die 'Select() error' if ($nfound == -1); 197 last if ($nfound == 0); 198 die 'Recv() error' if (!defined(recv SOURCE, $buf, 512, 0)); #kakyato error 199 $res .= $buf; 200 } 201 return $res; 202} 203 204sub listen_sock_for_file 205{ 206 local (*SOURCE, *DEST) = ($_[0], $_[1]); 207 my $timeout = $_[2]; 208 my ($buf, $write_command, $rin, $rout) = ('defined :)'); 209 vec ($rin, fileno(SOURCE), 1) = 1; 210 while ($buf ne '') 211 { 212 my $nfound = select($rout = $rin, '', '', $timeout); 213 die 'Select() error' if ($nfound == -1); 214 last if ($nfound == 0); 215 die 'Recv() error' if (!defined(recv SOURCE, $buf, 512, 0)); 216 print DEST $buf; 217 } 218} 219 220sub help 221{ 222 my $param = lc shift; 223 my %help = 224 ( 225 'open' => "Connect to remote tftp", 226 'ls' => "List contents of remote directory", 227 'dir' => "List contents of remote directory (extended)", 228 'send' => "Send one file", 229 'recv' => "Receive file", 230 'cd' => "Change remote working directory", 231 'pwd' => "Print working directory on remote machine", 232 'user' => "Send new user information", 233 'mv' => "Rename file; file name with spaces must be quoted", 234 'rm' => "Delete remote file", 235 'mkdir' => "Make directory on the remote machine", 236 'rmdir' => "Remove directory on the remote machine", 237 'disconnect' => "Terminate ftp session", 238 'size' => "Returns size of file; type 'size -h' for human-readable format", 239 'quit' => "Terminate ftp session and exit" 240 ); 241 if ($param) 242 { 243 print "$param\t\t$help{$param}\n" if $help{$param}; 244 print "Unknown command\n" unless $help{$param}; 245 } 246 else 247 { 248 print "$_\t" foreach (sort keys %help); 249 print "\n"; 250 } 251 return 1; 252} 253 254sub usage_ftp 255{ 256 print "Transfers files to and from a computer running an FTP server service.\n\n"; 257 print "FTP [-h] [-v] [-a] [-T time] [-X filename] [host]\n\n"; 258 print " -h\t\tPrint this help and exit.\n"; 259 print " -a\t\tlogin as anonymous.\n"; 260 print " -v\t\tSuppresses display of remote server responses.\n"; 261 print " -T time\tSet how long to wait for a response from the server;\n\t\ttime in seconds.\n"; 262 print " -X filename\tSpecifies a text file containing FTP commands; the commands\n\t\twill automatically run after FTP starts.\n"; 263 print " host\t\tSpecifies the host name or IP address of the remote host\n\t\tto connect to.\n"; 264 return 1; 265} 266 2671;