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

http://usu-wtf.googlecode.com/ · Perl · 267 lines · 262 code · 4 blank · 1 comment · 19 complexity · 8d9147f4f47fc9a88af39770edcf17b3 MD5 · raw file

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