Chinaunix首页 | 论坛 | 博客
  • 博客访问: 128240
  • 博文数量: 28
  • 博客积分: 2431
  • 博客等级: 大尉
  • 技术积分: 321
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 18:40
文章分类

全部博文(28)

文章存档

2011年(3)

2010年(6)

2009年(7)

2008年(12)

分类:

2010-08-20 16:29:39

网上看到很多通过邮件之类的东西来远控电脑下载啊,或者干别的软件,看了一下,发现这些软件的功能都十分有限,一般都是通过内置的一些系统命令,或者运行某些程序,但是却不能很好的看到程序的运行结果,因为软件不会反馈,so,有空无聊就搞了这么一个东西出来,现在也只是原型,但执行一些基本的东西应该是没问题的,下载的话,迟点还可以加上~~~本来我还想加上可以在邮件正文写代码,然后在目标机器中通过eval运行的,但是正文的解析,解码,比较麻烦,用模块的话,发现很多都不行,这就是我纠结的地方啊~~嘛~~~有时间以后再改吧。写的不好,望指正。
ps:这类的框架,应该用POE来写更好的吧··但是我没看过这个模块!!


#BY Weigun http://blog.chinaunix.net/u2/70443/

use strict;
use warnings;
use threads;
use threads::shared;
use Thread::Semaphore;
#use Thread::Queue;

use Config::IniFiles;
use Data::Dumper;
use Net::IMAP::Simple;
use POSIX qw(strftime);
use mail_parse;
use Mail::Sender;
use File::Spec::Functions;
use Cwd;
use Win32::ChangeNotify;
use Fcntl qw/:flock/;
BEGIN{push (@INC,'.');}
$|++;
our $conf_dir = catdir(getcwd(),'conf');
our $cfg_file = catfile($conf_dir,'conf.ini');
my $cmd_file = 'list.ini';
my $pre_mails_num = 'pre mails num.ini';
my $mails_ref;
my @threads;
my $pre = 74||get_pre_mails_num($pre_mails_num);
our $cfg_ref:shared = load_from_cfg_file($cfg_file);
my $cmd_list_ref = load_cmd_list_from_file($cmd_file);
my $imap;    #全局用,不传递

my $tid = threads->create(\&conf_file_watcher,$cfg_file); #监视配置文件,一旦发生改变,reload

$tid->detach;
my $running_threads=Thread::Semaphore->new($cfg_ref->{max_threads});
while(1)
{
    $imap = Net::IMAP::Simple->new($cfg_ref->{server}->{host}) || warn "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";    

    unless($imap->login($cfg_ref->{server}->{user},$cfg_ref->{server}->{pwd}))
    {
        err($imap->errstr);
        sleep 10;
        redo;
    }
    my $count_of_messages = $imap->select('INBOX');
    if ($count_of_messages > $pre)    
    {
        $mails_ref = get_new_mail_info($count_of_messages,$pre);
        my @jobs = get_jobs(map {$mails_ref->{$_}->{subject}} sort{$a <=> $b} keys(%$mails_ref));
        print "@jobs\n";
        write_cmd_log($mails_ref);
        $pre = $count_of_messages;
        save_mail_num_to_file($pre);
        while (my $job = shift @jobs)
        {
            $running_threads->down;
            my $tid = threads->create(\&start_job,$job,$cmd_list_ref);#

            push @threads,$tid;
        }
        while(my $thread = shift @threads)
        {
            print "ready to detach thread\n";
            $thread->detach;
            $running_threads->up;
        }
    }
    else
    {
        print "无新邮件\n";
#        ;

#        exit;

    }
    #$subjects_ref = get_new_mail_subject($count_of_messages);

#    for (sort{$b <=> $a} keys(%$mails_ref))

#    {

#        print "subject: $mails_ref->{$_}->{subject}\n";

#        print "date: $mails_ref->{$_}->{date}\n";

#        print '=' x 80,"\n";

#    }

#    exit;

    $imap->quit;
    sleep $cfg_ref->{sleep_time};
}

sub load_from_cfg_file
{
    my $file = shift;
    my $ini=Config::IniFiles->new( -file => $file);
    die "can't find $file:$!\n" if !$ini;    
    my $cfg = {};
    $cfg->{$_} = $ini->val('General',$_) for qw(log_dir script_dir neRe_dir max_threads sleep_time);
    $cfg->{server}->{$_} = $ini->val('IMAP SERVER',$_) for qw(host user pwd smtp);
    $cfg->{neRe_mail}->{$_} = $ini->val('neRe mail',$_) for qw(from user pwd to);
#    print Dumper $cfg;

    return shared_clone($cfg);
}

sub get_pre_mails_num
{
    my $file = shift;
    my $mail_num_conf=Config::IniFiles->new( -file => $file);
    die "can't find $file:$!\n" if !$mail_num_conf;
    return $mail_num_conf->val('num', 'total mails');
}

sub load_cmd_list_from_file
{
    my $file = shift;
  my $cmd = {};
  open FH,"<",catfile($conf_dir,$file);
  while (<FH>)
  {
      next if /^#/;

      my ($key,$value) = split /=/,$_;
      $cmd->{lc $key} = $value;
  }
  close FH;
  return $cmd;
}
sub get_new_mail_info
{
    my ($total,$pre) = @_;
    my $mail_info = {};
    for(my $i = $total; $total - $pre < $i; $i--)
    {
     next if $imap->seen($i);
     my $mail = mail_parse::new(\@{$imap->top($i)});
#        $mail_info->{$i}->{subject} = ($mail->get('subject'))=~/[cmd]/i ? $mail->get('subject') : next;

        $mail_info->{$i}->{subject} = $mail->get('subject');
     $mail_info->{$i}->{date} = format_date($mail->get('date'),'/');
        $imap->see($i)    #设置已读    #这条不要注释

    }
    return $mail_info;
}

sub format_date
{
    my ($date,$cvs) = @_;
    my ($day,$moon,$year,$time) = $date=~/\s*(\d+)\s+(\w+)\s+(\d+)\s+(.*?)\s+/;
    my %moon=(
                             'Jan' => '01',
                             'Feb' => '02',
                             'Mar' => '03',
                             'Apr' => '04',
                             'May' => '05',
                             'Jun' => '06',
                             'Jul' => '07',
                             'Aug' => '08',
                             'Sep' => '09',
                             'Oct' => '10',
                             'Nov' => '11',
                             'Dec' => '12',
                     );
  return join("$cvs",($year,$moon{$moon},$day))." $time";
}

sub save_mail_num_to_file
{
    my $file = 'pre mails num.txt';
    open F,">",$file;
    print F "total mails:",shift;
    close F;
}

sub write_cmd_log
{
    my $subjects_ref = shift;
    open LOG,">>",catfile($cfg_ref->{log_dir},'cmd.log');
    for (sort{$b <=> $a} keys(%$subjects_ref))
    {
        my $date_time = strftime "%y/%m/%d %H:%M:%S", localtime; #这里可以取邮件的时间作为参考

        print LOG "$date_time $subjects_ref->{$_}->{subject}\n" ;
    }
    close LOG;
}

sub get_jobs
{
    return my @jobs = grep {s{\[cmd\](.*)\[\\cmd\]}{$1}i} @_;
}

sub start_job
{
    my ($job,$cmd_list) = @_;
    print "job is: $job\n";
    my $out_file = catfile($cfg_ref->{neRe_dir},$job.'.txt');
    if ( (exists $cmd_list->{$job} && system $cmd_list->{$job}) or ($job=~/\[script\](.*)/i && system catfile($cfg_ref->{script_dir},$1),$out_file))
    {
        err("can't run job:$job");
    }
    sendMail($job,$out_file) if $job=~/neRe/; #如果有nere标记,则反馈程序执行 结果
    unlink $out_file || warn "can't del $out_file:$!\n";    
}

sub err
{
    my $err_msg = shift;
    open ERR,">>",catfile($cfg_ref->{log_dir},'err.log');
    flock(ERR,LOCK_EX) || warn "can't get lock:$!\n";
    my $date_time = strftime "%y/%m/%d %H:%M:%S", localtime;
    print ERR '[',$date_time,']',$err_msg,"\n";
    flock(ERR,LOCK_UN) || warn "can't unlock:$!\n";
    close ERR;
}

sub conf_file_watcher
{
    my $conf_file = shift;
    while(1)
    {
        my $notify = Win32::ChangeNotify->new($conf_dir,0,'LAST_WRITE'); #注意路径

     $notify->wait || warn "Notify error: $!\n";
     $notify->reset;
        $cfg_ref = load_from_cfg_file($cfg_file);
        select(undef, undef, undef, 5);
    }
}

sub check_neRe_dir_full
{
    opendir DH,$cfg_ref->{neRe_dir} ||die "can't open dir:$!\n";
    my @files = grep{!/^\./}readdir DH;
#    unlink catfile($neRe_dir,$_) for (@files) if @files > 100;

}

sub sendMail
{
    my ($job,$file_name) = @_;
    my $msg;
    open F,"<",$file_name;
    $msg.=$_ while (<F>);
    close F;
    my $subject = 'neRe:'.$job;
    my $sender;
    $sender=new Mail::Sender();
    #     #my @protocols = $sender->QueryAuthProtocols(); 查询服务器支持的认证方式

    if ($sender->MailMsg({
     smtp => $cfg_ref->{server}->{smtp},
     from => $cfg_ref->{neRe_mail}->{from},
     to =>$cfg_ref->{neRe_mail}->{to},
     subject => $subject, #主题

     msg => $msg, #内容

     auth => 'LOGIN', #smtp的验证方式    

     authid =>$cfg_ref->{neRe_mail}->{user}, #user

     authpwd => $cfg_ref->{neRe_mail}->{pwd}, #pwd

     }) < 0) {
     warn "$Mail::Sender::Error\n";
     }
    else
    {
     print "neRe Mail sent OK.\n";
    }
}


阅读(1215) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~