]> jfr.im git - irc/SurrealServices/srsv.git/blame - branches/erry-devel/SrSv/Insp/Parse.pm
My work on this so far....
[irc/SurrealServices/srsv.git] / branches / erry-devel / SrSv / Insp / Parse.pm
CommitLineData
5975999e 1# This file is part of SurrealServices.
2#
3# SurrealServices is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# SurrealServices is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with SurrealServices; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
17package SrSv::IRCd::Parse;
18
19use strict;
20
21use Exporter 'import';
22# parse_sjoin shouldn't get used anywhere else, as we never produce SJOINs
23# parse_tkl however is used for loopbacks.
24BEGIN { our @EXPORT_OK = qw(parse_line parse_tkl parse_addline) }
25
26# FIXME
27BEGIN { *SJB64 = \&ircd::SJB64; *CLK = \&ircd::CLK; *NICKIP = \&ircd::NICKIP; }
28
29use SrSv::Conf 'main';
30
31use SrSv::Debug;
32use SrSv::IRCd::State qw($ircline $remoteserv create_server get_server_children set_server_state get_server_state %IRCd_capabilities);
33use SrSv::IRCd::Queue qw(queue_size);
34use SrSv::IRCd::IO qw( ircsend ircsendimm);
35use SrSv::IRCd::Send qw (getRevUuid getUuid setRevUuid setUuid);
36use SrSv::Unreal::Modes qw(%opmodes);
37
38# Unreal uses its own modified base64 for everything except NICKIP
39use SrSv::Unreal::Base64 qw(b64toi itob64);
2eef9154 40use SrSv::User '/./';
5975999e 41# Unreal uses unmodified base64 for NICKIP.
42# Consider private implementation,
43# tho MIME's is probably faster
44use MIME::Base64;
2eef9154 45use Data::Dumper;
5975999e 46# FIXME
47use constant {
48 # Wait For
49 WF_NONE => 0,
50 WF_NICK => 1,
51 WF_CHAN => 2,
52 WF_ALL => 3,
53};
54
55use SrSv::Shared qw(@servernum);
56
57our %cmdhash;
58
59sub parse_line($) {
60 my ($in) = @_;
61 if (!$in) {
62 return;
63 }
64 my $cmd;
65
66 if($in =~ /^(?:@|:)(\S+) (\S+)/) {
67 $cmd = $2;
68 }
69 elsif ($in =~ /^(\S+)/) {
70 $cmd = $1;
71 }
72 my $sub = $cmdhash{$cmd};
73 unless (defined($sub)) {
74 print "Bailing out from $ircline:$cmd for lack of cmdhash\n" if DEBUG();
75 return undef();
76 }
77 my ($event, $src, $dst, $wf, @args) = &$sub($in);
78 unless (defined($event)) {
79 print "Bailing out from $ircline:$cmd for lack of event\n" if DEBUG;
80 return undef();
81 }
82 #return unless defined $event;
83
84 my (@recipients, @out);
85 if(defined($dst)) {
86 #$args[$dst] = lc $args[$dst];
87 @recipients = split(/\,/, $args[$dst]);
88 }
89 #if(defined($src)) { $args[$src] = lc $args[$src]; }
90
91 if(@recipients > 1) {
92 foreach my $rcpt (@recipients) {
93 $args[$dst] = $rcpt;
94 push @out, [$event, $src, $dst, $wf, [@args]];
95 }
96 } else {
97 @out = [$event, $src, $dst, $wf, [@args]];
98 }
99
100 return @out;
101}
102#parse_fjoin($server, $channel, $ts, $modes, @nicks, @status)
103sub parse_fjoin ($$$$$$) {
2eef9154 104 my ($server, $channel, $ts, $modes, $idsr, $statusref) = @_;
5975999e 105 my @status = @$statusref;
2eef9154 106 my @ids = @$idsr;
5975999e 107 my $i = 0;
108 my @users;
2eef9154 109 foreach my $id (@ids) {
5975999e 110 my $op = 0;
111 my @ops = split ("",$status[$i]);
112 foreach my $prefix (@ops) {
113 $op |= $opmodes{$prefix};
114 }
2eef9154 115 my $user = {ID => $id, __OP=>$op};
116 get_user_nick ($user);
117 push @users, $user;
5975999e 118 $i++;
119 }
2eef9154 120 return ($server, $channel, $ts, $modes, undef, \@users, undef, undef, undef); #bans etc are got from FMODE..
5975999e 121}
122sub parse_sjoin($$$$) {
123 my ($server, $ts, $cn, $parms) = @_;
124 my (@users, @bans, @excepts, @invex, @blobs, $blobs, $chmodes, $chmodeparms);
125
126 $server = '' unless $server;
127
128 if($parms =~ /^:(.*)/) {
129 $blobs = $1;
130 } else {
131 ($chmodes, $blobs) = split(/ :/, $parms, 2);
132 ($chmodes, $chmodeparms) = split(/ /, $chmodes, 2);
133 }
134 @blobs = split(/ /, $blobs);
135
136 foreach my $x (@blobs) {
137 if($x =~ /^(\&|\"|\')(.*)$/) {
138 my $type;
139 push @bans, $2 if $1 eq '&';
140 push @excepts, $2 if $1 eq '"';
141 push @invex, $2 if $1 eq "\'";
142 } else {
143 $x =~ /^([*~@%+]*)(.*)$/;
144 my ($prefixes, $nick) = ($1, $2);
145 my @prefixes = split(//, $prefixes);
146 my $op = 0;
147 foreach my $prefix (@prefixes) {
148 $op |= $opmodes{q} if ($prefix eq '*');
149 $op |= $opmodes{a} if ($prefix eq '~');
150 $op |= $opmodes{o} if ($prefix eq '@');
151 $op |= $opmodes{h} if ($prefix eq '%');
152 $op |= $opmodes{v} if ($prefix eq '+');
153 }
154
155 push @users, { NICK => $nick, __OP => $op };
156 }
157 }
158
159 return ($server, $cn, $ts, $chmodes, $chmodeparms, \@users, \@bans, \@excepts, \@invex);
160}
161sub parse_addline ($) {
162 my ($line) = @_;
163 #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
164 #>> 47 :583AAAAAA ADDLINE G test@testie inspircd.erry.omg 1308118489 0 :hi
165 my ($setter, undef, $type, $mask, $server, $time, $expiry, $reason) = split (/ /, $line, 7);
166 $reason =~ /:(.*)/;
167 $reason = $1;
168 $setter =~ /:(.*)/;
169 $setter = $1;
170 my @masks = split (/@/,$mask, 1);
171 my $ident = $masks[0];
172 my $host = $masks[1];
173 #return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
174 return ($type, +1, $ident, $host, $setter, $expiry, $time, $reason);
175}
176sub parse_tkl ($) {
177 my ($in) = @_;
178 # This function is intended to accept ALL tkl types,
179 # tho maybe not parse all of them in the first version.
180
181 # Discard first token, 'TKL'
182 my (undef, $sign, $type, $params) = split(/ /, $in, 4);
183
184 # Yes, TKL types are case sensitive!
185 # also be aware (and this applies to the net.pm generator functions too)
186 # This implementation may appear naiive, but Unreal assumes that, for a given
187 # TKL type, that all parameters are non-null.
188 # Thus, if any parameters ARE null, Unreal WILL segfault.
189 ## Update: this problem may have been fixed since Unreal 3.2.2 or so.
190 if ($type eq 'G' or $type eq 'Z' or $type eq 's' or $type eq 'Q') {
191 # format is
192 # TKL + type ident host setter expiretime settime :reason
193 # TKL - type ident host setter
194 # for Q, ident is always '*' or 'h' (Services HOLDs)
195 if ($sign eq '+') {
196 my ($ident, $host, $setter, $expire, $time, $reason) = split(/ /, $params, 6);
197
198 $reason =~ s/^\://;
199 return ($type, +1, $ident, $host, $setter, $expire, $time, $reason);
200 }
201 elsif($sign eq '-') {
202 my ($ident, $host, $setter) = split(/ /, $params, 3);
203 return ($type, -1, $ident, $host, $setter);
204 }
205 }
206 elsif($type eq 'F') {
207 # TKL + F cpnNPq b saturn!attitude@netadmin.SCnet.ops 0 1099959668 86400 Possible_mIRC_DNS_exploit :\/dns (\d+\.){3}\d
208 # TKL + F u g saturn!attitude@saturn.netadmin.SCnet.ops 0 1102273855 604800 sploogatheunbreakable:_Excessively_offensive_behavior,_ban_evasion. :.*!imleetnig@.*\.dsl\.mindspring\.com
209 # TKL - F u Z tabris!northman@tabris.netadmin.SCnet.ops 0 0 :do_not!use@mask
210 if ($sign eq '+') {
211 my ($target, $action, $setter, $expire, $time, $bantime, $reason, $mask) = split(/ /, $params, 8);
212 $mask =~ s/^\://;
213 return ($type, +1, $target, $action, $setter, $expire, $time, $bantime, $reason, $mask);
214 }
215 elsif($sign eq '-') {
216 my ($target, $action, $setter, $expire, $time, $mask) = split(/ /, $params, 6);
217 $mask =~ s/^\://;
218 return ($type, -1, $target, $action, $setter, $mask);
219 }
220 }
221}
222
223sub PING($) {
224 my ($event, $src, $dst, @args);
225 $_[0] =~ /^(?:8|PING) :(\S+)$/;
226 # ($event, $src, $dst, $args)
227 return ('PING', undef, undef, WF_NONE, $1);
228}
229sub UID ($) {
230 #:583 UID 583AAAAAJ 1307703236 erry__ localhost localhost errietta 127.0.0.1 1307703241 + :errietta
231 $_[0] =~ /^(:\S+) UID (\S+) (\d+) (\S+) (\S+) (\S+) (\S+) (\S+) (\d+) (\S+) :(.*)$/;
2eef9154 232 my ($server, $uid, $stamp, $nick, $host, $vhost, $ident, $IP, $ts, $modes, $gecos) = ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12);
5975999e 233 ircd::setRevUuid ($uid, $nick);
234 ircd::setUuid ($nick, $uid);
2eef9154 235 my $user = { NICK => $nick, ID => $uid };
236 return ('NICKCONN', undef, undef, WF_NICK, $user, 0, $ts, $ident, $host, $server, $stamp, $modes, $vhost, $gecos,
5975999e 237 join('.', unpack('C4', MIME::Base64::decode($IP))));
238}
239sub EOS($) {
240 my $event;
241 print "EOS\n";
242 if ($_[1] != "ENDBURST") {
243 $_[0] =~ /^(@|:)(\S+) (?:EOS|ES)/; # Sometimes there's extra crap on the end?
244 my $server;
245 if ($1 eq '@') {
246 $server = $servernum[b64toi($2)];
247 }
248 else {
249 $server = $2;
250 }
2eef9154 251 print "SERVER $server\n";
5975999e 252 set_server_state($server, 1);
253 return undef() unless get_server_state($remoteserv);
254 if($server eq $remoteserv) { $event = 'SEOS' } else { $event = 'EOS' }
255 print "Ok. we had EOS\n";
256 return ($event, undef, undef, WF_ALL, $server);
257 }
258 else {
2eef9154 259 print "wot\n";
260 $_[0] =~ /^:(\S+) ENDBURST/;
261 my $server = $1;
262 set_server_state($server, 1);
263 print "server $server remote $remoteserv\n";
264 return undef() unless get_server_state($remoteserv);
5975999e 265 print "This be it! Got endbrust!\n";
266 return ("ENDBURST", undef, undef, WF_ALL, $1);
267 }
268}
269
270sub SERVER($) {
271 #ircd::debug($_[0]) if $debug;
2eef9154 272
5975999e 273 if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(U[0-9]+)-([A-Za-z0-9]+)-([0-9]+) (.*)$/) {
274 # SERVER test-tab.surrealchat.net 1 :U2307-FhinXeOoZEmM-200 SurrealChat
275 # cmd, servername, hopCount, U<protocol>-<buildflags>-<numeric> infoLine
276 $remoteserv = $1;
277 create_server($1);
278 $servernum[$5] = $1;
279
280 return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $6, $5, $3, $4);
281 # src, serverName, numHops, infoLine, serverNumeric, protocolVersion, buildFlags
282 }
283 elsif($_[0] =~ /^(:|@)(\S+) (?:SERVER|\') (\S+) (\d+) (\d+) :(.*)$/) {
284 # @38 SERVER test-hermes.surrealchat.net 2 100 :SurrealChat
285 # source, cmd, new server, hopCount, serverNumeric, infoLine
286 my ($numeric, $name);
287 if ($1 eq '@') {
288 $name = $servernum[b64toi($2)];
289 }
290 else {
291 $name = $2;
292 }
293 create_server($3, $name);
294 $servernum[$5] = $3;
295
296 return ('SERVER', undef, undef, WF_ALL, $name, $3, $4, $6, $5);
297 # src, serverName, numHops, infoLine, serverNumeric
298 }
299 if($_[0] =~ /^(?:SERVER|\') (\S+) (\S+) :(.*)$/) {
300 $remoteserv = $1;
301 create_server($1);
302 return ('SERVER', undef, undef, WF_ALL, undef, $1, $2, $3);
303 # src, serverName, numHops, infoLine
304 }
305 elsif($_[0] =~ /^:(\S+) (?:SERVER|\') (\S+) (\d+) :(.*)$/) {
306 # source, new server, hop count, description
307 create_server($2, $1);
308 return ('SERVER', undef, undef, WF_ALL, $1, $2, $3, $4);
309 # src, serverName, numHops, infoLine
310 }
2eef9154 311 elsif ($_[0] =~ /SERVER (\S+) (\S+) (\d+) (\S+) :(.*)$/) {
312 #SERVER inspircd.erry.omg mypass 0 583 :erry World
313 #SERVER servername password hopcount SID :Server Desc
314 $remoteserv = $4;
315 create_server ($4);
316 #since from now on we'll be getting commands as sent from the SID it's much wiser to keep that than the name.
317 return ("SERVER", undef, undef, WF_ALL, undef, $1, $3, $5, $4);
318 }
5975999e 319}
320
321sub SQUIT($) {
322 if($_[0] =~ /^(?:SQUIT|-) (\S+) :(.*)$/) {
323 my $list = [get_server_children($1)];
324 set_server_state($1, undef());
325 return ('SQUIT', undef, undef, WF_ALL, undef, $list, $2);
326 }
327 elsif($_[0] =~ /^(:|@)(\S+) (?:SQUIT|-) (\S+) :(.*)$/) {
328 my $name;
329 if ($1 eq '@') {
330 $name = $servernum[b64toi($2)];
331 }
332 else {
333 $name = $2;
334 }
335 my $list = [get_server_children($3)];
336 set_server_state($3, undef());
337 return ('SQUIT', undef, undef, WF_ALL, $name, $list, $4);
338 }
339}
340
341sub NETINFO($) {
342 $_[0] =~ /^(?:NETINFO|AO) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) (\S+) :(.*)$/;
343 return ('NETINFO', undef, undef, WF_NONE, $1, $2, $3, $4, $5, $6, $7, $8);
344}
345
346sub PROTOCTL($) {
347 $_[0] =~ /^PROTOCTL (.*)$/;
348 return ('PROTOCTL', undef, undef, WF_NONE, $1);
349}
350
351sub JOIN($) {
352 $_[0] =~ /^:(\S+) (?:C|JOIN) (\S+)$/;
2eef9154 353 my $user = { ID => $1 };
354 get_user_nick ($user);
355 return ('JOIN', undef, 1, WF_CHAN, $user, $2);
5975999e 356}
2eef9154 357
5975999e 358sub FJOIN ($) {
2eef9154 359 #>> 13 :97K FJOIN #erry 1307879417 +nt :o,97KAAAAAA ,97KAAAAAB
5975999e 360 $_[0] =~ m"^(:\S+) FJOIN (\S+) (\d+) (\S+) (.*)$";
361 my ($server, $channel, $ts, $modes, $userstring) = ($1, $2, $3, $4, $5);
362 my @users = split (" ", $userstring);
2eef9154 363 my (@ids, @status);
5975999e 364 foreach my $user (@users) {
365 my @params = split (",",$user);
366 push (@status, $params[0]);
2eef9154 367 push (@ids, $params[1]);
5975999e 368 }
2eef9154 369 return ('SJOIN', undef, undef, WF_CHAN, parse_fjoin($server, $channel, $ts, $modes, \@ids, \@status));
5975999e 370}
371sub SJOIN($) {
372 if ($_[0] =~ /^(?:\~|SJOIN) (\S+) (\S+) (.*)$/) {
373 my ($ts, $cn, $payload) = ($1, $2, $3);
374 if ($ts =~ s/^!//) {
375 $ts = b64toi($ts);
376 }
377 return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($remoteserv, $ts, $cn, $payload));
378 }
379 elsif($_[0] =~ /^(@|:)(\S+) (?:\~|SJOIN) (\S+) (\S+) (.*)$/) {
380 my ($server, $ts, $cn, $payload) = ($2, $3, $4, $5);
381 if ($1 eq '@') {
382 $server = $servernum[b64toi($2)];
383 }
384 else {
385 $server = $2;
386 }
387 if ($ts =~ s/^!//) {
388 $ts = b64toi($ts);
389 }
390 return ('SJOIN', undef, undef, WF_CHAN, parse_sjoin($server, $ts, $cn, $payload));
391 }
392}
393
394sub PART($) {
2eef9154 395 my $user;
396
5975999e 397 if($_[0] =~ /^:(\S+) (?:D|PART) (\S+) :(.*)$/) {
2eef9154 398 $user = {ID => $1};
399 get_user_nick ($user);
400 return ('PART', undef, 0, WF_CHAN, $user, $2, $3);
5975999e 401 }
402 elsif($_[0] =~ /^:(\S+) (?:D|PART) (\S+)$/) {
2eef9154 403 $user = {ID => $1};
404 return ('PART', undef, 0, WF_CHAN, $user, $2, undef);
405 }
406}
407sub FMODE($) {
408 #:583AAAAAR FMODE #erry 1308214721 +ib test!*@* When any mode in the channel is set.
409 #:583 FMODE #erry 1308214721 +b test1!*@* At server connect. Note that the rest of the channel modes are not there but rather at FJOIN. So this will only have bans and the like.
410 if($_[0] =~ /^:(\S+) FMODE (#\S+) (\d+) (\S+) ?(.*)$/) {
411 my $id = $1;
412 my $user = {ID => $id};
413 get_user_nick ($user);
414 return ('MODE', undef, 1, WF_ALL, $user, $2, $4, $5);
5975999e 415 }
416}
5975999e 417sub MODE($) {
2eef9154 418 my $user;
419
5975999e 420 if($_[0] =~ /^(@|:)(\S+) (?:G|MODE) (#\S+) (\S+) (.*)(?: \d+)?$/) {
421 my $name;
422 if ($1 eq '@') {
423 $name = $servernum[b64toi($2)];
2eef9154 424 $user = {NICK => $name};
5975999e 425 }
426 else {
427 $name = $2;
2eef9154 428 $user = { ID=>$name};
429 get_user_nick ($user);
5975999e 430 }
2eef9154 431 return ('MODE', undef, 1, WF_ALL, $user, $3, $4, $5);
5975999e 432 }
433 elsif($_[0] =~ /^:(\S+) (?:G|MODE) (\S+) :(\S+)$/) {
434 # We shouldn't ever get this, as UMODE2 is preferred
2eef9154 435 $user = { ID => $1 };
436 get_user_nick ($user);
437 return ('UMODE', 0, 0, WF_ALL, $user, $3);
5975999e 438 }
439
440}
441
442sub MESSAGE($) {
443 my ($event, @args);
444 if($_[0] =~ /^(@|:)(\S+) (?:\!|PRIVMSG) (\S+) :(.*)$/) {
2eef9154 445
446 my ($name, $srcUser, $dstUser) ;
5975999e 447 if ($1 eq '@') {
448 $name = $servernum[b64toi($2)];
2eef9154 449 $srcUser = {NICK=>$name};
5975999e 450 }
451 else {
452 $name = $2;
2eef9154 453 $srcUser = {ID=>$name};
454 unless (get_user_nick ($srcUser)) {
455 $srcUser = {NICK=>$name};
456 get_user_id ($name);
457 }
5975999e 458 }
459 my $dest = $3;
2eef9154 460 $dstUser = {ID=>$dest};
461 unless (get_user_nick ($dstUser)) {
462 $dstUser = {NICK=>$dest};
5975999e 463 }
2eef9154 464 print Dumper ($srcUser);
465 print Dumper ($dstUser);
466 $event = 'PRIVMSG'; @args = ($srcUser, $dstUser, $4);
5975999e 467 }
468 elsif($_[0] =~ /^(@|:)(\S+) (?:B|NOTICE) (\S+) :(.*)$/) {
469 my $name;
470 if ($1 eq '@') {
471 $name = $servernum[b64toi($2)];
472 }
473 else {
474 $name = $2;
475 }
476 $event = 'NOTICE'; @args = ($name, $3, $4);
477 }
478 $args[1] =~ s/\@${main_conf{local}}.*//io;
479
480 if(queue_size > 50 and $event eq 'PRIVMSG' and $args[1] !~ /^#/ and $args[2] =~ /^\w/) {
481 ircd::notice($args[1], $args[0], "It looks like the system is busy. You don't need to do your command again, just hold on a minute...");
482 }
483
484 return ($event, 0, 1, WF_ALL, @args);
485}
486
487sub AWAY($) {
488 if($_[0] =~ /^:(\S+) (?:6|AWAY) :(.*)$/) {
2eef9154 489 my $user = {ID=>$1};
490 get_user_nick($user);
491 return ('AWAY', undef, undef, WF_ALL, $user, $2);
5975999e 492 }
2eef9154 493 elsif($_[0] =~ /^:(\S+) (?:6|AWAY)$/) {
494 my $user = {ID => $1};
495 get_user_nick ($user);
496 return ('BACK', undef, undef, WF_ALL, $user);
5975999e 497 }
498}
499
500sub NICK($) {
501 my ($event, @args);
502 #:97KAAAAAA NICK erry_ 1307878528
503 if($_[0] =~ /^:(\S+) (?:NICK|\&) (\S+) :?(\S+)$/) {
2eef9154 504 my $user = {ID => $1};
505 get_user_nick ($user);
5975999e 506 ircd::setRevUuid ($1, $2);
507 ircd::setUuid ($2, $1);
2eef9154 508 return ('NICKCHANGE', undef, undef, WF_NICK, $user, $2, $3);
5975999e 509 }
510}
511
512sub QUIT($) {
513 $_[0] =~ /^:(\S+) (?:QUIT|\,) :(.*)$/;
2eef9154 514 my $user = {ID=>$1};
515 get_user_nick ($1);
516 return ('QUIT', 0, undef, WF_NICK, $user, $2);
5975999e 517}
518
519sub KILL($) {
520#:tabris KILL ProxyBotW :tabris.netadmin.SCnet.ops!tabris (test.)
521#:ProxyBotW!bopm@ircop.SCnet.ops QUIT :Killed (tabris (test.))
522 $_[0] =~ /^(@|:)(\S+) (?:KILL|\.) (\S+) :(\S+) \((.*)\)$/;
523 my $name;
524 if ($1 eq '@') {
525 $name = $servernum[b64toi($2)];
526 }
527 else {
528 $name = $2;
529 }
2eef9154 530 my $user = {ID => $name};
531 unless (get_user_nick ($user)) {
532 $user = {NICK => $name};
533 get_user_id ($user);
534 }
535 return ('KILL', 0, 1, WF_NICK, $user, $3, $4, $5);
5975999e 536}
537
538sub KICK($) {
539#:tabris KICK #diagnostics SurrealBot :i know you don't like this. but it's for science!
540 $_[0] =~ /^(@|:)(\S+) (?:KICK|H) (\S+) (\S+) :(.*)$/;
541 # source, chan, target, reason
542 #$src = 0; #$dst = 2;
543 my $name;
544 if ($1 eq '@') {
545 $name = $servernum[b64toi($2)];
546 }
547 else {
548 $name = $2;
549 }
2eef9154 550 my $user = {ID => $name};
551 unless (get_user_nick ($user)) {
552 $user = {NICK => $name};
553 get_user_id ($user);
554 }
555 return ('KICK', 0, undef, WF_CHAN, $user, $3, $4, $5);
5975999e 556}
557
558sub HOST($) {
559 if($_[0] =~ /^:(\S+) (?:CHGHOST|AL) (\S+) (\S+)$/) {
560 #:Agent CHGHOST tabris tabris.netadmin.SCnet.ops
561 return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3);
562 #setter, target, vhost
563 }
564 elsif($_[0] =~ /^:(\S+) (?:SETHOST|AA) (\S+)$/) {
565 #:tabris SETHOST tabris.netadmin.SCnet.ops
566 return ('CHGHOST', 0, 1, WF_CHAN, $1, $1, $2);
567 }
568
569 elsif ($_[0] =~ /^:(?:\S* )?302 (\S+) :(\S+?)\*?=[+-].*?\@(.*)/) {
570 #:serebii.razorville.co.uk 302 leif :Jesture=+~Jesture00@buzz-3F604D09.sympatico.ca
571 return ('CHGHOST', 0, 1, WF_CHAN, $1, $2, $3);
572 }
573}
574
575
576sub USERIP($) {
577 $_[0] =~ /^:(?:\S* )?340 (\S+) :(\S+?)\*?=[+-].*?\@((?:\.|\d)*)/;
578 return ('USERIP', 0, 1, WF_CHAN, $1, $2, $3);
579}
580
581sub IDENT($) {
582 if($_[0] =~ /^:(\S+) (?:CHGIDENT|AL) (\S+) (\S+)$/) {
583 return ('CHGIDENT', 0, 1, WF_ALL, $1, $2, $3);
584 #setter, target, IDENT
585 }
586 elsif($_[0] =~ /^:(\S+) (?:SETIDENT|AD) (\S+)$/) {
587 return ('CHGIDENT', 0, 1, WF_ALL, $1, $1, $2);
588 #setter, target, ident
589 }
590}
591
592
593sub TOPIC($) {
2eef9154 594 if ($_[0] =~ /^:(\S+) TOPIC (\S+) :(.*)$/) {
595 #:583AAAAAF TOPIC #erry :Welcome to erry(world|net). Have a cookie.
596 my $setter = { ID => $1 };
597 get_user_nick ($setter);
598 return ('TOPIC', 0, 1, WF_ALL, $setter, $2, $setter, 0, $3);
5975999e 599 }
600}
601
602sub UMODE($) {
603#:tabris | +oghaANWt
604 $_[0] =~ /^:(\S+) (?:UMODE2|\|) (\S+)$/;
605 # src, umodes
606 # a note, not all umodes are passed
607 # +s, +O, and +t are not passed. possibly others
608 # also not all umodes do we care about.
609 # umodes we need care about:
610 # oper modes: hoaACN,O oper-only modes: HSq
611 # regular modes: rxB,izV (V is only somewhat, as the ircd
612 # does the conversions from NOTICE to PRIVSMG for us).
613
614 # Yes, I'm changing the event type on this
615 # It's better called UMODE, and easily emulated
616 # on IRCds with only MODE.
617 return ('UMODE', 0, 0, WF_ALL, $1, $2);
618}
2eef9154 619sub OPERTYPE ($) {
620 #:583AAAAAB OPERTYPE SuperNetAdmin
621 #Every OPERTYPE will get +o, so it's safe to assume they're opers,
622 #even if we don't give them privs (either in inspircd or srsv)
623 $_[0] =~ /^:(\S+) OPERTYPE (\S+)$/;
624 my $user = { ID => $1 };
625 print Dumper ($user);
626 get_user_nick ($user);
627 return ("OPERUP", 0, 0, WF_ALL, $user);
628}
5975999e 629sub SVSMODE($) {
630#:tabris | +oghaANWt
631 $_[0] =~ /^:(\S+) (?:SVS2?MODE|n|v) (\S+) (\S+)$/;
632 # src, umodes
633 # a note, not all umodes are passed
634 # +s, +O, and +t are not passed. possibly others
635 # also not all umodes do we care about.
636 # umodes we need care about:
637 # oper modes: hoaACN,O oper-only modes: HSq
638 # regular modes: rxB,izV (V is only somewhat, as the ircd
639 # does the conversions from NOTICE to PRIVSMG for us).
640
641 return ('UMODE', 0, 0, WF_ALL, $2, $3);
642}
643
644sub WHOIS($) {
645# :tab WHOIS ConnectServ :ConnectServ
646 if($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+)$/) {
647 return ('WHOIS', 0, undef, WF_NONE, $1, $2);
648 }
649 elsif($_[0] =~ /^:(\S+) (?:WHOIS|\#) (\S+) :(\S+)$/) {
650 return ('WHOIS', 0, undef, WF_NONE, $1, $3);
651 }
652}
653
654sub TSCTL($) {
655 $_[0] =~ /^:(\S+) (?:TSCTL|AW) alltime$/;
656 ircsend(":$main_conf{local} NOTICE $1 *** Server=$main_conf{local} TSTime=".
657 time." time()=".time." TSOffset=0");
658 return;
659}
660
661sub VERSION($) {
662 $_[0] =~ /^:(\S+) (?:VERSION|\+).*$/;
663 return ('VERSION', 0, undef, WF_NONE, $1);
664}
665
666sub TKL($) {
667 if ($_[0] =~ /^(@|:)(\S+) (?:TKL|BD) (.*)$/) {
668 # We discard the source anyway.
669 #my $server;
670 #if ($1 eq '@') {
671 # $server = $servernum[b64toi($2)];
672 #}
673 #else {
674 # $server = $2;
675 #}
676 return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $3"));
677 }
678 elsif ($_[0] =~ /^(?:TKL|BD) (.*)$/) {
679 return ('TKL', undef, undef, WF_NONE, parse_tkl("TKL $1"));
680 }
681}
682
683sub SNOTICE($) {
684 $_[0] =~ /^(@|:)(\S+) (SENDSNO|Ss|SMO|AU) ([A-Za-z]) :(.*)$/;
685 #@servernumeric Ss snomask :message
686 my $name;
687 if ($1 eq '@') {
688 $name = $servernum[b64toi($2)];
689 }
690 else {
691 $name = $2;
692 }
693 my $event;
694 $event = 'SENDSNO' if(($3 eq 'SENDSNO' or $3 eq 'Ss'));
695 $event = 'SMO' if(($3 eq 'SMO' or $3 eq 'AU'));
696 return ($event, 0, undef, WF_NONE, $name, $4, $5);
697}
698
699sub GLOBOPS($) {
700 $_[0] =~ /^(@|:)(\S+) (?:GLOBOPS|\]) :(.*)$/;
701 #@servernumeric [ :message
702 my $name;
703 if ($1 eq '@') {
704 $name = $servernum[b64toi($2)];
705 }
706 else {
707 $name = $2;
708 }
709 return ('GLOBOPS', 0, undef, WF_NONE, $name, $3);
710}
711
712sub ISUPPORT($) {
713 $_[0] =~ /^:(\S+) (?:105|005) (\S+) (.+) :are supported by this server$/;
714 # :test-tab.surrealchat.net 105 services.SC.net CMDS=KNOCK,MAP,DCCALLOW,USERIP :are supported by this server
715 foreach my $token (split(/\s+/, $3)) {
716 my ($key, $value) = split('=', $token);
717 $IRCd_capabilities{$key} = ($value ? $value : 1);
718 }
719}
720
721sub STATS($) {
722 $_[0] =~ /^:(\S+) (?:STATS|2) (\S) :(.+)$/;
723 return ('STATS', undef, undef, WF_NONE, $1, $2, $3)
724}
725
726BEGIN {
727 %cmdhash = (
728 PING => \&PING,
729 '8' => \&PING,
730
731 EOS => \&EOS,
732 ES => \&EOS,
733 ENDBURST => \&EOS,
734 SERVER => \&SERVER,
735 "\'" => \&SERVER,
736
737 SQUIT => \&SQUIT,
738 '-' => \&SQUIT,
739
740 NETINFO => \&NETINFO,
741 AO => \&NETINFO,
742
743 PROTOCTL => \&PROTOCTL,
744
745 JOIN => \&JOIN,
746 C => \&JOIN,
747
748 PART => \&PART,
749 D => \&PART,
750
751 SJOIN => \&SJOIN,
752 '~' => \&SJOIN,
753 FJOIN => \&FJOIN,
2eef9154 754 FMODE => \&FMODE,
5975999e 755 MODE => \&MODE,
756 G => \&MODE,
757
758 PRIVMSG => \&MESSAGE,
759 '!' => \&MESSAGE,
760 NOTICE => \&MESSAGE,
761 B => \&MESSAGE,
762
763 AWAY => \&AWAY,
764 '6' => \&AWAY,
765
766 NICK => \&NICK,
767 '&' => \&NICK,
768
769 QUIT => \&QUIT,
770 ',' => \&QUIT,
771
772 KILL => \&KILL,
773 '.' => \&KILL,
774
775 KICK => \&KICK,
776 H => \&KICK,
777
778 CHGHOST => \&HOST,
779 AL => \&HOST,
780 SETHOST => \&HOST,
781 AA => \&HOST,
782 '302' => \&HOST,
783
784 '340' => \&USERIP,
785
786 CHGIDENT => \&IDENT,
787 AZ => \&IDENT,
788 SETIDENT => \&IDENT,
789 AD => \&IDENT,
790
791 TOPIC => \&TOPIC,
792 ')' => \&TOPIC,
793
794 UMODE2 => \&UMODE,
795 '|' => \&UMODE,
796
797 TSCTL => \&TSCTL,
798 AW => \&TSCTL,
799
800 VERSION => \&VERSION,
801 '+' => \&VERSION,
802
803 TKL => \&TKL,
804 BD => \&TKL,
805
806 WHOIS => \&WHOIS,
807 '#' => \&WHOIS,
808
809 SENDSNO => \&SNOTICE,
810 Ss => \&SNOTICE,
811
812 SMO => \&SNOTICE,
813 AU => \&SNOTICE,
814
815 GLOBOPS => \&GLOBOPS,
816 ']' => \&GLOBOPS,
817
818 '105' => \&ISUPPORT,
819 '005' => \&ISUPPORT,
820
821 SVSMODE => \&SVSMODE,
822 'n' => \&SVSMODE,
823 SVS2MODE => \&SVSMODE,
824 'v' => \&SVSMODE,
825
826 STATS => \&STATS,
827 '2' => \&STATS,
828 UID => \&UID,
2eef9154 829 OPERTYPE => \&OPERTYPE,
5975999e 830 );
831}
832
8331;