File Coverage

blib/lib/Net/DirectConnect/clihub.pm
Criterion Covered Total %
statement 36 296 12.1
branch 0 202 0.0
condition 0 120 0.0
subroutine 12 63 19.0
pod 0 2 0.0
total 48 683 7.0


line stmt bran cond sub pod time code
1             #$Id: clihub.pm 998 2013-08-14 12:21:20Z pro $ $URL: svn://svn.setun.net/dcppp/trunk/lib/Net/DirectConnect/clihub.pm $
2             package #hide from cpan
3             Net::DirectConnect::clihub;
4 1     1   865 use strict;
  1         3  
  1         27  
5 1     1   6 no strict qw(refs);
  1         1  
  1         22  
6 1     1   4 use warnings "NONFATAL" => "all";
  1         1  
  1         41  
7 1     1   5 no warnings qw(uninitialized);
  1         1  
  1         29  
8 1     1   4 no if $] >= 5.017011, warnings => 'experimental::smartmatch';
  1         2  
  1         4  
9 1     1   35 use utf8;
  1         1  
  1         4  
10 1     1   20 use Time::HiRes qw(time sleep);
  1         1  
  1         8  
11 1     1   161 use Data::Dumper; #dev only
  1         2  
  1         46  
12             $Data::Dumper::Sortkeys = $Data::Dumper::Indent = 1;
13 1     1   4 use Net::DirectConnect;
  1         15  
  1         14  
14 1     1   450 use Net::DirectConnect::clicli;
  1         2  
  1         66  
15             #use Net::DirectConnect::http;
16             our $VERSION = ( split( ' ', '$Revision: 998 $' ) )[1];
17 1     1   6 use base 'Net::DirectConnect';
  1         2  
  1         863  
18              
19             sub name_to_ip($) {
20 0     0 0   my ($name) = @_;
21 0 0         unless ( $name =~ /^\d+\.\d+\.\d+\.\d+$/ ) {
22 0           local $_ = ( gethostbyname($name) )[4];
23 0 0         return ( $name, 1 ) unless length($_) == 4;
24 0           $name = inet_ntoa($_);
25             }
26 0           return $name;
27             }
28              
29             sub init {
30 0     0 0   my $self = shift;
31             #%$self = (
32             #%$self,
33 0           local %_ = (
34             'Nick' => 'NetDCBot',
35             'port' => 411,
36             'host' => 'localhost',
37             'Pass' => '',
38             'key' => 'zzz',
39             #'auto_wait' => 1,
40             'supports_avail' => [ qw(
41             NoGetINFO
42             NoHello
43             UserIP2
44             UserCommand
45             TTHSearch
46             OpPlus
47             Feed
48             MCTo
49             HubTopic
50             )
51             ],
52             'search_every' => 10,
53             'search_every_min' => 10,
54             'auto_connect' => 1,
55             'auto_bug' => 1,
56             'reconnects' => 99999,
57             'NoGetINFO' => 1, #test
58             'NoHello' => 1,
59             'UserIP2' => 1,
60             'TTHSearch' => 1,
61             'Version' => '1,0091',
62             'auto_GetNickList' => 1,
63             'follow_forcemove' => 1,
64             'incomingclass' => 'Net::DirectConnect::clicli',
65             'disconnect_recursive' => 1,
66             );
67 0   0       $self->{$_} //= $_{$_} for keys %_;
68             $self->{'periodic'}{ __FILE__ . __LINE__ } = sub {
69 0 0   0     my $self = shift if ref $_[0];
70 0 0         $self->search_buffer() if $self->{'socket'};
71 0           };
72             #$self->log($self, 'inited',"MT:$self->{'message_type'}", ' with', Dumper \@_);
73             #$self->baseinit();
74             #share_full share_tth want
75 0   0       $self->{$_} ||= $self->{'parent'}{$_} ||= {} for qw( NickList IpList PortList PortList_udp); #handler
      0        
76             #$self->{'NickList'} ||= {};
77             #$self->{'IpList'} ||= {};
78             #$self->{'PortList'} ||= {};
79             #$self->log( $self, 'inited3', "MT:$self->{'message_type'}", ' with' );
80             #You are already in the hub.
81             # $self->{'parse'} ||= {
82 0           $self->module_load('filelist');
83             local %_ = (
84             'chatline' => sub {
85 0 0   0     my $self = shift if ref $_[0];
86             #$self->log( 'dev', Dumper \@_);
87 0           my ( $nick, $text ) = $_[0] =~ /^(?:<|\* )(.+?)>? (.+)$/s;
88             #$self->log('dcdev', 'chatline parse', Dumper(\@_,$nick, $text));
89             $self->log( 'warn', "[$nick] oper: already in the hub [$self->{'Nick'}]" ), $self->nick_generate(), $self->reconnect(),
90 0 0 0       if ( ( !keys %{ $self->{'NickList'} } or $self->{'NickList'}{$nick}{'oper'} )
      0        
91             and $text eq 'You are already in the hub.' );
92 0 0 0       if ( $self->{'NickList'}{$nick}{'oper'} or $self->{'NickList'}{$nick}{'hubbot'} or $nick eq 'Hub-Security' ) {
      0        
93 0 0 0       if (
      0        
      0        
      0        
94             $text =~
95             /Минимальный интервал поиска составляет: \(Minimum search interval is:\) (\d+)секунд \(seconds\)/
96             or $text =~ /^(?:Minimum search interval is|Минимальный интервал поиска):(\d+)s/
97             or $text =~ /Search ignored\. Please leave at least (\d+) seconds between search attempts\./ #Hub-Security opendchub
98             or $text =~
99             /Минимальный интервал между поисковыми запросами:(\d+)сек., попробуйте чуть позже/
100             or $text =~ /You can do 1 searches in (\d+) seconds/
101             )
102             {
103 0   0       $self->{'search_every'} = int( rand(5) + $1 || $self->{'search_every_min'} );
104 0           $self->log( 'warn', "[$nick] oper: set min interval = $self->{'search_every'}" );
105 0           $self->search_retry();
106             }
107 0 0 0       if ( $text =~
      0        
      0        
      0        
108 1     1   7 /(?:Пожалуйста )?подождите (\d+) секунд перед следующим поиском\./i
  1         2  
  1         16  
109             or $text =~ /(?:Please )?wait (\d+) seconds before next search\./i
110             or $text eq 'Пожалуйста не используйте поиск так часто!'
111             or $text eq "Please don't flood with searches!"
112             or $text eq 'Sorry Hub is busy now, no search, try later..' )
113             {
114 0   0       $self->{'search_every'} += int( rand(5) + $1 || $self->{'search_every_min'} );
115 0           $self->log( 'warn', "[$nick] oper: increase min interval => $self->{'search_every'}" );
116 0           $self->search_retry();
117             }
118             }
119 0 0 0       if ( !$self->{count_parse}{chatline} and $text =~ /PtokaX/i ) {
120             #$self->log( 'dev', "[$nick] - probably hub bot" );
121 0           $self->{'NickList'}{$nick}{'hubbot'} = 1;
122             }
123 0 0 0       $self->search_retry(),
124             if $self->{'NickList'}->{$nick}{'oper'} and $text eq 'Sorry Hub is busy now, no search, try later..';
125             },
126             'welcome' => sub {
127 0 0   0     my $self = shift if ref $_[0];
128 0           my ( $nick, $text ) = $_[0] =~ /^(?:<|\* )(.+?)>? (.+)$/s;
129 0 0 0       if ( !keys %{ $self->{'NickList'} } or !exists $self->{'NickList'}->{$nick} or $self->{'NickList'}->{$nick}{'oper'} ) {
      0        
130 0 0 0       if ( $text =~ /^Bad nickname: unallowed characters, use these (\S+)/ )
    0 0        
    0 0        
      0        
131             #
132             {
133 0           my $try = $self->{'Nick'};
134 0           $try =~ s/[^\Q$1\E]//g;
135 0           $self->log( 'warn', "CHNICK $self->{'Nick'} -> $try" );
136 0 0         $self->{'Nick'} = $try if length $try;
137             } elsif ( $text =~ /Bad nickname: Wait (\d+)sec before reconnecting/i
138             or $text =~
139             /Пожалуйста подождите (\d+) секунд до повторного подключения\./
140             or $text =~ /Do not reconnect too fast. Wait (\d+) secs before reconnecting./ )
141             {
142             #sleep $1 + 1;
143 0           $self->work( $1 + 10 );
144             } elsif ( $self->{'auto_bug'} and $nick eq 'VerliHub' and $text =~ /^This Hub Is Running Version 0.9.8d/i ) { #_RC1
145 0           ++$self->{'bug_MyINFO_last'};
146 0           $self->log( 'dev', "possible bug fixed [$self->{'bug_MyINFO_last'}]" );
147             }
148             }
149             },
150             'Lock' => sub {
151 0 0   0     my $self = shift if ref $_[0];
152             #$self->log( "lockparse", @_ );
153 0           $self->{'sendbuf'} = 1;
154 0           $self->cmd('Supports');
155 0           my ($lock) = $_[0] =~ /^(.+?)(\s+Pk=.+)?\s*$/is;
156             #print "lock[$1]\n";
157             #$self->log( 'dev', "lock from [$_[0]] = [$lock]");
158 0           $self->cmd( 'Key', $self->lock2key($lock) );
159 0           $self->{'sendbuf'} = 0;
160 0           $self->cmd('ValidateNick');
161             },
162             'Hello' => sub {
163 0 0   0     my $self = shift if ref $_[0];
164             #$self->log('info', "HELLO recieved, connected. me=[$self->{'Nick'}]", @_);
165 0 0         return unless $_[0] eq $self->{'Nick'};
166 0           $self->{'sendbuf'} = 1;
167 0           $self->cmd('Version');
168 0 0         $self->{'sendbuf'} = 0 unless $self->{'auto_GetNickList'};
169 0 0         $self->cmd('MyINFO') unless $self->{'bug_MyINFO_last'};
170 0 0         $self->{'sendbuf'} = 0, $self->cmd('GetNickList') if $self->{'auto_GetNickList'};
171 0 0         $self->{'sendbuf'} = 0, $self->cmd('MyINFO') if $self->{'bug_MyINFO_last'};
172 0           $self->{'status'} = 'connected';
173 0 0         $self->cmd('BotINFO') if $self->{botinfo};
174 0           $self->cmd('make_hub');
175             },
176             'Supports' => sub {
177 0 0   0     my $self = shift if ref $_[0];
178 0           $self->supports_parse( $_[0], $self );
179             },
180             'ValidateDenide' => sub {
181 0 0   0     my $self = shift if ref $_[0];
182 0           $self->log( 'warn', "ValidateDenide", $self->{'Nick'}, @_ );
183 0           $self->cmd('nick_generate');
184 0           $self->cmd('ValidateNick');
185             },
186             'To' => sub {
187 0 0   0     my $self = shift if ref $_[0];
188             #$self->log( 'msg', "Private message to", @_ );
189             #@_;
190 0           undef;
191             },
192             'MyINFO' => sub {
193 0 0   0     my $self = shift if ref $_[0];
194 0           my ( $nick, $info ) = $_[0] =~ /\S+\s+(\S+)\s+(.*)/;
195 0           $self->{'NickList'}->{$nick}{'Nick'} = $nick;
196 0           $self->info_parse( $info, $self->{'NickList'}{$nick} );
197 0           $self->{'NickList'}->{$nick}{'online'} = 1;
198             },
199             'UserIP' => sub {
200 0 0   0     my $self = shift if ref $_[0];
201             /(\S+)\s+(\S+)/, $self->{'NickList'}{$1}{'ip'} = $2, $self->{'IpList'}{$2} = $self->{'NickList'}{$1},
202             $self->{'IpList'}{$2}{'port'} = $self->{'PortList'}{$2}
203 0           for grep $_, split /\$\$/, $_[0];
204             },
205             'HubName' => sub {
206 0 0   0     my $self = shift if ref $_[0];
207 0           $self->{'HubName'} = $_[0];
208             },
209             'HubTopic' => sub {
210 0 0   0     my $self = shift if ref $_[0];
211 0           $self->{'HubTopic'} = $_[0];
212             },
213             'NickList' => sub {
214 0 0   0     my $self = shift if ref $_[0];
215 0           $self->{'NickList'}->{$_}{'online'} = 1 for grep $_, split /\$\$/, $_[0];
216 0 0         $self->GetINFO() if $self->{auto_GetINFO};
217             },
218             'OpList' => sub {
219 0 0   0     my $self = shift if ref $_[0];
220 0           $self->{'NickList'}->{$_}{'oper'} = 1 for grep $_, split /\$\$/, $_[0];
221             },
222             'ForceMove' => sub {
223 0 0   0     my $self = shift if ref $_[0];
224 0           my ($to) = grep { length $_ } split /;/, $_[0];
  0            
225 0           $self->log( 'warn', "ForceMove to $to :: ", @_ );
226 0           $self->disconnect();
227 0           sleep(1);
228 0 0 0       $self->connect($to) if $self->{'follow_forcemove'} and $to;
229             },
230             'Quit' => sub {
231 0 0   0     my $self = shift if ref $_[0];
232 0           $self->{'NickList'}->{ $_[0] }{'online'} = 0;
233             },
234             'ConnectToMe' => sub {
235 0 0   0     my $self = shift if ref $_[0];
236 0           my ( $nick, $host, $port ) = $_[0] =~ /\s*(\S+)\s+(\S+)\:(\S+)/;
237 0           $self->{'IpList'}{$host}{'port'} = $self->{'PortList'}->{$host} = $port;
238             #$self->log('dev', "portlist: $host = $self->{'PortList'}->{$host} :=$port");
239 0 0         $self->log("ignore flooding attempt to [$host:$port ] ($self->{flood}{$host})"), $self->{flood}{$host} = time + 30,
240             return
241             if $self->{flood}{$host} > time;
242 0           $self->{flood}{$host} = time + 60;
243 0 0         return if $self->{'clients'}{ $host . ':' . $port }->{'socket'};
244 0           $self->{'clients'}{ $host . ':' . $port } = Net::DirectConnect::clicli->new(
245             #! %$self, $self->clear(),
246             parent => $self, 'host' => $host, 'port' => $port,
247             #'want' => \%{ $self->{'want'} }, 'NickList' => \%{ $self->{'NickList'} }, 'IpList' => \%{ $self->{'IpList'} }, 'PortList' => \%{ $self->{'PortList'} }, 'handler' => \%{ $self->{'handler'} },
248             #'want' => $self->{'want'},
249             #'NickList' => $self->{'NickList'},
250             #'IpList' => $self->{'IpList'},
251             #'PortList' => $self->{'PortList'},
252             #'handler' => $self->{'handler'},
253             #'share_tth' => $self->{'share_tth'},
254             #'reconnects' => 0,
255             'auto_connect' => 1,
256             );
257             },
258             'RevConnectToMe' => sub {
259 0 0   0     my $self = shift if ref $_[0];
260 0           my ( $to, $from ) = split /\s+/, $_[0];
261             #$self->log( 'dev', "[$from eq $self->{'Nick'}] ($_[0])" );
262             #$self->log( 'dev', 'go ctm' ),
263 0 0         $self->cmd( 'ConnectToMe', $to ) if $from eq $self->{'Nick'};
264             },
265             'GetPass' => sub {
266 0 0   0     my $self = shift if ref $_[0];
267 0           $self->cmd('MyPass');
268             },
269             'BadPass' => sub {
270 0 0   0     my $self = shift if ref $_[0];
271             },
272             'LogedIn' => sub {
273 0 0   0     my $self = shift if ref $_[0];
274             },
275             'Search' => sub {
276 0 0   0     my $self = shift if ref $_[0];
277 0           my $search = $_[0];
278 0           $self->make_hub();
279 0           my $params = { 'time' => int( time() ), 'hub' => $self->{'hub_name'}, };
280 0           ( $params->{'who'}, $params->{'cmds'} ) = split /\s+/, $search;
281 0           $params->{'cmd'} = [ split /\?/, $params->{'cmds'} ];
282 0 0         if ( $params->{'who'} =~ /^Hub:(.+)$/ ) { $params->{'nick'} = $1; }
  0            
283 0           else { ( $params->{'ip'}, $params->{'udp'} ) = split /:/, $params->{'who'}; }
284 0 0         if ( $params->{'cmd'}[4] =~ /^TTH:([0-9A-Z]{39})$/ ) { $params->{'tth'} = $1; }
  0            
285 0           else { $params->{'string'} = $params->{'cmd'}[4]; }
286 0 0         $self->{'PortList_udp'}->{ $params->{'ip'} } = $params->{'udp'} if $params->{'udp'};
287 0           $params->{'string'} =~ tr/$/ /;
288             #$self->cmd('make_hub');
289             #r$self->{'share_tth'}
290 0   0       my $found = $self->{'share_full'}{ $params->{'tth'} } || $self->{'share_full'}{ $params->{'string'} };
291 0           my $tth = $self->{'share_tth'}{$found};
292 0 0 0       if (
293             $found
294             and $tth
295             #$params->{'tth'} and $self->{'share_tth'}{ $params->{'tth'} }
296             )
297             {
298 0           $self->log(
299             'adcdev', 'Search', $params->{'who'},
300             #$self->{'share_tth'}{ $params->{'tth'} },
301             $found, -s $found, -e $found,
302             ),
303             #$self->{'share_tth'}{ $params->{'tth'} } =~ tr{\\}{/};
304             #$self->{'share_tth'}{ $params->{'tth'} } =~ s{^/+}{};
305             my $path;
306 0 0         if ( $self->{'adc'} ) {
307 0           $path = $self->adc_path_encode(
308             $found
309             #$self->{'share_tth'}{ $params->{'tth'} }
310             );
311             } else {
312 0           $path = $found; #$self->{'share_tth'}{ $params->{'tth'} };
313 0           $path =~ s{^\w:}{};
314 0           $path =~ s{^\W+}{};
315 0           $path =~ tr{/}{\\};
316 0 0         $path = Encode::encode $self->{charset_protocol}, Encode::decode( $self->{charset_fs}, $path, Encode::FB_WARN ),
317             Encode::FB_WARN
318             if $self->{charset_fs} ne $self->{charset_protocol};
319             }
320 0 0 0       local @_ = (
    0 0        
321             'SR', (
322             #( $self->{'M'} eq 'P' or !$self->{'myport_tcp'} or !$self->{'myip'} ) ?
323             $self->{'Nick'}
324             #: $self->{'myip'} . ':' . $self->{'myport_tcp'}
325             ),
326             $path . "\x05" . ( -s $found or -1 ),
327             $self->{'S'} . '/'
328             . $self->{'S'} . "\x05"
329             .
330             #"TTH:" . $params->{'tth'}
331             ( $params->{'tth'} ? $params->{'cmd'}[4] : "TTH:" . $tth )
332             #. ( $self->{'M'} eq 'P' ? " ($self->{'host'}:$self->{'port'})" : '' ),
333             #. ( " ($self->{'host'}:$self->{'port'})\x05$params->{'nick'}" ),
334             . (
335             #" ($self->{'host'}:$self->{'port'})"
336             #" (".name_to_ip($self->{'host'}).":$self->{'port'})"
337             #" (".inet_ntoa(gethostbyname ($self->{'host'})).":$self->{'port'})"
338             " ($self->{'hostip'}:$self->{'port'})" . ( ( $params->{'ip'} and $params->{'udp'} ) ? '' : "\x05$params->{'nick'}" )
339             ),
340             #. ( $self->{'M'} eq 'P' ? " ($self->{'host'}:$self->{'port'})\x05$params->{'nick'}" : '' ),
341             #{ SI => -s $self->{'share_tth'}{ $params->{TR} },SL => $self->{INF}{SL},FN => $self->adc_path_encode( $self->{'share_tth'}{ $params->{TR} } ),=> $params->{TO} || $self->make_token($peerid),TR => $params->{TR}}
342             );
343 0 0 0       if ( $params->{'ip'} and $params->{'udp'} ) {
344 0           $self->send_udp( $params->{'ip'}, $params->{'udp'}, $self->{'cmd_bef'} . join ' ', @_ );
345             } else {
346 0           $self->cmd(@_);
347             }
348             }
349             #'SR', ( $self->{'M'} eq 'P' ? "Hub:$self->{'Nick'}" : "$self->{'myip'}:$self->{'myport_udp'}" ), join '?',
350             #Hub: [Outgoing][80.240.208.42:4111] $SR prrrrroo0 distr\s60\games\10598_paintball2.zip621237 1/2TTH:3TFVOXE2DS6W62RWL2QBEKZBQLK3WRSLG556ZCA (80.240.208.42:4111)breathe|
351             #$SR prrrrroo0 distr\moscow\mom\Mo\P\Paintball.htm1506 1/2TTH:NRRZNA5MYJSZGMPQ634CPGCPX3ZBRLKHAACPAFQ (80.240.208.42:4111)breathe|
352             #$SR prrrrroo0 distr\moscow\mom\Map\P\Paintball.htm3966 1/2TTH:QLRRMET6MSNJTIRKBDLQYU6RMI5QVZDZOGAXEXA (80.240.208.42:4111)breathe|
353             #$SR ILICH ЕГТС_07_2007\bases\sidhouse.DBF120923801 6/8TTH:4BAKR7LLXE65I6S4HASIXWIZONBEFS7VVZ7QQ2Y (80.240.211.183:411)
354             #$SR gellarion7119 MuZonnO\Mark Knopfler - Get Lucky (2009)\mark_knopfler_-_you_cant_beat_the_house.mp36599140 7/7TTH:IDPHZ4AJIIWDYOFEKCCVJUNVIPGSGTYFW5CGEQQ (80.240.211.183:411)
355             #$SR 13th_day Картинки\еще девки\sacrifice_penthouse02.jpg62412 0/20TTH:GHMWHVBKRLF52V26VFO4M4RUQ65NC3YKWIW7FPI (80.240.211.183:411)
356             #DIRECT:
357             #$SR server1 server\Unsorted\Desperate.Housewives.S04.720p.HDTV.x264\desperate.housewives.s04e03.720p.hdtv.x264.Rus.Eng.mkv1194423977 2/2TTH:6YWRGDXNQJEOGSB4Q7Y3Y7XRM7EXPLUK7GBRJ3A (80.240.211.183:411)
358             #$SR MikMEBX Deep purple\1980-1988\08-The House Of Blue Light.1987 10/10[ f12p.ru ][ F12P-HUB ] - день единства... вспомните хорошее и улыбнитесь друг другу.. пусть это будет днем гармонии (80.240.211.183)
359             #PASSIVE
360             #$SR ILICH ЕГТС_07_2007\bases\sidhouse.DBF120923801 6/8TTH:4BAKR7LLXE65I6S4HASIXWIZONBEFS7VVZ7QQ2Y (80.240.211.183:411)
361             #$SR gellarion7119 MuZonnO\Mark Knopfler - Get Lucky (2009)\mark_knopfler_-_you_cant_beat_the_house.mp36599140 7/7TTH:IDPHZ4AJIIWDYOFEKCCVJUNVIPGSGTYFW5CGEQQ (80.240.211.183:411)
362             #$SR SALAGA Видео\Фильмы\XXX\xxx Penthouse.avi732665856 0/5TTH:3OFCM6GPQZNBNAMV6SRDFHFPK2X76EO6UCIO7ZQ (80.240.211.183:411)
363 0           return $params;
364             },
365             'SR' => sub {
366 0 0   0     my $self = shift if ref $_[0];
367             #$self->log( 'dev', "SR", @_ , 'parent=>', $self->{parent}, 'h=', $self->{handler}, Dumper($self->{handler}), 'ph=', $self->{parent}{handler}, Dumper($self->{parent}{handler}), ) if $self;
368 0           $self->make_hub();
369 0           my $params = { 'time' => int( time() ), 'hub' => $self->{'hub_name'}, };
370 0           ( $params->{'nick'}, $params->{'str'} ) = split / /, $_[0], 2;
371 0           $params->{'str'} = [ split /\x05/, $params->{'str'} ];
372 0           $params->{'file'} = shift @{ $params->{'str'} };
  0            
373 0           ( $params->{'filename'} ) = $params->{'file'} =~ m{([^\\]+)$};
374 0           ( $params->{'ext'} ) = $params->{'filename'} =~ m{[^.]+\.([^.]+)$};
375 0           ( $params->{'size'}, $params->{'slots'} ) = split / /, shift @{ $params->{'str'} };
  0            
376 0           ( $params->{'tth'}, $params->{'ipport'} ) = split / /, shift @{ $params->{'str'} };
  0            
377 0 0         ( $params->{'tth'}, $params->{'ipport'} ) = ( $params->{'size'}, $params->{'slots'} ) unless $params->{'tth'};
378 0           ( $params->{'target'} ) = shift @{ $params->{'str'} };
  0            
379 0           $params->{'tth'} =~ s/^TTH://;
380 0           ( $params->{'ipport'}, $params->{'ip'}, $params->{'tcp'} ) = $params->{'ipport'} =~ /\(((\S+):(\d+))\)/;
381 0           delete $params->{'str'};
382             #( $params->{'slotsopen'}, $params->{'S'} ) = split /\//, $params->{'slots'};
383             #$params->{'slotsfree'} = $params->{'S'} - $params->{'slotsopen'};
384 0           ( $params->{'slotsfree'}, $params->{'S'} ) = split /\//, $params->{'slots'};
385             #$params->{'slotsfree'} = $params->{'S'} - $params->{'slotsopen'};
386 0           $params->{'string'} = $self->{'search_last_string'};
387 0           $self->{'NickList'}{ $params->{'nick'} }{$_} = $params->{$_} for qw(S ip tcp);
388 0           $self->{'PortList'}->{ $params->{'ip'} } = $params->{'tcp'};
389 0           $self->{'IpList'}->{ $params->{'ip'} } = $self->{'NickList'}{ $params->{'nick'} };
390 0           $params->{'TR'} = $params->{'tth'};
391 0           $params->{FN} = $params->{'filename'};
392 0           my $peerid = $params->{'nick'};
393 0           $params->{CID} = $peerid;
394             #($params->{'file'}) = $params->{FN} =~ m{([^\\/]+)$};
395 0   0       my $wdl = $self->{'want_download'}{ $params->{'TR'} } || $self->{'want_download'}{ $params->{'filename'} };
396 0 0         if ($wdl) { #exists $self->{'want_download'}{ $params->{'TR'} } ) {
397             #$self->{'want_download'}{ $params->{'TR'} }
398 0           $wdl->{$peerid} = $params; #maybe not all
399 0 0         if ( $params->{'filename'} ) { ++$self->{'want_download_filename'}{ $params->{TR} }{ $params->{'filename'} }; }
  0            
400 0           $self->{'want_download'}{ $params->{TR} }{$peerid} = $params; # _tth_from
401             }
402 0           return $params;
403             },
404             'UserCommand' => sub {
405 0 0   0     my $self = shift if ref $_[0];
406             },
407             #};
408 0           );
409 0   0       $self->{'parse'}{$_} ||= $_{$_} for keys %_;
410              
411             =COMMANDS
412              
413              
414              
415              
416              
417              
418              
419              
420             =cut
421              
422             #$self->{'cmd'} = {
423             local %_ = (
424             'connect_aft' => sub {
425 0 0   0     my $self = shift if ref $_[0];
426             #$self->log( 'dbg', "nothing to do after connect");
427             },
428             'chatline' => sub {
429 0 0   0     my $self = shift if ref $_[0];
430 0           for (@_) {
431 0 0 0       if ( $self->{'min_chat_delay'} and ( time - $self->{'last_chat_time'} < $self->{'min_chat_delay'} ) ) {
432 0           $self->log( 'dbg', 'sleep', $self->{'min_chat_delay'} - time + $self->{'last_chat_time'} );
433 0           $self->wait_sleep( $self->{'min_chat_delay'} - time + $self->{'last_chat_time'} );
434             }
435 0           $self->{'last_chat_time'} = time;
436 0           $self->log(
437             'dcdmp',
438             "($self->{'number'}) we send [",
439             "<$self->{'Nick'}> $_|",
440             "]:", $self->send("<$self->{'Nick'}> $_|"), $!
441             );
442             }
443             },
444             'To' => sub {
445 0 0   0     my $self = shift if ref $_[0];
446 0           my $to = shift;
447 0           $self->sendcmd( 'To:', $to, "From: $self->{'Nick'} \$<$self->{'Nick'}> $_" ) for (@_);
448             },
449             'Key' => sub {
450 0 0   0     my $self = shift if ref $_[0];
451 0           $self->sendcmd( 'Key', $_[0] );
452             },
453             'ValidateNick' => sub {
454 0 0   0     my $self = shift if ref $_[0];
455 0           $self->sendcmd( 'ValidateNick', $self->{'Nick'} );
456             },
457             'Version' => sub {
458 0 0   0     my $self = shift if ref $_[0];
459 0           $self->sendcmd( 'Version', $self->{'Version'} );
460             },
461             'MyINFO' => sub {
462 0 0   0     my $self = shift if ref $_[0];
463 0           $self->sendcmd( 'MyINFO', '$ALL', $self->myinfo() );
464             },
465             'GetNickList' => sub {
466 0     0     $self->sendcmd('GetNickList');
467             },
468             'GetINFO' => sub {
469 0 0   0     my $self = shift if ref $_[0];
470 0 0         @_ = grep { $self->{'NickList'}{$_}{'online'} and !$self->{'NickList'}{$_}{'info'} } keys %{ $self->{'NickList'} }
  0 0          
  0            
471             unless @_;
472 0           local $self->{'sendbuf'} = 1;
473 0           $self->sendcmd( 'GetINFO', $_, $self->{'Nick'} ) for @_;
474 0           $self->sendcmd();
475             },
476             'BotINFO' => sub {
477 0 0   0     my $self = shift if ref $_[0];
478 0           $self->sendcmd( 'BotINFO', $self->{botinfo} );
479             },
480             'ConnectToMe' => sub {
481 0 0   0     my $self = shift if ref $_[0];
482 0 0 0       $self->log( 'dcdbg', "cannot ConnectToMe from passive mode" ), return
483             if $self->{'M'} eq 'P' and !$self->{'allow_passive_ConnectToMe'};
484 0 0         $self->log( 'err', "please define myip" ), return unless $self->{'myip'};
485 0           $self->sendcmd( 'ConnectToMe', $_[0], "$self->{'myip'}:$self->{'myport'}" );
486             },
487             'RevConnectToMe' => sub {
488 0 0   0     my $self = shift if ref $_[0];
489 0           $self->log( "send", ( 'RevConnectToMe', $self->{'Nick'}, $_[0] ), ref $_[0] );
490 0           $self->sendcmd( 'RevConnectToMe', $self->{'Nick'}, $_[0] );
491             },
492             'MyPass' => sub {
493 0 0   0     my $self = shift if ref $_[0];
494 0   0       my $pass = ( $_[0] or $self->{'Pass'} );
495 0 0         $self->sendcmd( 'MyPass', $pass ) if $pass;
496             },
497             'Supports' => sub {
498 0 0   0     my $self = shift if ref $_[0];
499 0   0       $self->sendcmd( 'Supports', $self->supports() || return );
500             },
501             'Quit' => sub {
502 0 0   0     my $self = shift if ref $_[0];
503 0           $self->sendcmd( 'Quit', $self->{'Nick'} );
504 0           $self->disconnect();
505             },
506             'SR' => sub {
507 0 0   0     my $self = shift if ref $_[0];
508 0           $self->sendcmd( 'SR', @_ );
509             },
510             'Search' => sub {
511 0 0   0     my $self = shift if ref $_[0];
512             #$self->log('devsearch', "mode=[$self->{'M'}]");
513 0 0         $self->sendcmd( 'Search', ( $self->{'M'} eq 'P' ? "Hub:$self->{'Nick'}" : "$self->{'myip'}:$self->{'myport_udp'}" ),
514             join '?', @_ );
515             },
516             'search_nmdc' => sub {
517 0 0   0     my $self = shift if ref $_[0];
518 0           local @_ = @_;
519 0           $_[0] =~ tr/ /$/;
520 0           @_ = ( ( 'F', 'T', '0', undef )[ 0 .. 3 - $#_ ], reverse @_ );
521 0 0 0       $_[3] ||= ( $_[4] =~ s/^(TTH:)?([A-Z0-9]{39})$/TTH:$2/ ? '9' : '1' ) unless defined $_[3];
    0          
522             #
523             #$self->cmd( 'search_buffer', 'F', 'T', '0', '1', @_ );
524 0           $self->search_buffer(@_);
525             },
526             'search_tth' => sub {
527 0 0   0     my $self = shift if ref $_[0];
528 0           $self->{'search_last_string'} = undef;
529 0           $self->search_nmdc(@_);
530             },
531             'search_string' => sub {
532 0 0   0     my $self = shift if ref $_[0];
533             #my $string = $_[0];
534 0           $self->{'search_last_string'} = $_[0]; #$string;
535             #$string =~ tr/ /$/;
536 0           $self->search_nmdc(@_);
537             },
538             'search_send' => sub {
539 0 0   0     my $self = shift if ref $_[0];
540             #$self->log( 'devsearchsend', "$self->{'M'} ne 'P' and $self->{'myip'} and $self->{'myport_udp'}" );
541 0 0         $self->sendcmd(
542             'Search', (
543             ( $self->{'M'} ne 'P' and $self->{'myip'} and $self->{'myport_udp'} )
544             ? "$self->{'myip'}:$self->{'myport_udp'}"
545             : 'Hub:' . $self->{'Nick'}
546             ),
547             join '?',
548 0 0 0       @{ $_[0] || $self->{'search_last'} }
549             );
550             },
551             #
552             'stat_hub' => sub {
553 0 0   0     my $self = shift if ref $_[0];
554 0           local %_;
555             #for my $w qw(SS) {
556             #++$_{UC},
557 0 0         local @_ = grep { length $_ and $_ ne $self->{'Nick'} } keys %{ $self->{'NickList'} };
  0            
  0            
558 0           $_{SS} += $self->{'NickList'}{$_}{'sharesize'} for @_;
559             #}
560 0           $_{UC} = @_;
561 0           return \%_;
562             },
563             #};
564 0           );
565 0   0       $self->{'cmd'}{$_} ||= $_{$_} for keys %_;
566             #$self->log( 'dev', "0making listeners [$self->{'M'}]" );
567 0 0 0       if ( $self->{'M'} eq 'A' or !$self->{'M'} ) {
568             #$self->log( 'dev', "making listeners: tcp, class=", $self->{'incomingclass'} );
569 0           $self->{'clients'}{'listener_tcp'} = $self->{'incomingclass'}->new(
570             #%$self, $self->clear(),
571             #'want' => \%{ $self->{'want'} },
572             #'NickList' => \%{ $self->{'NickList'} },
573             #'IpList' => \%{ $self->{'IpList'} },
574             #'PortList' => \%{ $self->{'PortList'} },
575             #'handler' => \%{ $self->{'handler'} },
576             #'share_tth' => $self->{'share_tth'},
577             'myport' => $self->{'myport'},
578             'auto_listen' => 1,
579             'parent' => $self,
580             );
581 0           $self->{'myport'} = $self->{'myport_tcp'} = $self->{'clients'}{'listener_tcp'}{'myport'};
582 0 0         $self->log( 'err', "cant listen tcp (file transfers)" ) unless $self->{'myport_tcp'};
583             #$self->log( 'dev', "making listeners: udp" );
584             $self->{'clients'}{'listener_udp'} = $self->{'incomingclass'}->new(
585             #%$self, $self->clear(),
586             'parent' => $self, 'Proto' => 'udp', 'myport' => $self->{myport_udp},
587             #? 'want' => \%{ $self->{'want'} },
588             #? 'NickList' => \%{ $self->{'NickList'} },
589             #? 'IpList' => \%{ $self->{'IpList'} },
590             #? 'PortList' => \%{ $self->{'PortList'} },
591             #'handler' => \%{ $self->{'handler'} },
592             #'handler' => $self->{'handler'} ,
593             #$self->{'clients'}{''} = $self->{'incomingclass'}->new( %$self, $self->clear(),
594             #'LocalPort'=>$self->{'myport'},
595             #'debug'=>1,
596             #'nonblocking' => 0,
597             'parse' => {
598             'SR' => $self->{'parse'}{'SR'},
599             'PSR' => sub { #U
600 0 0   0     my $self = shift if ref $_[0];
601             #my $self = ref $_[0] ? shift() : $self;
602 0 0         $self->log( 'dev', "PSR", @_ ) if $self;
603             },
604             'UPSR' => sub { # TODO
605 0 0   0     my $self = shift if ref $_[0];
606             #my $self = ref $_[0] ? shift() : $self;
607             #!$self->log( 'dev', "UPSR", 'udp' ) if $self;
608 0 0         for ( split /\n+/, $_[0] ) { return $self->parser($_) if /^\$SR/; }
  0            
609             #$self->log( 'dev', "UPSR", @_ ) if $self;
610             },
611             #2008/12/14-13:30:50 [3] rcv: welcome UPSR FQ2DNFEXG72IK6IXALNSMBAGJ5JAYOQXJGCUZ4A NIsss2911 HI81.9.63.68:4111 U40 TRZ34KN23JX2BQC2USOTJLGZNEWGDFB327RRU3VUQ PC4 PI0,64,92,94,100,128,132,135 RI64,65,66,67,68,68,69,70,71,72
612             #UPSR CDARCZ6URO4RAZKK6NDFTVYUQNLMFHS6YAR3RKQ NIAspid HI81.9.63.68:411 U40 TRQ6SHQECTUXWJG5ZHG3L322N5B2IV7YN2FG4YXFI PC2 PI15,17,20,128 RI128,129,130,131
613             #$SR [Predator]Wolf DC++\Btyan Adams - Please Forgive Me.mp314217310 18/20TTH:G7DXSTGPHTXSD2ZZFQEUBWI7PORILSKD4EENOII (81.9.63.68:4111)
614             #2008/12/14-13:30:50 welcome UPSR FQ2DNFEXG72IK6IXALNSMBAGJ5JAYOQXJGCUZ4A NIsss2911 HI81.9.63.68:4111 U40 TRZ34KN23JX2BQC2USOTJLGZNEWGDFB327RRU3VUQ PC4 PI0,64,92,94,100,128,132,135 RI64,65,66,67,68,68,69,70,71,72
615             #UPSR CDARCZ6URO4RAZKK6NDFTVYUQNLMFHS6YAR3RKQ NIAspid HI81.9.63.68:411 U40 TRQ6SHQECTUXWJG5ZHG3L322N5B2IV7YN2FG4YXFI PC2 PI15,17,20,128 RI128,129,130,131
616             #$SR [Predator]Wolf DC++\Btyan Adams - Please Forgive Me.mp314217310 18/20TTH:G7DXSTGPHTXSD2ZZFQEUBWI7PORILSKD4EENOII (81.9.63.68:4111)
617             },
618 0           'auto_listen' => 1,
619             'parent' => $self,
620             );
621 0           $self->{'myport_udp'} = $self->{'clients'}{'listener_udp'}{'myport'};
622 0 0         $self->log( 'err', "cant listen udp (search repiles)" ) unless $self->{'myport_udp'};
623             }
624              
625             =z
626             $self->log( 'dev', "making listeners: http" );
627             $self->{'clients'}{'listener_http'} = Net::DirectConnect::http->new(
628             %$self, $self->clear(),
629             #'want' => \%{ $self->{'want'} },
630             #'NickList' => \%{ $self->{'NickList'} },
631             #'IpList' => \%{ $self->{'IpList'} },
632             ## 'PortList' => \%{ $self->{'PortList'} },
633             'handler' => \%{ $self->{'handler'} },
634             #$self->{'clients'}{''} = $self->{'incomingclass'}->new( %$self, $self->clear(),
635             #'LocalPort'=>$self->{'myport'},
636             #'debug'=>1,
637             'auto_listen' => 1,
638             );
639             $self->{'myport_http'} = $self->{'clients'}{'listener_http'}{'myport'};
640             $self->log( 'err', "cant listen http" )
641             unless $self->{'myport_http'};
642             =cut
643              
644 0     0     $self->{'handler_int'}{'disconnect_bef'} = sub {
645             #delete $self->{'sid'};
646             #$self->log( 'dev', 'disconnect int' ) if $self and $self->{'log'};
647 0           };
648             }
649             1;