📄 web-ftp.cgi
字号:
#!/usr/bin/perl$| = 1;#BEGIN {# use POSIX;# @main::a = POSIX::times();#}use lib 'webftp';use IO::Socket;use strict;use MiniServer;use WebFTPPages; # ooh, Net::Gnift compliance.. if I ever get the d**m thing writtenBEGIN { $^W = 0; eval "use Net::Gnift qw(Net::FTP);"; if($@) { eval "use Net::FTP;"; if($@) { print qq`Content-Type: text/html\n\n<HTML><BODY>You do not have Net::FTP installed. You need it to use Web-FTP. You can find it on <A HREF="http://search.cpan.org/">CPAN</A></BODY></HTML>`; die "Net::FTP not found in \@INC: @INC"; } }} ############## Global vars ################my %conf;load_conf(\%conf);my($FTPhost,$FTPhostname);my $Version = '2.2.1';@{$conf{h}} = split /\s*,\s*/, $conf{ftphost};@{$conf{hn}} = split /\s*,\s*/, $conf{ftphostname};for(my $i=0; $i<=$#{$conf{h}}; $i++) { $conf{hn}->[$i] ||= $conf{h}->[$i]; $conf{whathostname}{$conf{h}->[$i]} = $conf{hn}->[$i];}unless($#{$conf{h}}) { $FTPhost = $conf{h}->[0]; $FTPhostname = $conf{hn}->[0];}# Don't alter these ## unless you know ## what you're doing # $FTPhostname ||= $FTPhost;my $BufferSize = 5 * 1024;my $CRLF = "\015\012";my $RemoteHost = $ENV{'REMOTE_ADDR'}; # These may have to change ifmy $Scriptname = $ENV{'SCRIPT_NAME'}; # you're not using Apache.my $Servername = $ENV{'HTTP_HOST'}; #my ($ServerPort,$FTP);$conf{SERVERNAME} = $Servername;$conf{SCRIPT_NAME} = $conf{maincgi};$conf{ORIG_SCRIPT_NAME} = $Scriptname;$conf{HTTP} = (($ENV{HTTPS} =~ /on/i )? 'https://' : 'http://');$conf{SCRIPT} = "$conf{HTTP}$conf{SERVERNAME}$Scriptname"; ############### Main program #################my($CONTENT,$EDITOR,$HTTPD);if($ENV{PATH_INFO}) { &HandleSession;} else { &UserLogin;} ################ Login handler ##################sub UserLogin { my($language, $host, $username, $password); while (<STDIN>) { if(/(?:language=([^&]*)&)?(?:host=([^&]*)&)?username=(\S*)&password=(\S*)/) { if($1) { load_lang(\%conf,$1); } $username = $3; $password = $4; $FTPhost = $FTPhostname = $2 if $2; $FTPhost ||= 'localhost'; $FTPhost =~ s/\%([A-Fa-f0-9]{2})/chr(hex($1))/eg if($FTPhost); $FTPhostname = ($conf{whathostname}{$FTPhost} || $FTPhost); } if($_ eq 'CRLF') { last; } } $username =~ s/\%([A-Fa-f0-9]{2})/chr(hex($1))/eg if($username); $password =~ s/\%([A-Fa-f0-9]{2})/chr(hex($1))/eg if($password); $conf{username} = $username; $conf{password} = $password; $CONTENT = WebFTPPages->new($Version, $FTPhost, $FTPhostname, $Servername, $conf{maincgi}, \%conf); $HTTPD = MiniServer->new($RemoteHost, $CONTENT, $Servername, \&FileMaster, \%conf); $conf{HTTPD} = $HTTPD; $conf{CONTENT} = $CONTENT; if($username && $password) { if(&TryFTPLogin([$username, $password, 1])) { #ANT: this is a major kludge... STDOUT not closing makes some # browsers hang and not redirect. However, closing STDOUT causes # apache to kill the cgi. SO! I must fork and close the parent, # then close STDOUT thus saving the day... till I find a better # solution# $HTTPD->WANT_COOKIE(1);# &TryFTPLogin([$username, $password]); close STDOUT; &Serve; } } else { $HTTPD->sendResponse($CONTENT->loginScreen()); exit(0); }}sub TryFTPLogin { my ($user, $pass, $test) = @{$_[0]}; #passed this way to hide password from logs, sigh unless($FTP = Net::FTP->new($FTPhost, Timeout => $conf{timeout}+50)) { $HTTPD->sendResponse($CONTENT->errorPage("Server said: $@")); die "Server said: $@"; } if($FTP->message() =~ /microsoft/i) { $conf{servertype} = 'MS'; $conf{hidepermissions} = 1; $conf{hidepermbutton} = 1; $conf{hideowngrp} = 1; }# print STDERR "---- ",$FTP->message(),"\n"; unless( $FTP->login($user, $pass) ) { if($FTP->message =~ /CRYPTOCard challenge (\d+)/i) { $conf{challenge} = $1; } else { my $mesg = $FTP->message; $FTP->quit; $HTTPD->sendResponse($CONTENT->failLogin($mesg)); exit(0); } } if(fork()) { $FTP->close(); exit(0); } $FTP->cwd($conf{initialdir}) if $conf{initialdir}; # All systems are go. Let's start the webserver. $conf{FTP} = $FTP; $HTTPD->startServer; $HTTPD->sendRedirect(sprintf("$conf{HTTP}$Servername$conf{maincgi}/%05d/START?$conf{challenge}",$$));} ############## Server core ################sub Serve { $SIG{ALRM} = \&Timeout; alarm($conf{timeout}); while(1) { unless($HTTPD->awaitConnection()) { next; } my $queryHashRef = $HTTPD->handleQueryHeaders(); next unless($queryHashRef); if($queryHashRef->{REQUEST_METHOD} eq 'GET') { &GetHandler($queryHashRef->{PATH}); } elsif($queryHashRef->{REQUEST_METHOD} eq 'POST') { &PostHandler($queryHashRef); } $HTTPD->closeConnection unless $conf{noclose}; $conf{noclose} = 0; }}sub GetHandler { $_ = shift;# s|^/(?:\Q$conf{SCRIPT_NAME}\E/)*||;# s|^/||g; if(($_ eq '') || ($_ eq 'LIST') || ($_ eq 'START')) { $CONTENT->updateDir($FTP->pwd()); $CONTENT->getDirectory($FTP->dir()); $HTTPD->genCookie(); $HTTPD->sendResponse($CONTENT->frameset()); } elsif($_ eq 'PUT') { $HTTPD->sendResponse($CONTENT->uploadScreen()); } elsif($_ eq 'MKDIR') { $HTTPD->sendResponse($CONTENT->mkdirScreen()); } elsif($_ eq 'CDUP') { $FTP->cdup; unshift @{$conf{messages}}, [time(), $FTP->message]; alarm($conf{timeout}); $HTTPD->sendRedirect("$conf{HTTP}$Servername$conf{SCRIPT_NAME}$conf{COOKIE}/"); } elsif($_ eq 'QUIT') { $FTP->quit; print STDERR "Exiting '$conf{HTTP}$Servername$conf{ORIG_SCRIPT_NAME}'\n"; $HTTPD->sendRedirect("$conf{HTTP}$Servername$conf{ORIG_SCRIPT_NAME}"); cleanup(); } elsif(/CDTO\?(.*)/) { $FTP->cwd($CONTENT->unencode($1)); unshift @{$conf{messages}}, [time(), $FTP->message]; alarm($conf{timeout}); $CONTENT->updateDir($FTP->pwd()); $CONTENT->getDirectory($FTP->dir()); $HTTPD->sendResponse($CONTENT->MAIN()); } elsif(/PERM\?(.*)/) { $HTTPD->sendResponse($CONTENT->permsScreen($1)); } elsif(/DNLD\?(.*)/) { my(%foo); $foo{Files} = [$1]; $foo{action} = ['download']; my $pwd = $FTP->pwd(); if($conf{challenge}) { download(\%foo); } elsif (!fork()) { close $FTP; # Much thanks to Graham Barr for this fix. unless($FTP = Net::FTP->new($FTPhost, Timeout => $conf{timeout}+50)) { $HTTPD->sendResponse($CONTENT->errorPage("Server said: ".$FTP->message)); die "Server said: ".$FTP->message; } $FTP->login($conf{username}, $conf{password}); unshift @{$conf{messages}}, [time(), $FTP->message]; $FTP->cwd($pwd); unshift @{$conf{messages}}, [time(), $FTP->message]; download(\%foo); $HTTPD->closeConnection(); exit(0); } } elsif(/EDIT\?(.*)/) { my(%foo); my $str = $1; $str =~ /file=([^&]+)/; $foo{Files} = [$1]; $foo{action} = ['edit']; $str =~ /editor=([^&]+)/; my $editor = $1; require "$editor.pm"; $EDITOR = eval "new $editor('conf' => \\\%conf)"; download(\%foo); } elsif(/MAIN/) { $CONTENT->updateDir($FTP->pwd()); $CONTENT->getDirectory($FTP->dir()); $HTTPD->sendResponse($CONTENT->MAIN()); } elsif($_) { my $str; s/\?(.*)$//; eval { $str = eval "\$CONTENT->$_(\$1)"; die if $@; }; if($@) { eval { $str = eval "\$EDITOR->$_(\$1)"; }; die if $@; } $HTTPD->sendResponse($str) if($str && !$@); }}BEGIN { # a horrendous kludge my $FILE; sub FileMaster { my $directive = shift; my $full_path = $_[1]; # Ewwwww ugly. # ant if($directive eq 'NEW') { my $filename = shift; $filename =~ s/^.*[\\\/\:]// unless $full_path; $_[2] ? $FTP->ascii : $FTP->binary; $FILE = $FTP->stor($filename); unshift @{$conf{messages}}, [time(), $FTP->message()]; } elsif($directive eq 'PUT') { my $buff = shift; if($FILE && length($buff)) { $FILE->write($buff, length($buff)); } } elsif($directive eq 'CLOSE') { if($FILE) { $FILE->close; $FILE = undef; alarm($conf{timeout}); } else { $conf{save_error} = 1; unshift @{$conf{messages}}, [time(), "Could not write file: ". $FTP->message()]; } } }}sub PostHandler { my $QueryHashRef = shift; my @keys = keys %$QueryHashRef; my @Files = @{$QueryHashRef->{'Files'}} if(exists($QueryHashRef->{'Files'})); my @Directories; @Directories = @{$QueryHashRef->{'Directories'}} if(exists($QueryHashRef->{'Directories'})); push @Directories, split "\n", $QueryHashRef->{'DirectoriesList'}->[0] if($QueryHashRef->{'DirectoriesList'}->[0]); my($Action) = @{$QueryHashRef->{'action'}} if(exists($QueryHashRef->{'action'})); print STDERR "Action is $Action\n"; if($Action eq 'download') { return &download($QueryHashRef); } elsif($Action eq 'site') { $FTP->quot('SITE',$Directories[0]); } elsif($Action eq 'edit') { $conf{EDITDATA} = $QueryHashRef->{data}[0]; doEditSave(); $HTTPD->sendResponse($EDITOR->SYS); return; } elsif($Action eq 'move') { $HTTPD->sendResponse($CONTENT->moveScreen(@Directories, @Files)); return; } elsif($Action eq $conf{lang}{move_button}) { print STDERR "Action is $Action MOVE\n"; while($_ = shift @Files) { $FTP->rename($_, shift @Directories); alarm($conf{timeout}); } } elsif($Action eq 'permissions') { $HTTPD->sendResponse($CONTENT->permsScreen(@Directories, @Files)); return 0; } elsif($Action eq $conf{lang}{change_permissions}) { my $i = 0; while($_ = shift @Files) { my $newperms = shift(@Directories); if($newperms) { if($newperms =~ /[0-7]{3,4}/) { $FTP->quot('SITE',"CHMOD $newperms $_"); } } else { $newperms = 0; if($QueryHashRef->{"perm_$i"}) { for(@{$QueryHashRef->{"perm_$i"}}) { $newperms |= $_; } $FTP->quot('SITE',sprintf("CHMOD %03o $_", $newperms)); } } $i++; alarm($conf{timeout}); } } elsif($Action eq 'chdir') { $FTP->cwd(shift @Directories); alarm($conf{timeout}); } elsif($Action eq $conf{lang}{make_directory}) { $FTP->mkdir(shift @Directories, 1); alarm($conf{timeout});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -