line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POE::Filter::IRC::Compat; |
2
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:HINRIK'; |
3
|
|
|
|
|
|
|
$POE::Filter::IRC::Compat::VERSION = '6.92'; |
4
|
80
|
|
|
80
|
|
80424
|
use strict; |
|
80
|
|
|
|
|
468
|
|
|
80
|
|
|
|
|
2854
|
|
5
|
80
|
|
|
80
|
|
457
|
use warnings FATAL => 'all'; |
|
80
|
|
|
|
|
170
|
|
|
80
|
|
|
|
|
3194
|
|
6
|
80
|
|
|
80
|
|
467
|
use Carp; |
|
80
|
|
|
|
|
215
|
|
|
80
|
|
|
|
|
5256
|
|
7
|
80
|
|
|
80
|
|
585
|
use POE::Filter::IRCD; |
|
80
|
|
|
|
|
173
|
|
|
80
|
|
|
|
|
2603
|
|
8
|
80
|
|
|
80
|
|
556
|
use File::Basename qw(fileparse); |
|
80
|
|
|
|
|
419
|
|
|
80
|
|
|
|
|
9306
|
|
9
|
80
|
|
|
80
|
|
602
|
use base qw(POE::Filter); |
|
80
|
|
|
|
|
194
|
|
|
80
|
|
|
|
|
287689
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
my %irc_cmds = ( |
12
|
|
|
|
|
|
|
qr/^\d{3}$/ => sub { |
13
|
|
|
|
|
|
|
my ($self, $event, $line) = @_; |
14
|
|
|
|
|
|
|
$event->{args}->[0] = _decolon( $line->{prefix} ); |
15
|
|
|
|
|
|
|
shift @{ $line->{params} }; |
16
|
|
|
|
|
|
|
if ( $line->{params}->[0] && $line->{params}->[0] =~ /\x20/ ) { |
17
|
|
|
|
|
|
|
$event->{args}->[1] = $line->{params}->[0]; |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
else { |
20
|
|
|
|
|
|
|
$event->{args}->[1] = join(' ', ( map { /\x20/ ? ":$_" : $_ } @{ $line->{params} } ) ); |
21
|
|
|
|
|
|
|
} |
22
|
|
|
|
|
|
|
$event->{args}->[2] = $line->{params}; |
23
|
|
|
|
|
|
|
}, |
24
|
|
|
|
|
|
|
qr/^cap$/ => sub { |
25
|
|
|
|
|
|
|
my ($self, $event, $line) = @_; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
for (my $i = 0; ; $i++) { |
28
|
|
|
|
|
|
|
last if !defined $line->{params}[$i+1]; |
29
|
|
|
|
|
|
|
$event->{args}[$i] = $line->{params}[$i+1]; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
}, |
32
|
|
|
|
|
|
|
qr/^notice$/ => sub { |
33
|
|
|
|
|
|
|
my ($self, $event, $line) = @_; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
if (defined $line->{prefix} && $line->{prefix} =~ /!/) { |
36
|
|
|
|
|
|
|
$event->{args} = [ |
37
|
|
|
|
|
|
|
_decolon( $line->{prefix} ), |
38
|
|
|
|
|
|
|
[split /,/, $line->{params}->[0]], |
39
|
|
|
|
|
|
|
($self->{identifymsg} |
40
|
|
|
|
|
|
|
? _split_idmsg($line->{params}->[1]) |
41
|
|
|
|
|
|
|
: $line->{params}->[1] |
42
|
|
|
|
|
|
|
), |
43
|
|
|
|
|
|
|
]; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
else { |
46
|
|
|
|
|
|
|
$event->{name} = 'snotice'; |
47
|
|
|
|
|
|
|
$event->{args} = [ |
48
|
|
|
|
|
|
|
$line->{params}->[1], |
49
|
|
|
|
|
|
|
$line->{params}->[0], |
50
|
|
|
|
|
|
|
(defined $line->{prefix} ? _decolon($line->{prefix}) : ()), |
51
|
|
|
|
|
|
|
]; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
}, |
54
|
|
|
|
|
|
|
qr/^privmsg$/ => sub { |
55
|
|
|
|
|
|
|
my ($self, $event, $line) = @_; |
56
|
|
|
|
|
|
|
if ( grep { index( $line->{params}->[0], $_ ) >= 0 } @{ $self->{chantypes} } ) { |
57
|
|
|
|
|
|
|
$event->{args} = [ |
58
|
|
|
|
|
|
|
_decolon( $line->{prefix} ), |
59
|
|
|
|
|
|
|
[split /,/, $line->{params}->[0]], |
60
|
|
|
|
|
|
|
($self->{identifymsg} |
61
|
|
|
|
|
|
|
? _split_idmsg($line->{params}->[1]) |
62
|
|
|
|
|
|
|
: $line->{params}->[1] |
63
|
|
|
|
|
|
|
), |
64
|
|
|
|
|
|
|
]; |
65
|
|
|
|
|
|
|
$event->{name} = 'public'; |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
else { |
68
|
|
|
|
|
|
|
$event->{args} = [ |
69
|
|
|
|
|
|
|
_decolon( $line->{prefix} ), |
70
|
|
|
|
|
|
|
[split /,/, $line->{params}->[0]], |
71
|
|
|
|
|
|
|
($self->{identifymsg} |
72
|
|
|
|
|
|
|
? _split_idmsg($line->{params}->[1]) |
73
|
|
|
|
|
|
|
: $line->{params}->[1] |
74
|
|
|
|
|
|
|
), |
75
|
|
|
|
|
|
|
]; |
76
|
|
|
|
|
|
|
$event->{name} = 'msg'; |
77
|
|
|
|
|
|
|
} |
78
|
|
|
|
|
|
|
}, |
79
|
|
|
|
|
|
|
qr/^invite$/ => sub { |
80
|
|
|
|
|
|
|
my ($self, $event, $line) = @_; |
81
|
|
|
|
|
|
|
shift( @{ $line->{params} } ); |
82
|
|
|
|
|
|
|
unshift( @{ $line->{params} }, _decolon( $line->{prefix} || '' ) ) if $line->{prefix}; |
83
|
|
|
|
|
|
|
$event->{args} = $line->{params}; |
84
|
|
|
|
|
|
|
}, |
85
|
|
|
|
|
|
|
); |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# the magic cookie jar |
88
|
|
|
|
|
|
|
my %dcc_types = ( |
89
|
|
|
|
|
|
|
qr/^(?:CHAT|SEND)$/ => sub { |
90
|
|
|
|
|
|
|
my ($nick, $type, $args) = @_; |
91
|
|
|
|
|
|
|
my ($file, $addr, $port, $size); |
92
|
|
|
|
|
|
|
return if !(($file, $addr, $port, $size) = $args =~ /^(".+"|[^ ]+) +(\d+) +(\d+)(?: +(\d+))?/); |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
if ($file =~ s/^"//) { |
95
|
|
|
|
|
|
|
$file =~ s/"$//; |
96
|
|
|
|
|
|
|
$file =~ s/\\"/"/g; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
$file = fileparse($file); |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
return ( |
101
|
|
|
|
|
|
|
$port, |
102
|
|
|
|
|
|
|
{ |
103
|
|
|
|
|
|
|
nick => $nick, |
104
|
|
|
|
|
|
|
type => $type, |
105
|
|
|
|
|
|
|
file => $file, |
106
|
|
|
|
|
|
|
size => $size, |
107
|
|
|
|
|
|
|
addr => $addr, |
108
|
|
|
|
|
|
|
port => $port, |
109
|
|
|
|
|
|
|
}, |
110
|
|
|
|
|
|
|
$file, |
111
|
|
|
|
|
|
|
$size, |
112
|
|
|
|
|
|
|
$addr, |
113
|
|
|
|
|
|
|
); |
114
|
|
|
|
|
|
|
}, |
115
|
|
|
|
|
|
|
qr/^(?:ACCEPT|RESUME)$/ => sub { |
116
|
|
|
|
|
|
|
my ($nick, $type, $args) = @_; |
117
|
|
|
|
|
|
|
my ($file, $port, $position); |
118
|
|
|
|
|
|
|
return if !(($file, $port, $position) = $args =~ /^(".+"|[^ ]+) +(\d+) +(\d+)/); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
$file =~ s/^"|"$//g; |
121
|
|
|
|
|
|
|
$file = fileparse($file); |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
return ( |
124
|
|
|
|
|
|
|
$port, |
125
|
|
|
|
|
|
|
{ |
126
|
|
|
|
|
|
|
nick => $nick, |
127
|
|
|
|
|
|
|
type => $type, |
128
|
|
|
|
|
|
|
file => $file, |
129
|
|
|
|
|
|
|
size => $position, |
130
|
|
|
|
|
|
|
port => $port, |
131
|
|
|
|
|
|
|
}, |
132
|
|
|
|
|
|
|
$file, |
133
|
|
|
|
|
|
|
$position, |
134
|
|
|
|
|
|
|
); |
135
|
|
|
|
|
|
|
}, |
136
|
|
|
|
|
|
|
); |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub new { |
139
|
124
|
|
|
124
|
1
|
781
|
my ($package, %self) = @_; |
140
|
|
|
|
|
|
|
|
141
|
124
|
|
|
|
|
855
|
$self{lc $_} = delete $self{$_} for keys %self; |
142
|
124
|
|
|
|
|
451
|
$self{BUFFER} = [ ]; |
143
|
124
|
|
|
|
|
518
|
$self{_ircd} = POE::Filter::IRCD->new(); |
144
|
124
|
50
|
|
|
|
2840
|
$self{chantypes} = [ '#', '&' ] if ref $self{chantypes} ne 'ARRAY'; |
145
|
|
|
|
|
|
|
|
146
|
124
|
|
|
|
|
736
|
return bless \%self, $package; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub clone { |
150
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
151
|
0
|
|
|
|
|
0
|
my $nself = { }; |
152
|
0
|
|
|
|
|
0
|
$nself->{$_} = $self->{$_} for keys %{ $self }; |
|
0
|
|
|
|
|
0
|
|
153
|
0
|
|
|
|
|
0
|
$nself->{BUFFER} = [ ]; |
154
|
0
|
|
|
|
|
0
|
return bless $nself, ref $self; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
# Set/clear the 'debug' flag. |
158
|
|
|
|
|
|
|
sub debug { |
159
|
0
|
|
|
0
|
1
|
0
|
my ($self, $flag) = @_; |
160
|
0
|
0
|
|
|
|
0
|
if (defined $flag) { |
161
|
0
|
|
|
|
|
0
|
$self->{debug} = $flag; |
162
|
0
|
|
|
|
|
0
|
$self->{_ircd}->debug($flag); |
163
|
|
|
|
|
|
|
} |
164
|
0
|
|
|
|
|
0
|
return $self->{debug}; |
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
sub chantypes { |
168
|
180
|
|
|
180
|
1
|
520
|
my ($self, $ref) = @_; |
169
|
180
|
50
|
33
|
|
|
950
|
return if ref $ref ne 'ARRAY' || !@{ $ref }; |
|
180
|
|
|
|
|
842
|
|
170
|
180
|
|
|
|
|
566
|
$self->{chantypes} = $ref; |
171
|
180
|
|
|
|
|
470
|
return 1; |
172
|
|
|
|
|
|
|
} |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
sub identifymsg { |
175
|
91
|
|
|
91
|
1
|
259
|
my ($self, $switch) = @_; |
176
|
91
|
|
|
|
|
254
|
$self->{identifymsg} = $switch; |
177
|
91
|
|
|
|
|
226
|
return; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
sub _split_idmsg { |
181
|
0
|
|
|
0
|
|
0
|
my ($line) = @_; |
182
|
0
|
|
|
|
|
0
|
my ($identified, $msg) = split //, $line, 2; |
183
|
0
|
0
|
|
|
|
0
|
$identified = $identified eq '+' ? 1 : 0; |
184
|
0
|
|
|
|
|
0
|
return $msg, $identified; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
sub get_one { |
188
|
3317
|
|
|
3317
|
1
|
46167
|
my ($self) = @_; |
189
|
3317
|
100
|
|
|
|
5197
|
my $line = shift @{ $self->{BUFFER} } or return [ ]; |
|
3317
|
|
|
|
|
10636
|
|
190
|
|
|
|
|
|
|
|
191
|
2611
|
50
|
33
|
|
|
18365
|
if (ref $line ne 'HASH' || !$line->{command} || !$line->{params}) { |
|
|
|
33
|
|
|
|
|
192
|
0
|
0
|
|
|
|
0
|
warn "Received line '$line' that is not IRC protocol\n" if $self->{debug}; |
193
|
0
|
|
|
|
|
0
|
return [ ]; |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
|
196
|
2611
|
100
|
100
|
|
|
7664
|
if ($line->{command} =~ /^PRIVMSG|NOTICE$/ && $line->{params}->[1] =~ tr/\001//) { |
197
|
34
|
|
|
|
|
167
|
return $self->_get_ctcp($line); |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
my $event = { |
201
|
|
|
|
|
|
|
name => lc $line->{command}, |
202
|
|
|
|
|
|
|
raw_line => $line->{raw_line}, |
203
|
2577
|
|
|
|
|
9537
|
}; |
204
|
|
|
|
|
|
|
|
205
|
2577
|
|
|
|
|
9996
|
for my $cmd (keys %irc_cmds) { |
206
|
7659
|
100
|
|
|
|
91536
|
if ($event->{name} =~ $cmd) { |
207
|
2130
|
|
|
|
|
7950
|
$irc_cmds{$cmd}->($self, $event, $line); |
208
|
2130
|
|
|
|
|
10852
|
return [ $event ]; |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# default |
213
|
447
|
100
|
50
|
|
|
1830
|
unshift( @{ $line->{params} }, _decolon( $line->{prefix} || '' ) ) if $line->{prefix}; |
|
356
|
|
|
|
|
1841
|
|
214
|
447
|
|
|
|
|
1179
|
$event->{args} = $line->{params}; |
215
|
447
|
|
|
|
|
2025
|
return [ $event ]; |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub get_one_start { |
219
|
2611
|
|
|
2611
|
1
|
8907263
|
my ($self, $lines) = @_; |
220
|
2611
|
|
|
|
|
4530
|
push @{ $self->{BUFFER} }, @$lines; |
|
2611
|
|
|
|
|
6135
|
|
221
|
2611
|
|
|
|
|
5626
|
return; |
222
|
|
|
|
|
|
|
} |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
sub put { |
225
|
27
|
|
|
27
|
1
|
92
|
my ($self, $lineref) = @_; |
226
|
27
|
|
|
|
|
62
|
my $quoted = [ ]; |
227
|
27
|
|
|
|
|
117
|
push @$quoted, _ctcp_quote($_) for @$lineref; |
228
|
27
|
|
|
|
|
112
|
return $quoted; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# Properly CTCP-quotes a message. Whoop. |
232
|
|
|
|
|
|
|
sub _ctcp_quote { |
233
|
27
|
|
|
27
|
|
58
|
my ($line) = @_; |
234
|
|
|
|
|
|
|
|
235
|
27
|
|
|
|
|
175
|
$line = _low_quote( $line ); |
236
|
|
|
|
|
|
|
#$line =~ s/\\/\\\\/g; |
237
|
27
|
|
|
|
|
84
|
$line =~ s/\001/\\a/g; |
238
|
|
|
|
|
|
|
|
239
|
27
|
|
|
|
|
138
|
return "\001$line\001"; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
# Splits a message into CTCP and text chunks. This is gross. Most of |
243
|
|
|
|
|
|
|
# this is also stolen from Net::IRC, but I (fimm) wrote that too, so it's |
244
|
|
|
|
|
|
|
# used with permission. ;-) |
245
|
|
|
|
|
|
|
sub _ctcp_dequote { |
246
|
34
|
|
|
34
|
|
84
|
my ($msg) = @_; |
247
|
34
|
|
|
|
|
68
|
my (@chunks, $ctcp, $text); |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
# CHUNG! CHUNG! CHUNG! |
250
|
|
|
|
|
|
|
|
251
|
34
|
50
|
|
|
|
116
|
if (!defined $msg) { |
252
|
0
|
|
|
|
|
0
|
croak 'Not enough arguments to POE::Filter::IRC::Compat::_ctcp_dequote'; |
253
|
|
|
|
|
|
|
} |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
# Strip out any low-level quoting in the text. |
256
|
34
|
|
|
|
|
130
|
$msg = _low_dequote( $msg ); |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
# Filter misplaced \001s before processing... (Thanks, tchrist!) |
259
|
34
|
100
|
|
|
|
161
|
substr($msg, rindex($msg, "\001"), 1, '\\a') |
260
|
|
|
|
|
|
|
if ($msg =~ tr/\001//) % 2 != 0; |
261
|
|
|
|
|
|
|
|
262
|
34
|
100
|
|
|
|
126
|
return if $msg !~ tr/\001//; |
263
|
|
|
|
|
|
|
|
264
|
33
|
|
|
|
|
147
|
@chunks = split /\001/, $msg; |
265
|
33
|
50
|
|
|
|
128
|
shift @chunks if !length $chunks[0]; # FIXME: Is this safe? |
266
|
|
|
|
|
|
|
|
267
|
33
|
|
|
|
|
136
|
for (@chunks) { |
268
|
|
|
|
|
|
|
# Dequote unnecessarily quoted chars, and convert escaped \'s and ^A's. |
269
|
35
|
|
|
|
|
108
|
s/\\([^\\a])/$1/g; |
270
|
35
|
|
|
|
|
78
|
s/\\\\/\\/g; |
271
|
35
|
|
|
|
|
104
|
s/\\a/\001/g; |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# If the line begins with a control-A, the first chunk is a CTCP |
275
|
|
|
|
|
|
|
# message. Otherwise, it starts with text and alternates with CTCP |
276
|
|
|
|
|
|
|
# messages. Really stupid protocol. |
277
|
33
|
50
|
|
|
|
193
|
if ($msg =~ /^\001/) { |
278
|
33
|
|
|
|
|
102
|
push @$ctcp, shift @chunks; |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
33
|
|
|
|
|
112
|
while (@chunks) { |
282
|
1
|
|
|
|
|
3
|
push @$text, shift @chunks; |
283
|
1
|
50
|
|
|
|
3
|
push @$ctcp, shift @chunks if @chunks; |
284
|
|
|
|
|
|
|
} |
285
|
|
|
|
|
|
|
|
286
|
33
|
|
|
|
|
110
|
return ($ctcp, $text); |
287
|
|
|
|
|
|
|
} |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
sub _decolon { |
290
|
2481
|
|
|
2481
|
|
5032
|
my ($line) = @_; |
291
|
|
|
|
|
|
|
|
292
|
2481
|
|
|
|
|
5047
|
$line =~ s/^://; |
293
|
2481
|
|
|
|
|
8405
|
return $line; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
## no critic (Subroutines::ProhibitExcessComplexity) |
297
|
|
|
|
|
|
|
sub _get_ctcp { |
298
|
34
|
|
|
34
|
|
97
|
my ($self, $line) = @_; |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
# Is this a CTCP request or reply? |
301
|
34
|
100
|
|
|
|
279
|
my $ctcp_type = $line->{command} eq 'PRIVMSG' ? 'ctcp' : 'ctcpreply'; |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
# CAPAP IDENTIFY-MSG is only applied to ACTIONs |
304
|
34
|
|
|
|
|
131
|
my ($msg, $identified) = ($line->{params}->[1], undef); |
305
|
34
|
50
|
33
|
|
|
159
|
($msg, $identified) = _split_idmsg($msg) if $self->{identifymsg} && $msg =~ /^.ACTION/; |
306
|
|
|
|
|
|
|
|
307
|
34
|
|
|
|
|
78
|
my $events = [ ]; |
308
|
34
|
|
|
|
|
150
|
my ($ctcp, $text) = _ctcp_dequote($msg); |
309
|
|
|
|
|
|
|
|
310
|
34
|
100
|
|
|
|
111
|
if (!defined $ctcp) { |
311
|
1
|
50
|
|
|
|
6
|
warn "Received malformed CTCP message: $msg\n" if $self->{debug}; |
312
|
1
|
|
|
|
|
6
|
return $events; |
313
|
|
|
|
|
|
|
} |
314
|
|
|
|
|
|
|
|
315
|
33
|
100
|
|
|
|
190
|
my $nick = defined $line->{prefix} ? (split /!/, $line->{prefix})[0] : undef; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
# We only process the first CTCP. The only people who send multiple ones |
318
|
|
|
|
|
|
|
# are those who are trying to flood our outgoing queue anyway (e.g. by |
319
|
|
|
|
|
|
|
# having us reply to 20 VERSION requests at a time). |
320
|
33
|
|
|
|
|
94
|
my ($name, $args); |
321
|
33
|
|
|
|
|
102
|
CTCP: for my $string ($ctcp->[0]) { |
322
|
33
|
50
|
|
|
|
273
|
if (!(($name, $args) = $string =~ /^(\w+)(?: +(.*))?/)) { |
323
|
|
|
|
|
|
|
defined $nick |
324
|
0
|
0
|
|
|
|
0
|
? do { warn "Received malformed CTCP message from $nick: $string\n" if $self->{debug} } |
325
|
0
|
0
|
|
|
|
0
|
: do { warn "Trying to send malformed CTCP message: $string\n" if $self->{debug} } |
|
0
|
0
|
|
|
|
0
|
|
326
|
|
|
|
|
|
|
; |
327
|
0
|
|
|
|
|
0
|
last CTCP; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
33
|
100
|
|
|
|
136
|
if (lc $name eq 'dcc') { |
331
|
11
|
|
|
|
|
26
|
my ($dcc_type, $rest); |
332
|
|
|
|
|
|
|
|
333
|
11
|
50
|
|
|
|
98
|
if (!(($dcc_type, $rest) = $args =~ /^(\w+) +(.+)/)) { |
334
|
|
|
|
|
|
|
defined $nick |
335
|
0
|
0
|
|
|
|
0
|
? do { warn "Received malformed DCC request from $nick: $args\n" if $self->{debug} } |
336
|
0
|
0
|
|
|
|
0
|
: do { warn "Trying to send malformed DCC request: $args\n" if $self->{debug} } |
|
0
|
0
|
|
|
|
0
|
|
337
|
|
|
|
|
|
|
; |
338
|
0
|
|
|
|
|
0
|
last CTCP; |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
} |
341
|
11
|
|
|
|
|
43
|
$dcc_type = uc $dcc_type; |
342
|
|
|
|
|
|
|
|
343
|
11
|
|
|
|
|
103
|
my ($handler) = grep { $dcc_type =~ /$_/ } keys %dcc_types; |
|
22
|
|
|
|
|
854
|
|
344
|
11
|
50
|
|
|
|
59
|
if (!$handler) { |
345
|
0
|
0
|
|
|
|
0
|
warn "Unhandled DCC $dcc_type request: $rest\n" if $self->{debug}; |
346
|
0
|
|
|
|
|
0
|
last CTCP; |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
|
349
|
11
|
|
|
|
|
82
|
my @dcc_args = $dcc_types{$handler}->($nick, $dcc_type, $rest); |
350
|
11
|
50
|
|
|
|
76
|
if (!@dcc_args) { |
351
|
|
|
|
|
|
|
defined $nick |
352
|
0
|
0
|
|
|
|
0
|
? do { warn "Received malformed DCC $dcc_type request from $nick: $rest\n" if $self->{debug} } |
353
|
0
|
0
|
|
|
|
0
|
: do { warn "Trying to send malformed DCC $dcc_type request: $rest\n" if $self->{debug} } |
|
0
|
0
|
|
|
|
0
|
|
354
|
|
|
|
|
|
|
; |
355
|
0
|
|
|
|
|
0
|
last CTCP; |
356
|
|
|
|
|
|
|
} |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
push @$events, { |
359
|
|
|
|
|
|
|
name => 'dcc_request', |
360
|
|
|
|
|
|
|
args => [ |
361
|
|
|
|
|
|
|
$line->{prefix}, |
362
|
|
|
|
|
|
|
$dcc_type, |
363
|
|
|
|
|
|
|
@dcc_args, |
364
|
|
|
|
|
|
|
], |
365
|
|
|
|
|
|
|
raw_line => $line->{raw_line}, |
366
|
11
|
|
|
|
|
145
|
}; |
367
|
|
|
|
|
|
|
} |
368
|
|
|
|
|
|
|
else { |
369
|
|
|
|
|
|
|
push @$events, { |
370
|
|
|
|
|
|
|
name => $ctcp_type . '_' . lc $name, |
371
|
|
|
|
|
|
|
args => [ |
372
|
|
|
|
|
|
|
$line->{prefix}, |
373
|
|
|
|
|
|
|
[split /,/, $line->{params}->[0]], |
374
|
|
|
|
|
|
|
(defined $args ? $args : ''), |
375
|
|
|
|
|
|
|
(defined $identified ? $identified : () ), |
376
|
|
|
|
|
|
|
], |
377
|
|
|
|
|
|
|
raw_line => $line->{raw_line}, |
378
|
22
|
100
|
|
|
|
248
|
}; |
|
|
50
|
|
|
|
|
|
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
# XXX: I'm not quite sure what this is for, but on FreeNode it adds an |
383
|
|
|
|
|
|
|
# extra bogus event and displays a debug message, so I have disabled it. |
384
|
|
|
|
|
|
|
# FreeNode precedes PRIVMSG and CTCP ACTION messages with '+' or '-'. |
385
|
|
|
|
|
|
|
#if ($text && @$text) { |
386
|
|
|
|
|
|
|
# my $what; |
387
|
|
|
|
|
|
|
# ($what) = $line->{raw_line} =~ /^(:[^ ]+ +\w+ +[^ ]+ +)/ |
388
|
|
|
|
|
|
|
# or warn "What the heck? '".$line->{raw_line}."'\n" if $self->{debug}; |
389
|
|
|
|
|
|
|
# $text = (defined $what ? $what : '') . ':' . join '', @$text; |
390
|
|
|
|
|
|
|
# $text =~ s/\cP/^P/g; |
391
|
|
|
|
|
|
|
# warn "CTCP: $text\n" if $self->{debug}; |
392
|
|
|
|
|
|
|
# push @$events, @{ $self->{_ircd}->get([$text]) }; |
393
|
|
|
|
|
|
|
#} |
394
|
|
|
|
|
|
|
|
395
|
33
|
|
|
|
|
211
|
return $events; |
396
|
|
|
|
|
|
|
} |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# Quotes a string in a low-level, protocol-safe, utterly brain-dead |
399
|
|
|
|
|
|
|
# fashion. Returns the quoted string. |
400
|
|
|
|
|
|
|
sub _low_quote { |
401
|
27
|
|
|
27
|
|
77
|
my ($line) = @_; |
402
|
27
|
|
|
|
|
369
|
my %enquote = ("\012" => 'n', "\015" => 'r', "\0" => '0', "\cP" => "\cP"); |
403
|
|
|
|
|
|
|
|
404
|
27
|
50
|
|
|
|
113
|
if (!defined $line) { |
405
|
0
|
|
|
|
|
0
|
croak 'Not enough arguments to POE::Filter::IRC::Compat->_low_quote'; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
27
|
50
|
|
|
|
141
|
if ($line =~ tr/[\012\015\0\cP]//) { # quote \n, \r, ^P, and \0. |
409
|
0
|
|
|
|
|
0
|
$line =~ s/([\012\015\0\cP])/\cP$enquote{$1}/g; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
27
|
|
|
|
|
104
|
return $line; |
413
|
|
|
|
|
|
|
} |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# Does low-level dequoting on CTCP messages. I hate this protocol. |
416
|
|
|
|
|
|
|
# Yes, I copied this whole section out of Net::IRC. |
417
|
|
|
|
|
|
|
sub _low_dequote { |
418
|
34
|
|
|
34
|
|
81
|
my ($line) = @_; |
419
|
34
|
|
|
|
|
327
|
my %dequote = (n => "\012", r => "\015", 0 => "\0", "\cP" => "\cP"); |
420
|
|
|
|
|
|
|
|
421
|
34
|
50
|
|
|
|
147
|
if (!defined $line) { |
422
|
0
|
|
|
|
|
0
|
croak 'Not enough arguments to POE::Filter::IRC::Compat->_low_dequote'; |
423
|
|
|
|
|
|
|
} |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
# dequote \n, \r, ^P, and \0. |
426
|
|
|
|
|
|
|
# Thanks to Abigail (abigail@foad.org) for this clever bit. |
427
|
34
|
50
|
|
|
|
140
|
if ($line =~ tr/\cP//) { |
428
|
0
|
|
|
|
|
0
|
$line =~ s/\cP([nr0\cP])/$dequote{$1}/g; |
429
|
|
|
|
|
|
|
} |
430
|
|
|
|
|
|
|
|
431
|
34
|
|
|
|
|
127
|
return $line; |
432
|
|
|
|
|
|
|
} |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
1; |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
=encoding utf8 |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
=head1 NAME |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
POE::Filter::IRC::Compat - A filter which converts L |
441
|
|
|
|
|
|
|
output into L events |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head1 SYNOPSIS |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
my $filter = POE::Filter::IRC::Compat->new(); |
446
|
|
|
|
|
|
|
my @events = @{ $filter->get( [ @lines ] ) }; |
447
|
|
|
|
|
|
|
my @msgs = @{ $filter->put( [ @messages ] ) }; |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=head1 DESCRIPTION |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
POE::Filter::IRC::Compat is a L that converts |
452
|
|
|
|
|
|
|
L output into the L |
453
|
|
|
|
|
|
|
compatible event references. Basically a hack, so I could replace |
454
|
|
|
|
|
|
|
L with something that was more |
455
|
|
|
|
|
|
|
generic. |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
Among other things, it converts normal text into thoroughly CTCP-quoted |
458
|
|
|
|
|
|
|
messages, and transmogrifies CTCP-quoted messages into their normal, |
459
|
|
|
|
|
|
|
sane components. Rather what you'd expect a filter to do. |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
A note: the CTCP protocol sucks bollocks. If I ever meet the fellow who |
462
|
|
|
|
|
|
|
came up with it, I'll shave their head and tattoo obscenities on it. |
463
|
|
|
|
|
|
|
Just read the "specification" (F in this distribution) |
464
|
|
|
|
|
|
|
and you'll hopefully see what I mean. Quote this, quote that, quote this |
465
|
|
|
|
|
|
|
again, all in different and weird ways... and who the hell needs to send |
466
|
|
|
|
|
|
|
mixed CTCP and text messages? WTF? It looks like it's practically complexity |
467
|
|
|
|
|
|
|
for complexity's sake -- and don't even get me started on the design of the |
468
|
|
|
|
|
|
|
DCC protocol! Anyhow, enough ranting. Onto the rest of the docs... |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=head1 METHODS |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
=head2 C |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
Returns a POE::Filter::IRC::Compat object. Takes no arguments. |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
=head2 C |
477
|
|
|
|
|
|
|
|
478
|
|
|
|
|
|
|
Makes a copy of the filter, and clears the copy's buffer. |
479
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
=head2 C |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
Takes an arrayref of L hashrefs and produces an arrayref of |
483
|
|
|
|
|
|
|
L compatible event hashrefs. Yay. |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
=head2 C, C |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
These perform a similar function as C but enable the filter to work with |
488
|
|
|
|
|
|
|
L. |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head2 C |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
Takes an array reference of CTCP messages to be properly quoted. This |
493
|
|
|
|
|
|
|
doesn't support CTCPs embedded in normal messages, which is a |
494
|
|
|
|
|
|
|
brain-dead hack in the protocol, so do it yourself if you really need |
495
|
|
|
|
|
|
|
it. Returns an array reference of the quoted lines for sending. |
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
=head2 C |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
Takes an optinal true/false value which enables/disables debugging |
500
|
|
|
|
|
|
|
accordingly. Returns the debug status. |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
=head2 C |
503
|
|
|
|
|
|
|
|
504
|
|
|
|
|
|
|
Takes an arrayref of possible channel prefix indicators. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=head2 C |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
Takes a boolean to turn on/off the support for CAPAB IDENTIFY-MSG. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=head1 AUTHOR |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
Chris 'BinGOs' Williams |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=head1 SEE ALSO |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
L |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
L |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
L |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
=cut |