分析 aMule / eMule 的 server.met 文件

前几天 DonkeyServer 被迫关闭了,原来的服务器列表里却不剩几个可用的服务器。连忙找人家 eMule 的服务器列表──server.met,打开一看,二进制的,晕!还好有 spec。

# !/usr/bin/perl -w

# server.met ref:
# http://www.amule.org/wiki/index.php/Server.met_file
#

use  strict;

my  (  $buf ,   $verify ,   $servers ,   $ip ,   $port ,   $tags ,   $tag_type ,   $tag_name_length ,
    
$tag_name ,   $tag_value_length ,   $tag_value  );
my   @ip ;
my   %tagid   =  (  0x01   =>   " Server name " ,   0x0b   =>   " Description " ,   0x0c   =>   " Ping " ,
    
0x0d   =>   " Fail " ,   0x0e   =>   " Preference " ,   0x85   =>   " DNS " ,   0x87   =>   " Max users " ,
    
0x88   =>   " Soft files " ,   0x89   =>   " Hard files " ,   0x90   =>   " Last ping " ,
    
0x91   =>   " Version " ,   0x92   =>   " UDP flags " ,   0x93   =>   " Auxiliary ports list " ,
    
0x94   =>   " LowID clients "  );
my   $output   =   '' ;

while  (  my   $file   =   shift   @ARGV  ) {

open  FH ,   " $file "  or  die   " Can't open file: $file " ;
binmode  FH;

sysread  ( FH ,   $buf ,   5  );
$verify ,   $servers  )  =   unpack  (  " CV " ,   $buf  );

#  Verify the file
unless  (  $verify   ==   0x0e   ||   $verify   ==   0xe0  ) {
    
close  FH;
    
printf   " %02x " ,   $verify ;
    
die   " The file: $file is NOT a verified server.met file " ;
}
else  {
    
# print "" . ( "=" x 78 ) . " File: $file ";
     $output   .=  (  " = "  x  78  )  .   " File: $file " ;
}

#  How many servers
#printf "Servers: %d ", $servers;

$output   .=   sprintf   " Servers: %d " ,   $servers ;

for  (  my   $i   =   0 $i   !=   $servers $i ++  ) {
    
# print '-' x 78, " ";
     $output   .=  (  ' - '  x  78  )  .   " " ;

    
sysread  ( FH ,   $buf ,   10 );
    ( 
$ip [ 0 ] ,   $ip [ 1 ] ,   $ip [ 2 ] ,   $ip [ 3 ] ,   $port ,   $tags  )  =   unpack  (  " C4vV " ,   $buf  );
    
# print "ip: ", join ( ".", @ip ), " ";
    #print "port: $port tags: $tags ";

     $output   .=   " ip:  "   .   join  (  " . " ,   @ip  )  .   " port: $port tags: $tags " ;

    
for  (  my   $j   =   0 $j   !=   $tags $j ++  ) {
        
sysread  ( FH ,   $buf ,   3  );
        ( 
$tag_type ,   $tag_name_length  )  =   unpack  (  " Cv " ,   $buf  );

        
sysread  ( FH ,   $tag_name ,   $tag_name_length  );
        
if  (  $tag_name_length   ==   1  ) {
            
$tag_name   =   unpack  (  " C " ,   $tag_name  );
            
$tag_name   =   $tagid { $tag_name ||   sprintf  (  " 0x%02x " ,   $tag_name  );
        }

        
if  (  $tag_type   ==   0x02  ) {       #  Is String
            #printf "S[0x%08X] %s: ", sysseek ( FH, 0, 1 ) + 2, $tag_name;

             $output   .=   sprintf   " S[0x%08X] %s:  " ,   sysseek  ( FH ,   0 ,   1  )  +   2 ,   $tag_name ;

            
sysread  ( FH ,   $buf ,   2  );
            
$tag_value_length   =   unpack  (  " v " ,   $buf  );
            
sysread  ( FH ,   $tag_value ,   $tag_value_length  );

            
#  strip the BOM off
             $tag_value   =   substr  (  $tag_value ,   3  )  if  (  substr  (  $tag_value ,   0 ,   3  ) eq  "  "  );
        }
        
elsif  (  $tag_type   ==   0x03  ) {    #  Is Numeric
            #printf "N[0x%08X] %s: ", sysseek ( FH, 0, 1 ), $tag_name;

             $output   .=   sprintf   " N[0x%08X] %s:  " ,   sysseek  ( FH ,   0 ,   1  ) ,   $tag_name ;

            
sysread  ( FH ,   $buf ,   4  );
            
$tag_value   =   unpack  (  " V " ,   $buf  );
        }
        
else  {                           #  Invalid
             printf   " Wrong tag type at %08x: %02x " ,
                
sysseek  ( FH ,   0 ,   1  )  -   $tag_name_length ,
                
$tag_type ;
            
close  FH;
            
die ;
        }

        
# print "$tag_value ";
         $output   .=   " $tag_value " ;
    }
}

close  FH;

}
print   $output ;

你可能感兴趣的:(perl)