PageRenderTime 48ms CodeModel.GetById 22ms app.highlight 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Anton.Dobrov/Perl/perlTask/ftp-client/Manage_ftp.pm

http://usu-wtf.googlecode.com/
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;