Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
#!/usr/local/bin/perl
# $Id: ftptrans.pl,v 1.2 2002/02/17 11:07:28 68user Exp $
# ps で見られてもいいように $0 を書き換える
BEGIN {
$0=~s|^\S+ (\S+)|$1|;
}
use Socket; # Socketモジュールを使う
$username = '';
$password = '';
$hostname = '';
$target_file = '';
$mode = ''; # get か put
$passive = 0; # デフォルトは Active モード
$infile = '-'; # デフォルトは '-' ('-' は標準入力)
$outfile = '-'; # デフォルトは '-' ('>-' は標準出力)
$timeout = 0; # タイムアウトの秒数
$verbose = 0;
#----------------- 引数解析 ---------------------
# 引数がなかったらエラー
if ( ! @ARGV ){
&usage;
}
for ( $i=0 ; $i<@ARGV ; $i++ ){
$_ = $ARGV[$i];
# anonymous FTP
if ( m|^ftp://(.*)|i ){
if ( $1 =~ m|^([a-zA-Z0-9\.\-\_]+)(/?.*)$| ){
$hostname = $1;
$target_file = $2 || '/';
} else {
&usage;
}
$mode = 'get';
$username = 'anonymous';
# パスワードを作成するために、
# ユーザ名とホスト名を取得
$local_username = `whoami`; chop $local_username;
$local_hostname = `hostname`; chop $local_hostname;
$password = "$local_username\@$local_hostname";
} elsif ( m/^GET|PUT$/i ){
$mode = $_;
$mode =~ tr/A-Z/a-z/;
$_ = $ARGV[++$i];
if ( m|^(.*?)@([a-zA-Z0-9\.\-\_]+):(.*)$| ){
($username, $hostname, $target_file) = ($1, $2, $3);
} else {
&usage;
}
} elsif ( m/^-password$/i ){
$password = $ARGV[++$i] || &usage;
} elsif ( m/^-in$/i ){
$infile = $ARGV[++$i] || &usage;
} elsif ( m/^-out$/i ){
$outfile = $ARGV[++$i] || &usage;
} elsif ( m/^-timeout$/i ){
$timeout = $ARGV[++$i] || &usage;
&usage unless ( $timeout =~ m/^\d+$/ );
} elsif ( m/^-passive$/i ){
$passive = 1;
} elsif ( m/^-v$/i ){
$verbose = 1;
} else {
&usage;
}
}
# 必須の項目が未設定ならエラー
unless ( $mode || $hostname || $username || $filename ){
&usage;
}
# パスワードが未設定なら、標準入力から入力させる。
# stty でエコーバックを ON/OFF にしている。
while ( $password eq "" ){
print "Password: ";
system("stty -echo >/dev/null 2>&1");
$password = ;
chomp $password;
system("stty echo >/dev/null 2>&1");
print "\n";
}
if ( $verbose ){
print STDERR "-----------------------\n";
print STDERR "mode = $mode\n";
print STDERR "hostname = $hostname\n";
print STDERR "username = $username\n";
print STDERR "password = $password\n";
print STDERR "filename = $target_file\n";
print STDERR "infile = $infile\n";
print STDERR "outfile = $outfile\n";
print STDERR "timeout = $timeout\n";
print STDERR "-----------------------\n";
}
#----------------- タイムアウト設定 -------------------
if ( $timeout ){
$SIG{ALRM} = sub {
if ( defined $pid ){
kill 'TERM', $pid;
}
die "TIMEOUT! ($timeout secs)";
};
alarm($timeout);
}
#------ コマンドコネクションを作成し、ログイン --------
$port = getservbyname('ftp', 'tcp');
&client_work(COMMAND, $hostname, $port);
&read_response;
&send_command("USER $username\r\n");
&read_response;
&send_command("PASS $password\r\n");
$ret = &read_response;
if ( $ret =~ m/^5\d\d/ ){
print STDERR "ログインできませんでした。\n";
exit;
}
&send_command("TYPE I\r\n");
&read_response;
#----------- データコネクションオープン ------------
if ( ! $passive ){ # Active モード
($local_ip, $local_port) = &server_work;
# コマンドコネクションに PORT コマンドを送信
&send_command(
sprintf("PORT $local_ip,%d,%d\r\n", $local_port/256, $local_port%256)
);
&read_response;
} else { # Passive モード
&send_command("PASV\r\n");
$ret = &read_response;
# レスポンスから情報を取得
if ( $ret =~ m/^2\d\d .*\((\d+,\d+,\d+,\d+),(\d+),(\d+)\)/ ){
$data_connection_port = $2*256+$3;
$data_connection_host = $1;
$data_connection_host =~ s/,/\./g;
} else {
print STDERR $ret;
exit;
}
}
#------------- RETR/STOR/LIST を送信 ---------------
# put なら STOR
# get でディレクトリらしきものなら LIST
# get でファイルなら RETR
if ( $mode eq 'put' ){
&send_command("STOR $target_file\r\n");
} elsif ( $target_file =~ m|/$| ){
&send_command("LIST $target_file\r\n");
} else {
&send_command("RETR $target_file\r\n");
}
#---------------- データ送信/受信 ------------------
# 親プロセス
if ( $pid = fork() ){
$ret = &read_response;
# エラー。子プロセスを殺す
if ( $ret =~ m/^5/ ){
print STDERR $ret;
kill 'TERM', $pid;
} else {
&read_response;
}
# 子プロセス。データコネクションから読み込む
} else {
if ( $passive ){
&client_work(DATA, $data_connection_host, $data_connection_port);
} else {
accept(DATA, DATA_WAITING);
}
if ( $mode eq 'put' ){
open(IN, $infile) || die "$infile: $!";
while (){
print DATA $_;
}
close(IN);
} else {
open(OUT, ">$outfile") || die "$outfile: $!";
print OUT ;
close(OUT);
}
close(DATA);
exit;
}
# QUITを送ってセッション終了
&send_command("QUIT\r\n");
&read_response;
close(COMMAND);
exit;
#--------------------------------------------------------------
# サーバにデータを送信
#
sub send_command {
$verbose && print STDERR "$_[0]";
print COMMAND $_[0];
}
#--------------------------------------------------------------
# サーバからのレスポンスを読み込む。
# 複数行のレスポンスに対応。
sub read_response {
$buf = ;
$verbose && print STDERR "--> $buf";
# 複数行のレスポンス。
if ( $buf =~ m/^(\d\d\d)-/ ){
$return_code = $1;
while (){
$verbose && print STDERR "--> $_";
$buf .= $_;
if ( /^$return_code / ){
last;
}
}
}
return $buf;
}
#-------------------------------------------------------
# 引数でソケット名、ホスト、ポート番号を指定すると、
# ホスト、ポートに接続する。
sub client_work {
($SOCK, $host, $port) = @_;
# ホスト名を、IP アドレスの構造体に変換
unless ( $iaddr = inet_aton($host) ){
die "$host は存在しないホストです。$!";
}
# ポート番号と IP アドレスをまとめて構造体に変換
$sock_addr = pack_sockaddr_in($port, $iaddr);
# ソケット生成
socket($SOCK, PF_INET, SOCK_STREAM, 0)
|| die "ソケットを生成できません。\n";
# 指定のホストの指定の port に接続
connect($SOCK, $sock_addr)
|| die "$hostname のポート $port に接続できません。\n";
# ファイルハンドルをバッファリングしない
select($SOCK); $|=1; select(STDOUT);
}
#-------------------------------------------------------
# Active モードのデータ用コネクションを作成
sub server_work {
# ソケット生成
socket(DATA_WAITING, PF_INET, SOCK_STREAM, 0)
|| die "ソケットを生成できません。\n";
# ソケットオプション設定
setsockopt(DATA_WAITING, SOL_SOCKET, SO_REUSEADDR, 1)
|| die "setsockopt でエラーが発生しました。\n";
# ソケットにアドレス(=名前)を割り付ける
bind(DATA_WAITING, pack_sockaddr_in(0, INADDR_ANY))
|| die "bind に失敗しました。$!";
# OSに、クライアントと接続し待ち行列に入れるよう指示
listen(DATA_WAITING, SOMAXCONN)
|| die "listen に失敗しました。$!";
# ローカルホストの IP アドレス・ポート番号を取得
$local_sock_addr = getsockname(COMMAND);
($tmp_port, $local_addr) = unpack_sockaddr_in($local_sock_addr);
$local_ip = inet_ntoa($local_addr);
$local_ip =~ s/\./,/g;
# データコネクションのポート番号を取得
$local_sock_addr = getsockname(DATA_WAITING);
($local_port, $tmp_addr) = unpack_sockaddr_in($local_sock_addr);
return ($local_ip, $local_port);
}
#--------------------------------------------------------------
# 使用方法を表示して終了
#
sub usage {
$myname = $0; # 自分自身の名前を取得
$myname =~ s|(.*/)?||;
print STDERR <