failirc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/bin/failbot +162 -0
  2. data/bin/failircd +61 -0
  3. data/lib/failirc.rb +25 -0
  4. data/lib/failirc/client.rb +227 -0
  5. data/lib/failirc/client/channel.rb +98 -0
  6. data/lib/failirc/client/channels.rb +85 -0
  7. data/lib/failirc/client/client.rb +59 -0
  8. data/lib/failirc/client/clients.rb +43 -0
  9. data/lib/failirc/client/dispatcher.rb +209 -0
  10. data/lib/failirc/client/dispatcher/connectiondispatcher.rb +410 -0
  11. data/lib/failirc/client/dispatcher/event.rb +113 -0
  12. data/lib/failirc/client/dispatcher/eventdispatcher.rb +203 -0
  13. data/lib/failirc/client/module.rb +103 -0
  14. data/lib/failirc/client/modules/Base.rb +361 -0
  15. data/lib/failirc/client/modules/Logger.rb +89 -0
  16. data/lib/failirc/client/server.rb +89 -0
  17. data/lib/failirc/client/user.rb +66 -0
  18. data/lib/failirc/client/users.rb +100 -0
  19. data/lib/failirc/errors.rb +339 -0
  20. data/lib/failirc/extensions.rb +124 -0
  21. data/lib/failirc/mask.rb +117 -0
  22. data/lib/failirc/modes.rb +54 -0
  23. data/lib/failirc/responses.rb +360 -0
  24. data/lib/failirc/server.rb +266 -0
  25. data/lib/failirc/server/channel.rb +122 -0
  26. data/lib/failirc/server/channels.rb +84 -0
  27. data/lib/failirc/server/client.rb +100 -0
  28. data/lib/failirc/server/clients.rb +54 -0
  29. data/lib/failirc/server/dispatcher.rb +219 -0
  30. data/lib/failirc/server/dispatcher/connectiondispatcher.rb +477 -0
  31. data/lib/failirc/server/dispatcher/event.rb +113 -0
  32. data/lib/failirc/server/dispatcher/eventdispatcher.rb +196 -0
  33. data/lib/failirc/server/link.rb +50 -0
  34. data/lib/failirc/server/links.rb +49 -0
  35. data/lib/failirc/server/module.rb +103 -0
  36. data/lib/failirc/server/modules/Base.rb +2545 -0
  37. data/lib/failirc/server/modules/Cloaking.rb +170 -0
  38. data/lib/failirc/server/modules/Firewall.rb +104 -0
  39. data/lib/failirc/server/modules/Netlog.rb +67 -0
  40. data/lib/failirc/server/modules/Roulette.rb +78 -0
  41. data/lib/failirc/server/modules/TinyURL.rb +98 -0
  42. data/lib/failirc/server/modules/Translate.rb +62 -0
  43. data/lib/failirc/server/modules/WordFilter.rb +144 -0
  44. data/lib/failirc/server/user.rb +72 -0
  45. data/lib/failirc/server/users.rb +103 -0
  46. data/lib/failirc/sslutils.rb +74 -0
  47. data/lib/failirc/utils.rb +53 -0
  48. metadata +107 -0
@@ -0,0 +1,2545 @@
1
+ # failirc, a fail IRC library.
2
+ #
3
+ # Copyleft meh. [http://meh.doesntexist.org | meh.ffff@gmail.com]
4
+ #
5
+ # This file is part of failirc.
6
+ #
7
+ # failirc is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # failirc is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with failirc. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+ require 'failirc/utils'
21
+ require 'failirc/errors'
22
+ require 'failirc/responses'
23
+
24
+ require 'failirc/server/module'
25
+
26
+ require 'failirc/server/client'
27
+ require 'failirc/server/channel'
28
+ require 'failirc/server/user'
29
+
30
+ module IRC
31
+
32
+ class Server
33
+
34
+ module Modules
35
+
36
+ class Base < Module
37
+ attr_reader :messages
38
+
39
+ @@version = '0.0.1'
40
+
41
+ @@modes = {
42
+ :groups => {
43
+ :can_change_channel_modes => [
44
+ :can_change_channel_extended_modes, :can_change_topic_mode,
45
+ :can_change_no_external_messages_mode, :can_change_secret_mode,
46
+ :can_change_ssl_mode, :can_change_moderated_mode,
47
+ :can_change_invite_only_mode, :can_change_auditorium_mode,
48
+ :can_change_anonymous_mode, :can_change_limit_mode,
49
+ :can_change_redirect_mode, :can_change_noknock_mode,
50
+ :can_add_invitation, :can_channel_ban, :can_add_ban_exception,
51
+ :can_change_channel_password, :can_change_nocolors_mode,
52
+ :can_change_noctcp_mode, :can_change_no_nick_change_mode,
53
+ :can_change_nokicks_mode, :can_change_strip_colors_mode,
54
+ :can_change_noinvites_mode,
55
+ ],
56
+
57
+ :can_change_user_modes => [
58
+ :can_give_channel_operator, :can_give_channel_half_operator,
59
+ :can_give_voice, :can_change_user_extended_modes,
60
+ ],
61
+
62
+ :can_change_client_modes => [
63
+ :can_change_client_extended_modes,
64
+ ],
65
+ },
66
+
67
+ :channel => {
68
+ :a => :anonymous,
69
+ :c => :no_colors,
70
+ :C => :no_ctcps,
71
+ :i => :invite_only,
72
+ :l => :limit,
73
+ :L => :redirect,
74
+ :k => :password,
75
+ :K => :no_knock,
76
+ :m => :moderated,
77
+ :n => :no_external_messages,
78
+ :N => :no_nick_change,
79
+ :Q => :no_kicks,
80
+ :s => :secret,
81
+ :S => :strip_colors,
82
+ :t => :topic_change_needs_privileges,
83
+ :u => :auditorium,
84
+ :V => :no_invites,
85
+ :z => :ssl_only,
86
+ },
87
+
88
+ :user => {
89
+ :x => [:y, :can_give_channel_admin],
90
+ :y => [:o, :admin],
91
+ :o => [:h, :operator, :can_change_topic, :can_invite, :can_change_channel_modes, :can_change_user_modes],
92
+ :h => [:v, :halfoperator, :can_kick],
93
+ :v => [:voice, :can_talk],
94
+ },
95
+
96
+ :client => {
97
+ :netadmin => [:N, :operator],
98
+ :operator => [:o, :can_kill, :can_kick, :can_give_channel_owner, :can_change_topic, :can_change_channel_modes, :can_change_user_modes, :can_change_client_modes],
99
+ },
100
+ }
101
+
102
+ @@supportedModes = {
103
+ :client => [],
104
+ :channel => [],
105
+ }
106
+
107
+ @@support = {}
108
+
109
+ def self.version
110
+ @@version
111
+ end
112
+
113
+ def self.modes
114
+ @@modes
115
+ end
116
+
117
+ def self.supportedModes
118
+ @@supportedModes
119
+ end
120
+
121
+ def self.support
122
+ @@support
123
+ end
124
+
125
+ def description
126
+ "Base-#{Base.version}"
127
+ end
128
+
129
+ def initialize (server)
130
+ @aliases = {
131
+ :input => {
132
+ :PASS => /^PASS( |$)/i,
133
+ :NICK => /^(:[^ ] )?NICK( |$)/i,
134
+ :USER => /^(:[^ ] )?USER( |$)/i,
135
+
136
+ :PING => /^PING( |$)/i,
137
+ :PONG => /^PONG( |$)/i,
138
+
139
+ :AWAY => /^AWAY( |$)/i,
140
+ :MODE => /^MODE( |$)/i,
141
+ :ENCODING => /^ENCODING( |$)/i,
142
+
143
+ :JOIN => /^(:[^ ] )?JOIN( |$)/i,
144
+ :PART => /^(:[^ ] )?PART( |$)/i,
145
+ :KICK => /^(:[^ ] )?KICK( |$)/i,
146
+ :INVITE => /^INVITE( |$)/i,
147
+ :KNOCK => /^KNOCK( |$)/i,
148
+
149
+ :TOPIC => /^(:[^ ] )?TOPIC( |$)/i,
150
+ :NAMES => /^NAMES( |$)/i,
151
+ :LIST => /^LIST( |$)/i,
152
+
153
+ :WHO => /^WHO( |$)/i,
154
+ :WHOIS => /^WHOIS( |$)/i,
155
+ :WHOWAS => /^WHOWAS( |$)/i,
156
+ :ISON => /^ISON( |$)/i,
157
+
158
+ :PRIVMSG => /^(:[^ ] )?PRIVMSG( |$)/i,
159
+ :NOTICE => /^NOTICE( |$)/i,
160
+
161
+ :MAP => /^MAP( |$)/i,
162
+ :VERSION => /^VERSION( |$)/i,
163
+
164
+ :OPER => /^OPER( |$)/i,
165
+ :KILL => /^KILL( |$)/i,
166
+
167
+ :QUIT => /^QUIT( |$)/i,
168
+ },
169
+ }
170
+
171
+ @events = {
172
+ :pre => [Event::Callback.new(self.method(:input_encoding), -1234567890), self.method(:check)],
173
+ :post => [Event::Callback.new(self.method(:output_encoding), 1234567890)],
174
+
175
+ :custom => {
176
+ :client_nick_change => self.method(:client_nick_change),
177
+
178
+ :kill => self.method(:client_quit),
179
+
180
+ :join => self.method(:client_join),
181
+ :part => self.method(:user_part),
182
+ :kick => self.method(:send_kick),
183
+ :invite => self.method(:client_invite),
184
+
185
+ :whois => self.method(:send_whois),
186
+
187
+ :message => [self.method(:handling_message), self.method(:send_message)],
188
+ :notice => [self.method(:handling_notice), self.method(:send_notice)],
189
+ :ctcp => [self.method(:handling_ctcp), self.method(:send_ctcp)],
190
+ :error => self.method(:send_error),
191
+
192
+ :topic_change => self.method(:topic_change),
193
+
194
+ :mode => [self.method(:normal_mode), self.method(:extended_mode)],
195
+ },
196
+
197
+ :default => self.method(:unknown_command),
198
+
199
+ :input => {
200
+ :PING => self.method(:ping),
201
+ :PONG => self.method(:pong),
202
+
203
+ :AWAY => self.method(:away),
204
+ :MODE => self.method(:mode),
205
+ :ENCODING => self.method(:encoding),
206
+
207
+ :PASS => self.method(:pass),
208
+ :NICK => self.method(:nick),
209
+ :USER => self.method(:user),
210
+
211
+ :JOIN => self.method(:join),
212
+ :PART => self.method(:part),
213
+ :KICK => self.method(:kick),
214
+ :INVITE => self.method(:invite),
215
+ :KNOCK => self.method(:knock),
216
+
217
+ :TOPIC => self.method(:topic),
218
+ :NAMES => self.method(:names),
219
+ :LIST => self.method(:list),
220
+
221
+ :WHO => self.method(:who),
222
+ :WHOIS => self.method(:whois),
223
+ :WHOWAS => self.method(:whowas),
224
+ :ISON => self.method(:ison),
225
+
226
+ :PRIVMSG => self.method(:privmsg),
227
+ :NOTICE => self.method(:notice),
228
+
229
+ :MAP => self.method(:map),
230
+ :VERSION => self.method(:version),
231
+
232
+ :OPER => self.method(:oper),
233
+ :KILL => self.method(:kill),
234
+
235
+ :QUIT => self.method(:quit),
236
+ },
237
+ }
238
+
239
+ super(server)
240
+
241
+ server.data[:nicks] = {}
242
+
243
+ @@supportedModes[:client].insert(-1, *('o'.split(//)))
244
+ @@supportedModes[:channel].insert(-1, *('abcCehiIkKlLmnoQsStuvVxyz'.split(//)))
245
+
246
+ @@support.merge!({
247
+ 'CASEMAPPING' => 'ascii',
248
+ 'SAFELIST' => true,
249
+ 'EXCEPTS' => true,
250
+ 'CHANTYPES' => '&#+!',
251
+ 'PREFIX' => '(xyohv)~&@%+',
252
+ 'STATUSMSG' => '~&@%+',
253
+ 'FNC' => true,
254
+
255
+ 'CMDS' => 'KNOCK',
256
+ })
257
+
258
+ @joining = ThreadSafeHash.new
259
+ @semaphore = Mutex.new
260
+
261
+ @pingedOut = ThreadSafeHash.new
262
+ @toPing = ThreadSafeHash.new
263
+
264
+ @pingInterval = server.dispatcher.setInterval Fiber.new {
265
+ while true
266
+ # time to ping non active users
267
+ @toPing.each_value {|client|
268
+ @pingedOut[client.socket] = client
269
+
270
+ if client.modes[:registered]
271
+ client.send :raw, "PING :#{server.host}"
272
+ end
273
+ }
274
+
275
+ # clear and refil the hash of clients to ping with all the connected clients
276
+ @toPing.clear
277
+ @toPing.merge!(Hash[server.clients.values.collect {|client| [client.socket, client]}])
278
+
279
+ Fiber.yield
280
+
281
+ # people who didn't answer with a PONG has to YIFF IN HELL.
282
+ @pingedOut.each_value {|client|
283
+ if !client.socket.closed?
284
+ server.kill client, 'Ping timeout', true
285
+ end
286
+ }
287
+
288
+ @pingedOut.clear
289
+ end
290
+ }, (@pingTimeout / 2)
291
+ end
292
+
293
+ def rehash
294
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/misc/pingTimeout']
295
+ @pingTimeout = tmp.text.to_f
296
+ else
297
+ @pingTimeout = 60
298
+ end
299
+
300
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/misc/nickAllowed']
301
+ @nickAllowed = tmp.text
302
+ else
303
+ @nickAllowed = 'nick.match(/^[\w^`-]{1,23}$/)'
304
+ end
305
+
306
+ @messages = {}
307
+
308
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/messages/part']
309
+ @messages[:part] = tmp.text
310
+ else
311
+ @messages[:part] = '#{message}'
312
+ end
313
+
314
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/messages/quit']
315
+ @messages[:quit] = tmp.text
316
+ else
317
+ @messages[:quit] = 'Quit: #{message}'
318
+ end
319
+
320
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/messages/kill']
321
+ @messages[:kill] = tmp.text
322
+ else
323
+ @messages[:kill] = 'Kill: #{(message && !message.empty?) ? message : \'No reason\'} (#{sender.nick})'
324
+ end
325
+
326
+ if tmp = server.config.elements['config/modules/module[@name="Base"]/messages/version']
327
+ @messages[:version] = tmp.text
328
+ else
329
+ @messages[:version] = 'THE GAME'
330
+ end
331
+ end
332
+
333
+ def finalize
334
+ server.dispatcher.clearInterval @pingInterval
335
+ end
336
+
337
+ module Utils
338
+ module Client
339
+ class Action
340
+ attr_reader :client, :event, :string, :on
341
+
342
+ def initialize (client, event, string)
343
+ @client = client
344
+ @event = event
345
+ @string = string
346
+ @on = Time.now
347
+ end
348
+ end
349
+ end
350
+
351
+ module Channel
352
+ class Ban
353
+ attr_reader :setBy, :setOn, :channel, :mask
354
+
355
+ def initialize (by, channel, mask)
356
+ @setBy = by
357
+ @setOn = Time.now
358
+ @channel = channel
359
+ @mask = mask
360
+ end
361
+
362
+ def to_s
363
+ "#{channel} #{mask} #{setBy.nick} #{setOn.tv_sec}"
364
+ end
365
+ end
366
+
367
+ class Invitation
368
+ attr_reader :setBy, :setOn, :channel, :mask
369
+
370
+ def initialize (by, channel, mask)
371
+ @setBy = by
372
+ @setOn = Time.now
373
+ @channel = channel
374
+ @mask = mask
375
+ end
376
+
377
+ def to_s
378
+ "#{channel} #{mask} #{setBy.nick} #{setOn.tv_sec}"
379
+ end
380
+ end
381
+
382
+ def self.type (string)
383
+ string.match(/^([&#+!])/)
384
+ end
385
+
386
+ def self.isValid (string)
387
+ string.match(/^[&#+!][^ ,:\a]{0,50}$/) ? true : false
388
+ end
389
+
390
+ def self.invited? (channel, client, shallow=false)
391
+ if shallow && !channel.modes[:invite_only]
392
+ return true
393
+ end
394
+
395
+ if channel.modes[:invited].has_value?(client.nick)
396
+ return true
397
+ end
398
+
399
+ channel.modes[:invites].each {|invite|
400
+ if invite.match(client.mask)
401
+ return true
402
+ end
403
+ }
404
+
405
+ return false
406
+ end
407
+
408
+ def self.banned? (channel, client)
409
+ channel.modes[:bans].each {|ban|
410
+ if ban.match(client.mask)
411
+ return true
412
+ end
413
+ }
414
+
415
+ return false
416
+ end
417
+
418
+ def self.exception? (channel, client)
419
+ channel.modes[:exceptions].each {|exception|
420
+ if exception.match(client.mask)
421
+ return true
422
+ end
423
+ }
424
+
425
+ return false
426
+ end
427
+ end
428
+
429
+ module User
430
+ @@levels = {
431
+ :x => '~',
432
+ :y => '&',
433
+ :o => '@',
434
+ :h => '%',
435
+ :v => '+',
436
+ }
437
+
438
+ def self.levels
439
+ return @@levels
440
+ end
441
+
442
+ @@levelsOrder = [:x, :y, :o, :h, :v]
443
+
444
+ def self.isLevel (char)
445
+ @@levels.has_value?(char) ? char : false
446
+ end
447
+
448
+ def self.isLevelEnough (user, level)
449
+ if !level || (level.is_a?(String) && level.empty?)
450
+ return true
451
+ end
452
+
453
+ if level.is_a?(String)
454
+ level = @@levels.key level
455
+ end
456
+
457
+ highest = self.getHighestLevel(user)
458
+
459
+ if !highest
460
+ return false
461
+ else
462
+ highest = @@levelsOrder.index(highest)
463
+ level = @@levelsOrder.index(level)
464
+
465
+ if !level
466
+ return true
467
+ elsif !highest
468
+ return false
469
+ else
470
+ return highest <= level
471
+ end
472
+ end
473
+ end
474
+
475
+ def self.getHighestLevel (user)
476
+ if user.modes[:x]
477
+ return :x
478
+ elsif user.modes[:y]
479
+ return :y
480
+ elsif user.modes[:o]
481
+ return :o
482
+ elsif user.modes[:h]
483
+ return :h
484
+ elsif user.modes[:v]
485
+ return :v
486
+ end
487
+ end
488
+
489
+ def self.setLevel (user, level, value)
490
+ if @@levels[level]
491
+ Utils::setFlags(user, level, value)
492
+
493
+ if value
494
+ user.modes[:level] = @@levels[level]
495
+ else
496
+ self.setLevel(user, self.getHighestLevel(user), true)
497
+ end
498
+ else
499
+ user.modes[:level] = ''
500
+ end
501
+ end
502
+ end
503
+
504
+ # This method does some checks trying to register the connection, various checks
505
+ # for nick collisions and such.
506
+ def self.registration (thing)
507
+ if !thing.modes[:registered]
508
+ # additional check for nick collisions
509
+ if thing.nick
510
+ if (thing.server.data[:nicks][thing.nick] && thing.server.data[:nicks][thing.nick] != thing) || thing.server.clients[thing.nick]
511
+ if thing.modes[:__warned] != thing.nick
512
+ thing.send :numeric, ERR_NICKNAMEINUSE, thing.nick
513
+ thing.modes[:__warned] = thing.nick
514
+ end
515
+
516
+ return
517
+ end
518
+
519
+ thing.server.data[:nicks][thing.nick] = thing
520
+ end
521
+
522
+ # if the client isn't registered but has all the needed attributes, register it
523
+ if thing.user && thing.nick
524
+ if thing.listen.attributes['password'] && thing.listen.attributes['password'] != thing.password
525
+ return false
526
+ end
527
+
528
+ thing.modes[:registered] = true
529
+
530
+ # clean the temporary hash value and use the nick as key
531
+ thing.server.clients.delete(thing.socket)
532
+ thing.server.clients[thing.nick] = thing
533
+
534
+ thing.server.data[:nicks].delete(thing.nick)
535
+ thing.modes.delete(:__warned)
536
+
537
+ thing.server.dispatcher.execute(:registration, thing)
538
+
539
+ thing.send :numeric, RPL_WELCOME, thing
540
+ thing.send :numeric, RPL_HOSTEDBY, thing
541
+ thing.send :numeric, RPL_SERVCREATEDON
542
+ thing.send :numeric, RPL_SERVINFO, {
543
+ :user => Base.supportedModes[:client].join(''),
544
+ :channel => Base.supportedModes[:channel].join(''),
545
+ }
546
+
547
+ supported = String.new
548
+
549
+ Base.support.each {|key, value|
550
+ if value != true
551
+ supported << " #{key}=#{value}"
552
+ else
553
+ supported << " #{key}"
554
+ end
555
+ }
556
+
557
+ supported = supported[1, supported.length]
558
+
559
+ thing.send :numeric, RPL_ISUPPORT, supported
560
+
561
+ motd(thing)
562
+ end
563
+ end
564
+ end
565
+
566
+ # This method sends the MOTD 80 chars per line.
567
+ def self.motd (user)
568
+ user.send :numeric, RPL_MOTDSTART
569
+
570
+ offset = 0
571
+ motd = user.server.config.elements['config/server/motd'].text.strip
572
+
573
+ while line = motd[offset, 80]
574
+ user.send :numeric, RPL_MOTD, line
575
+ offset += 80
576
+ end
577
+
578
+ user.send :numeric, RPL_ENDOFMOTD
579
+ end
580
+
581
+ # This method assigns flags recursively using groups of flags
582
+ def self.setFlags (thing, type, value, inherited=false, forceFalse=false)
583
+ if Base.modes[:groups][type]
584
+ main = Base.modes[:groups]
585
+ else
586
+ if thing.is_a?(Server::Channel)
587
+ main = Base.modes[:channel]
588
+ elsif thing.is_a?(Server::User)
589
+ main = Base.modes[:user]
590
+ elsif thing.is_a?(Server::Client)
591
+ main = Base.modes[:client]
592
+ else
593
+ raise 'What sould I do?'
594
+ end
595
+ end
596
+
597
+ if !inherited
598
+ if value == false
599
+ thing.modes.delete(type)
600
+ else
601
+ thing.modes[type] = value
602
+ end
603
+ end
604
+
605
+ if !(modes = main[type])
606
+ return
607
+ end
608
+
609
+ if !modes.is_a?(Array)
610
+ modes = [modes]
611
+ end
612
+
613
+ modes.each {|mode|
614
+ if (main[mode] || Base.modes[:groups][mode]) && !thing.modes.has_key?(mode)
615
+ self.setFlags(thing, mode, value, !forceFalse)
616
+ else
617
+ if value == false
618
+ if !main.has_key?(mode)
619
+ thing.modes.delete(mode)
620
+ end
621
+ else
622
+ thing.modes[mode] = value
623
+ end
624
+ end
625
+ }
626
+ end
627
+
628
+ def self.checkFlag (thing, type)
629
+ # servers can do everything
630
+ if thing.is_a?(IRC::Server)
631
+ return true
632
+ end
633
+
634
+ result = thing.modes[type]
635
+
636
+ if !result && thing.is_a?(Server::User)
637
+ result = thing.client.modes[type]
638
+ end
639
+
640
+ if result.nil?
641
+ result = false
642
+ end
643
+
644
+ return result
645
+ end
646
+
647
+ def self.dispatchMessage (kind, from, to, message, level=nil)
648
+ if from.is_a?(Server::User)
649
+ from = from.client
650
+ end
651
+
652
+ if match = message.match(/^\x01([^ ]*)( (.*?))?\x01$/)
653
+ from.server.dispatcher.execute :ctcp, :input, kind, ref{:from}, ref{:to}, match[1], match[3], level
654
+ else
655
+ if kind == :notice
656
+ from.server.dispatcher.execute :notice, :input, ref{:from}, ref{:to}, message, level
657
+ elsif kind == :message
658
+ from.server.dispatcher.execute :message, :input, ref{:from}, ref{:to}, message
659
+ end
660
+ end
661
+ end
662
+
663
+ def self.escapeMessage (string)
664
+ string.inspect.gsub(/\\#/, '#').gsub(/\\'/, "'")
665
+ end
666
+ end
667
+
668
+ def check (event, thing, string)
669
+ if event.chain != :input || !thing || !string
670
+ return
671
+ end
672
+
673
+ @toPing.delete(thing.socket)
674
+ @pingedOut.delete(thing.socket)
675
+
676
+ if !event.aliases.include?(:PING) && !event.aliases.include?(:PONG) && !event.aliases.include?(:WHO) && !event.aliases.include?(:MODE)
677
+ thing.modes[:last_action] = Utils::Client::Action.new(thing, event, string)
678
+ end
679
+
680
+ stop = false
681
+
682
+ # if the client tries to do something without having registered, kill it with fire
683
+ if !event.aliases.include?(:PASS) && !event.aliases.include?(:NICK) && !event.aliases.include?(:USER) && !thing.modes[:registered]
684
+ thing.send :numeric, ERR_NOTREGISTERED
685
+ stop = true
686
+ # if the client tries to reregister, kill it with fire
687
+ elsif (event.aliases.include?(:PASS) || event.aliases.include?(:USER)) && thing.modes[:registered]
688
+ thing.send :numeric, ERR_ALREADYREGISTRED
689
+ stop = true
690
+ end
691
+
692
+ return !stop
693
+ end
694
+
695
+ def input_encoding (event, thing, string)
696
+ if event.chain != :input
697
+ return
698
+ end
699
+
700
+ begin
701
+ if thing.modes[:encoding]
702
+ string.force_encoding(thing.modes[:encoding])
703
+ string.encode!('UTF-8')
704
+ else
705
+ string.force_encoding('UTF-8')
706
+
707
+ if !string.valid_encoding?
708
+ raise Encoding::InvalidByteSequenceError
709
+ end
710
+ end
711
+ rescue
712
+ if thing.modes[:encoding]
713
+ server.dispatcher.execute :error, thing, 'The encoding you choose seems to not be the one you are using.'
714
+ else
715
+ server.dispatcher.execute :error, thing, 'Please specify the encoding you are using with ENCODING <encoding>'
716
+ end
717
+
718
+ string.force_encoding('ASCII-8BIT')
719
+
720
+ string.encode!('UTF-8',
721
+ :invalid => :replace,
722
+ :undef => :replace
723
+ )
724
+ end
725
+ end
726
+
727
+ def output_encoding (event, thing, string)
728
+ if event.chain != :output
729
+ return
730
+ end
731
+
732
+ if thing.modes[:encoding]
733
+ string.encode!(thing.modes[:encoding],
734
+ :invalid => :replace,
735
+ :undef => :replace
736
+ )
737
+ end
738
+ end
739
+
740
+ def unknown_command (event, thing, string)
741
+ match = string.match(/^([^ ]+)/)
742
+
743
+ if match && thing.modes[:registered]
744
+ thing.send :numeric, ERR_UNKNOWNCOMMAND, match[1]
745
+ end
746
+ end
747
+
748
+ def pass (thing, string)
749
+ match = string.match(/PASS\s+(:)?(.+)$/i)
750
+
751
+ if !match
752
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'PASS'
753
+ else
754
+ thing.password = match[2]
755
+
756
+ if thing.listen.attributes['password']
757
+ if thing.password != thing.listen.attributes['password']
758
+ server.dispatcher.execute(:error, thing, :close, 'Password mismatch')
759
+ server.kill thing, 'Password mismatch'
760
+ return
761
+ end
762
+ end
763
+
764
+ # try to register it
765
+ Utils::registration(thing)
766
+ end
767
+ end
768
+
769
+ def nick (thing, string)
770
+ if !thing.is_a?(Client)
771
+ return
772
+ end
773
+
774
+ match = string.match(/NICK\s+(:)?(.+)$/i)
775
+
776
+ # no nickname was passed, so tell the user is a faggot
777
+ if !match
778
+ thing.send :numeric, ERR_NONICKNAMEGIVEN
779
+ return
780
+ end
781
+
782
+ nick = match[2].strip
783
+
784
+ if server.dispatcher.execute(:client_nick_change, thing, nick) == false
785
+ if !thing.modes[:registered]
786
+ thing.modes[:__warned] = nick
787
+ end
788
+
789
+ return
790
+ end
791
+
792
+ if !thing.modes[:registered]
793
+ thing.nick = nick
794
+
795
+ # try to register it
796
+ Utils::registration(thing)
797
+ else
798
+ ok = true
799
+
800
+ thing.channels.each_value {|channel|
801
+ if channel.modes[:no_nick_change] && !Utils::User::isLevelEnough(channel.user(thing), '+')
802
+ thing.send :numeric, ERR_NONICKCHANGE, channel.name
803
+ ok = false
804
+ break
805
+ end
806
+ }
807
+
808
+ if !ok
809
+ return false
810
+ end
811
+
812
+ server.data[:nicks].delete(nick)
813
+
814
+ mask = thing.mask.clone
815
+ thing.nick = nick
816
+
817
+ server.clients[thing.nick] = server.clients.delete(mask.nick)
818
+
819
+ thing.channels.each_value {|channel|
820
+ channel.users.add(channel.users.delete(mask.nick))
821
+ }
822
+
823
+ if thing.channels.empty?
824
+ thing.send :raw, ":#{mask} NICK :#{nick}"
825
+ else
826
+ thing.channels.unique_users.send :raw, ":#{mask} NICK :#{nick}"
827
+ end
828
+ end
829
+ end
830
+
831
+ def client_nick_change (thing, nick)
832
+ if server.clients[nick] || server.data[:nicks][nick]
833
+ thing.send :numeric, ERR_NICKNAMEINUSE, nick
834
+ return false
835
+ end
836
+
837
+ allowed = eval(@nickAllowed) rescue false
838
+
839
+ if !allowed || nick.downcase == 'anonymous'
840
+ thing.send :numeric, ERR_ERRONEUSNICKNAME, nick
841
+ return false
842
+ end
843
+ end
844
+
845
+ def user (thing, string)
846
+ if thing.is_a?(Client)
847
+ match = string.match(/USER\s+([^ ]+)\s+[^ ]+\s+[^ ]+\s+:(.+)$/i)
848
+
849
+ if !match
850
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'USER'
851
+ else
852
+ thing.user = match[1]
853
+ thing.realName = match[2]
854
+
855
+ # try to register it
856
+ Utils::registration(thing)
857
+ end
858
+ elsif thing.is_a?(Link)
859
+
860
+ end
861
+ end
862
+
863
+ def ping (thing, string)
864
+ match = string.match(/PING\s+(.*)$/i)
865
+
866
+ if !match
867
+ thing.send :numeric, ERR_NOORIGIN
868
+ return
869
+ end
870
+
871
+ thing.send :raw, ":#{server.host} PONG #{server.host} :#{match[1]}"
872
+
873
+ # RFC isn't that clear about when this error should be shoot
874
+ # thing.send :numeric, ERR_NOSUCHSERVER, match[1]
875
+ end
876
+
877
+ def pong (thing, string)
878
+ match = string.match(/PONG\s+(:)?(.*)$/i)
879
+
880
+ if !match
881
+ thing.send :numeric, ERR_NOORIGIN
882
+ return
883
+ end
884
+
885
+ if match[2] == server.host
886
+ @pingedOut.delete(thing.socket)
887
+ else
888
+ thing.send :numeric, ERR_NOSUCHSERVER, match[2]
889
+ end
890
+ end
891
+
892
+ def away (thing, string)
893
+ match = string.match(/AWAY\s+(:)?(.*)$/i)
894
+
895
+ if !match || match[2].empty?
896
+ thing.modes[:away] = false
897
+ thing.send :numeric, RPL_UNAWAY
898
+ else
899
+ thing.modes[:away] = match[2]
900
+ thing.send :numeric, RPL_NOWAWAY
901
+ end
902
+ end
903
+
904
+ def mode (thing, string)
905
+ # MODE user/channel = +option,-option
906
+ match = string.match(/MODE\s+([^ ]+)(\s+(:)?(.*))?$/i)
907
+
908
+ if !match
909
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'MODE'
910
+ return
911
+ end
912
+
913
+ name = match[1]
914
+ value = match[4] || ''
915
+
916
+ # long options, extended protocol
917
+ if match = value.match(/^=\s+(.*)$/)
918
+ if Utils::Channel::isValid(name)
919
+ channel = server.channels[name]
920
+
921
+ if channel
922
+ handle_mode channel.user(thing) || thing, channel, value
923
+ else
924
+ thing.send :numeric, ERR_NOSUCHCHANNEL, name
925
+ end
926
+ elsif match = name.match(/^([^@])@(.*)$/)
927
+ user = match[1]
928
+ channel = match[2]
929
+
930
+ if tmp = server.channels[channel]
931
+ channel = tmp
932
+
933
+ if tmp = server.clients[user]
934
+ if tmp = channel.user(tmp)
935
+ user = tmp
936
+
937
+ handle_mode thing, user, value
938
+ else
939
+ thing.send :numeric, ERR_USERNOTINCHANNEL, {
940
+ :nick => user,
941
+ :channel => channel,
942
+ }
943
+ end
944
+ else
945
+ thing.send :numeric, ERR_NOSUCHNICK, user
946
+ end
947
+ else
948
+ thing.send :numeric, ERR_NOSUCHCHANNEL, channel
949
+ end
950
+ else
951
+ if tmp = server.clients[name]
952
+ client = tmp
953
+
954
+ handle_mode thing, client, value
955
+ else
956
+ thing.send :numeric, ERR_NOSUCHNICK, name
957
+ end
958
+ end
959
+ # usual shit
960
+ else
961
+ if Utils::Channel::isValid(name)
962
+ if server.channels[name]
963
+ channel = server.channels[name]
964
+
965
+ if value.empty?
966
+ thing.send :numeric, RPL_CHANNELMODEIS, channel
967
+ thing.send :numeric, RPL_CHANCREATEDON, channel
968
+ else
969
+ if thing.channels[name]
970
+ thing = thing.channels[name].user(thing)
971
+ end
972
+
973
+ handle_mode thing, channel, value
974
+ end
975
+ else
976
+ thing.send :numeric, ERR_NOSUCHCHANNEL, name
977
+ end
978
+ else
979
+ if server.clients[name]
980
+ handle_mode thing, server.clients[name], value
981
+ else
982
+ thing.send :numeric, ERR_NOSUCHNICK, name
983
+ end
984
+ end
985
+ end
986
+ end
987
+
988
+ def handle_mode (from, thing, request, noAnswer=false)
989
+ if match = request.match(/^=(.*)$/)
990
+ value = match[1].strip
991
+
992
+ if value == '?'
993
+ server.dispatcher.execute :mode, :extended, from, thing, '?', nil, nil, nil
994
+ else
995
+ modes = value.split(/[^\\],/)
996
+
997
+ modes.each {|mode|
998
+ if mode[0, 1] == '-'
999
+ type = '-'
1000
+ else
1001
+ type = '+'
1002
+ end
1003
+
1004
+ mode.sub!(/^[+\-]/, '')
1005
+
1006
+ mode = mode.split(/=/)
1007
+
1008
+ server.dispatcher.execute :mode, :extended, from, thing, type, *mode, nil
1009
+ }
1010
+ end
1011
+ else
1012
+ output = {
1013
+ :modes => [],
1014
+ :values => [],
1015
+ }
1016
+
1017
+ match = request.match(/^\s*([+\-])?\s*([^ ]+)(\s+(.+))?$/)
1018
+
1019
+ if !match
1020
+ return false
1021
+ end
1022
+
1023
+ type = match[1] || '+'
1024
+ modes = match[2].split(//)
1025
+ values = (match[4] || '').strip.split(/ /)
1026
+
1027
+ modes.each {|mode|
1028
+ server.dispatcher.execute :mode, :normal, from, thing, type, mode, values, output
1029
+ }
1030
+
1031
+ if from.is_a?(Server::Client) || from.is_a?(Server::User)
1032
+ from = from.mask
1033
+ end
1034
+
1035
+ if !noAnswer && (!output[:modes].empty? || !output[:values].empty?)
1036
+ string = "#{type}#{output[:modes].join('')}"
1037
+
1038
+ if !output[:values].empty?
1039
+ string << " #{output[:values].join(' ')}"
1040
+ end
1041
+
1042
+ thing.send :raw, ":#{from} MODE #{thing.is_a?(Server::Channel) ? thing.name : thing.nick} #{string}"
1043
+ end
1044
+
1045
+ end
1046
+ end
1047
+
1048
+ def normal_mode (kind, from, thing, type, mode, values, output={:modes => [], :values => []})
1049
+ if kind != :normal
1050
+ return
1051
+ end
1052
+
1053
+ if thing.is_a?(Server::Channel)
1054
+ case mode
1055
+
1056
+ when 'a'
1057
+ if thing.type != '&' && thing.type != '!'
1058
+ server.dispatcher.execute :error, from, 'Only & and ! channels can use this mode.'
1059
+ end
1060
+
1061
+ if Utils::checkFlag(from, :can_change_anonymous_mode)
1062
+ if Utils::checkFlag(thing, :a) == (type == '+')
1063
+ return
1064
+ end
1065
+
1066
+ Utils::setFlags(thing, :a, type == '+')
1067
+
1068
+ output[:modes].push('a')
1069
+ end
1070
+
1071
+ when 'b'
1072
+ if values.empty?
1073
+ thing.modes[:bans].each {|ban|
1074
+ from.send :numeric, RPL_BANLIST, ban
1075
+ }
1076
+
1077
+ from.send :numeric, RPL_ENDOFBANLIST, thing.name
1078
+ return
1079
+ end
1080
+
1081
+ if Utils::checkFlag(from, :can_channel_ban)
1082
+ mask = Mask.parse(values.shift)
1083
+
1084
+ if type == '+'
1085
+ if !thing.modes[:bans].any? {|ban| ban == mask}
1086
+ thing.modes[:bans].push(mask)
1087
+ end
1088
+ else
1089
+ result = thing.modes[:bans].reject! {|ban|
1090
+ if ban == mask
1091
+ true
1092
+ end
1093
+ }
1094
+
1095
+ if !result
1096
+ mask = nil
1097
+ end
1098
+ end
1099
+
1100
+ if mask
1101
+ output[:modes].push('b')
1102
+ output[:values].push(mask.to_s)
1103
+ end
1104
+ else
1105
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1106
+ end
1107
+
1108
+ when 'c'
1109
+ if Utils::checkFlag(from, :can_change_nocolors_mode)
1110
+ if Utils::checkFlag(thing, :c) == (type == '+')
1111
+ return
1112
+ end
1113
+
1114
+ Utils::setFlags(thing, :c, type == '+')
1115
+
1116
+ output[:modes].push('c')
1117
+ else
1118
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1119
+ end
1120
+
1121
+ when 'C'
1122
+ if Utils::checkFlag(from, :can_change_noctcp_mode)
1123
+ if Utils::checkFlag(thing, :C) == (type == '+')
1124
+ return
1125
+ end
1126
+
1127
+ Utils::setFlags(thing, :C, type == '+')
1128
+
1129
+ output[:modes].push('C')
1130
+ else
1131
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1132
+ end
1133
+
1134
+ when 'e'
1135
+ if Utils::checkFlag(from, :can_add_ban_exception)
1136
+ mask = Mask.parse(values.shift)
1137
+
1138
+ if type == '+'
1139
+ if !thing.modes[:exceptions].any? {|exception| exception == mask}
1140
+ thing.modes[:exceptions].push(mask)
1141
+ end
1142
+ else
1143
+ result = thing.modes[:exceptions].reject! {|exception|
1144
+ if exception == mask
1145
+ true
1146
+ end
1147
+ }
1148
+
1149
+ if !result
1150
+ mask = nil
1151
+ end
1152
+ end
1153
+
1154
+ if mask
1155
+ output[:modes].push('e')
1156
+ output[:values].push(mask.to_s)
1157
+ end
1158
+ else
1159
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1160
+ end
1161
+
1162
+ when 'h'
1163
+ if Utils::checkFlag(from, :can_give_channel_half_operator)
1164
+ value = values.shift
1165
+
1166
+ if !(user = thing.users[value])
1167
+ from.send :numeric, ERR_NOSUCHNICK, value
1168
+ return
1169
+ end
1170
+
1171
+ if Utils::checkFlag(user, :h) == (type == '+')
1172
+ return
1173
+ end
1174
+
1175
+ Utils::User::setLevel(user, :h, (type == '+'))
1176
+
1177
+ output[:modes].push('h')
1178
+ output[:values].push(value)
1179
+ else
1180
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1181
+ end
1182
+
1183
+ when 'i'
1184
+ if Utils::checkFlag(from, :can_change_invite_only_mode)
1185
+ if Utils::checkFlag(thing, :i) == (type == '+')
1186
+ return
1187
+ end
1188
+
1189
+ Utils::setFlags(thing, :i, type == '+')
1190
+
1191
+ output[:modes].push('i')
1192
+ else
1193
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1194
+ end
1195
+
1196
+ when 'I'
1197
+ if Utils::checkFlag(from, :can_add_invitation)
1198
+ mask = Mask.parse(values.shift)
1199
+
1200
+ if type == '+'
1201
+ if !thing.modes[:invites].any? {|invitation| invitation == mask}
1202
+ thing.modes[:invites].push(mask)
1203
+ end
1204
+ else
1205
+ result = thing.modes[:invites].reject! {|invitation|
1206
+ if invitation == mask
1207
+ true
1208
+ end
1209
+ }
1210
+
1211
+ if !result
1212
+ mask = nil
1213
+ end
1214
+ end
1215
+
1216
+ if mask
1217
+ output[:modes].push('I')
1218
+ output[:values].push(mask.to_s)
1219
+ end
1220
+ else
1221
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1222
+ end
1223
+
1224
+ when 'k'
1225
+ if Utils::checkFlag(from, :can_change_channel_password)
1226
+ if type == '+' && (password = values.shift)
1227
+ Utils::setFlags(thing, :k, true)
1228
+
1229
+ thing.modes[:password] = password
1230
+ else
1231
+ password = thing.modes[:password]
1232
+
1233
+ Utils::setFlags(thing, :k, false)
1234
+ end
1235
+
1236
+ if password
1237
+ output[:modes].push('k')
1238
+ output[:values].push(password)
1239
+ end
1240
+ else
1241
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1242
+ end
1243
+
1244
+ when 'K'
1245
+ if Utils::checkFlag(from, :can_change_noknock_mode)
1246
+ if Utils::checkFlag(thing, :K) == (type == '+')
1247
+ return
1248
+ end
1249
+
1250
+ Utils::setFlags(thing, :K, type == '+')
1251
+
1252
+ output[:modes].push('K')
1253
+
1254
+ else
1255
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1256
+ end
1257
+
1258
+ when 'l'
1259
+ if Utils::checkFlag(from, :can_change_limit_mode)
1260
+ if (!Utils::checkFlag(thing, :l) && type == '-') || (Utils::checkFlag(thing, :l) && type == '+')
1261
+ return
1262
+ end
1263
+
1264
+ if type == '+'
1265
+ value = values.shift
1266
+
1267
+ if !value.match(/^\d+$/)
1268
+ return
1269
+ end
1270
+
1271
+ Utils::setFlags(thing, :l, value)
1272
+
1273
+ output[:modes].push('l')
1274
+ output[:values].push(value)
1275
+ else
1276
+ Utils::setFlags(thing, :l, false)
1277
+
1278
+ output[:modes].push('l')
1279
+ end
1280
+ else
1281
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1282
+ end
1283
+
1284
+ when 'L'
1285
+ if Utils::checkFlag(from, :can_change_redirect_mode)
1286
+ if (!Utils::checkFlag(thing, :L) && type == '-') || (Utils::checkFlag(thing, :L) && type == '+')
1287
+ return
1288
+ end
1289
+
1290
+ if type == '+'
1291
+ value = values.shift
1292
+
1293
+ if !Utils::Channel::isValid(value)
1294
+ return
1295
+ end
1296
+
1297
+ Utils::setFlag(thing, :L, value)
1298
+
1299
+ output[:modes].push('L')
1300
+ output[:values].push(value)
1301
+ else
1302
+ Utils::setFlag(thing, :L, false)
1303
+
1304
+ output[:modes].push('L')
1305
+ end
1306
+ else
1307
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1308
+ end
1309
+
1310
+ when 'm'
1311
+ if Utils::checkFlag(from, :can_change_moderated_mode)
1312
+ if Utils::checkFlag(thing, :m) == (type == '+')
1313
+ return
1314
+ end
1315
+
1316
+ Utils::setFlags(thing, :m, type == '+')
1317
+
1318
+ output[:modes].push('m')
1319
+ else
1320
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1321
+ end
1322
+
1323
+ when 'n'
1324
+ if Utils::checkFlag(from, :can_change_no_external_messages_mode)
1325
+ if Utils::checkFlag(thing, :n) == (type == '+')
1326
+ return
1327
+ end
1328
+
1329
+ Utils::setFlags(thing, :n, type == '+')
1330
+
1331
+ output[:modes].push('n')
1332
+ else
1333
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1334
+ end
1335
+
1336
+ when 'N'
1337
+ if Utils::checkFlag(from, :can_change_no_nick_change_mode)
1338
+ if Utils::checkFlag(thing, :N) == (type == '+')
1339
+ return
1340
+ end
1341
+
1342
+ Utils::setFlags(thing, :N, type == '+')
1343
+
1344
+ output[:modes].push('N')
1345
+ else
1346
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1347
+ end
1348
+
1349
+ when 'o'
1350
+ if Utils::checkFlag(from, :can_give_channel_operator)
1351
+ value = values.shift
1352
+
1353
+ if !(user = thing.users[value])
1354
+ from.send :numeric, ERR_NOSUCHNICK, value
1355
+ return
1356
+ end
1357
+
1358
+ if Utils::checkFlag(user, :o) == (type == '+')
1359
+ return
1360
+ end
1361
+
1362
+ Utils::User::setLevel(user, :o, (type == '+'))
1363
+
1364
+ output[:modes].push('o')
1365
+ output[:values].push(value)
1366
+ else
1367
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1368
+ end
1369
+
1370
+ when 'Q'
1371
+ if Utils::checkFlag(from, :can_change_nokicks_mode)
1372
+ if Utils::checkFlag(thing, :Q) == (type == '+')
1373
+ return
1374
+ end
1375
+
1376
+ Utils::setFlags(thing, :Q, type == '+')
1377
+
1378
+ output[:modes].push('Q')
1379
+ else
1380
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1381
+ end
1382
+
1383
+ when 's'
1384
+ if Utils::checkFlag(from, :can_change_secret_mode)
1385
+ if Utils::checkFlag(thing, :s) == (type == '+')
1386
+ return
1387
+ end
1388
+
1389
+ Utils::setFlags(thing, :s, type == '+')
1390
+
1391
+ output[:modes].push('s')
1392
+ else
1393
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1394
+ end
1395
+
1396
+ when 'S'
1397
+ if Utils::checkFlag(from, :can_change_strip_colors_mode)
1398
+ if Utils::checkFlag(thing, :S) == (type == '+')
1399
+ return
1400
+ end
1401
+
1402
+ Utils::setFlags(thing, :S, type == '+')
1403
+
1404
+ output[:modes].push('S')
1405
+ else
1406
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1407
+ end
1408
+
1409
+ when 't'
1410
+ if Utils::checkFlag(from, :can_change_topic_mode)
1411
+ if Utils::checkFlag(thing, :t) == (type == '+')
1412
+ return
1413
+ end
1414
+
1415
+ Utils::setFlags(thing, :t, type == '+')
1416
+
1417
+ output[:modes].push('t')
1418
+ else
1419
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1420
+ end
1421
+
1422
+ when 'u'
1423
+ if Utils::checkFlag(from, :can_change_auditorium_mode)
1424
+ if Utils::checkFlag(thing, :u) == (type == '+')
1425
+ return
1426
+ end
1427
+
1428
+ Utils::setFlags(thing, :u, type == '+')
1429
+
1430
+ output[:modes].push('u')
1431
+ else
1432
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1433
+ end
1434
+
1435
+ when 'v'
1436
+ if Utils::checkFlag(from, :can_give_voice)
1437
+ value = values.shift
1438
+
1439
+ if !(user = thing.users[value])
1440
+ from.send :numeric, ERR_NOSUCHNICK, value
1441
+ return
1442
+ end
1443
+
1444
+ if Utils::checkFlag(user, :v) == (type == '+')
1445
+ return
1446
+ end
1447
+
1448
+ Utils::User::setLevel(user, :v, (type == '+'))
1449
+
1450
+ output[:modes].push('v')
1451
+ output[:values].push(value)
1452
+ else
1453
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1454
+ end
1455
+
1456
+ when 'V'
1457
+ if Utils::checkFlag(from, :can_change_noinvites_mode)
1458
+ if Utils::checkFlag(thing, :V) == (type == '+')
1459
+ return
1460
+ end
1461
+
1462
+ Utils::setFlags(thing, :V, type == '+')
1463
+
1464
+ output[:modes].push('V')
1465
+ else
1466
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1467
+ end
1468
+
1469
+ when 'x'
1470
+ if Utils::checkFlag(from, :can_give_channel_owner)
1471
+ value = values.shift
1472
+
1473
+ if !(user = thing.users[value])
1474
+ from.send :numeric, ERR_NOSUCHNICK, value
1475
+ return
1476
+ end
1477
+
1478
+ if Utils::checkFlag(user, :x) == (type == '+')
1479
+ return
1480
+ end
1481
+
1482
+ Utils::User::setLevel(user, :x, (type == '+'))
1483
+
1484
+ output[:modes].push('x')
1485
+ output[:values].push(value)
1486
+ else
1487
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1488
+ end
1489
+
1490
+ when 'y'
1491
+ if Utils::checkFlag(from, :can_give_channel_admin)
1492
+ value = values.shift
1493
+
1494
+ if !(user = thing.users[value])
1495
+ from.send :numeric, ERR_NOSUCHNICK, value
1496
+ return
1497
+ end
1498
+
1499
+ if Utils::checkFlag(user, :y) == (type == '+')
1500
+ return
1501
+ end
1502
+
1503
+ Utils::User::setLevel(user, :y, (type == '+'))
1504
+
1505
+ output[:modes].push('y')
1506
+ output[:values].push(value)
1507
+ else
1508
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1509
+ end
1510
+
1511
+ when 'z'
1512
+ if Utils::checkFlag(from, :can_change_ssl_mode)
1513
+ if Utils::checkFlag(thing, :z) == (type == '+')
1514
+ return
1515
+ end
1516
+
1517
+ if type == '+'
1518
+ ok = true
1519
+
1520
+ thing.users.each_value {|user|
1521
+ if !Utils::checkFlag(user, :ssl)
1522
+ ok = false
1523
+ break
1524
+ end
1525
+ }
1526
+
1527
+ if ok
1528
+ Utils::setFlags(thing, :z, true)
1529
+ else
1530
+ from.send :numeric, ERR_ALLMUSTUSESSL
1531
+ return
1532
+ end
1533
+ else
1534
+ Utils::setFlags(thing, :z, false)
1535
+ end
1536
+
1537
+ output[:modes].push('z')
1538
+ else
1539
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1540
+ end
1541
+ end
1542
+ elsif thing.is_a?(Server::Client)
1543
+ end
1544
+ end
1545
+
1546
+ def extended_mode (kind, from, thing, type, mode, values, output=nil)
1547
+ if kind != :extended
1548
+ return
1549
+ end
1550
+
1551
+ if thing.is_a?(Server::Channel) && !Utils::checkFlag(from, :can_change_channel_extended_modes)
1552
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.name
1553
+ return
1554
+ elsif thing.is_a?(Server::User) && !Utils::checkFlag(from, :can_change_user_extended_modes)
1555
+ from.send :numeric, ERR_CHANOPRIVSNEEDED, thing.channel.name
1556
+ return
1557
+ elsif thing.is_a?(Server::Client) && from.nick != thing.nick && !Utils::checkFlag(from, :can_change_client_extended_modes) && !Utils::checkFlag(from, :frozen)
1558
+ from.send :numeric, ERR_NOPRIVILEGES
1559
+ return
1560
+ end
1561
+
1562
+ if type == '?'
1563
+ if thing.is_a?(Server::Channel)
1564
+ name = thing.name
1565
+ elsif thing.is_a?(Server::User)
1566
+ name = "#{thing.nick}@#{thing.channel.name}"
1567
+ elsif thing.is_a?(Server::Client)
1568
+ name = thing.nick
1569
+ end
1570
+
1571
+ thing.modes[:extended].each {|key, value|
1572
+ from.server.dispatcher.execute :notice, :output, ref{:server}, ref{:from}, "#{name} #{key} = #{value}"
1573
+ }
1574
+ else
1575
+ if !mode.match(/^\w+$/)
1576
+ from.server.dispatcher.execute :error, from, "#{mode} is not a valid extended mode."
1577
+ return
1578
+ end
1579
+
1580
+ if type == '+'
1581
+ thing.modes[:extended][mode.to_sym] = values || true
1582
+ else
1583
+ thing.modes[:extended].delete(mode.to_sym)
1584
+ end
1585
+ end
1586
+ end
1587
+
1588
+ def encoding (thing, string)
1589
+ match = string.match(/ENCODING\s+(.+?)(\s+(.+))?$/i)
1590
+
1591
+ if !match
1592
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'ENCODING'
1593
+ return
1594
+ end
1595
+
1596
+ if match[2]
1597
+ nick = match[1].strip
1598
+ name = match[3].strip
1599
+ else
1600
+ nick = nil
1601
+ name = match[1].strip
1602
+ end
1603
+
1604
+ begin
1605
+ "".encode(name)
1606
+
1607
+ if nick
1608
+ if Utils::checkFlag(thing, :operator)
1609
+ if client = server.clients[nick]
1610
+ client.modes[:encoding] = name
1611
+ else
1612
+ thing.send :numeric, ERR_NOSUCHNICK, nick
1613
+ end
1614
+ else
1615
+ thing.send :numeric, ERR_NOPRIVILEGES
1616
+ end
1617
+ else
1618
+ thing.modes[:encoding] = name
1619
+ end
1620
+ rescue Encoding::ConverterNotFoundError
1621
+ server.dispatcher.execute(:error, thing, "#{name} is not a valid encoding.")
1622
+ end
1623
+ end
1624
+
1625
+ def join (thing, string)
1626
+ match = string.match(/JOIN\s+(.+?)(\s+(.+))?$/i)
1627
+
1628
+ if !match
1629
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'JOIN'
1630
+ return
1631
+ end
1632
+
1633
+ if match[1] == '0'
1634
+ thing.channels.each_value {|channel|
1635
+ server.dispatcher.execute :part, channel[thing.nick], 'Left all channels'
1636
+ }
1637
+
1638
+ return
1639
+ end
1640
+
1641
+ channels = match[1].split(/,/)
1642
+ passwords = (match[3] || '').split(/,/)
1643
+
1644
+ channels.each {|channel|
1645
+ channel.strip!
1646
+
1647
+ if !Utils::Channel::type(channel)
1648
+ channel = "##{channel}"
1649
+ end
1650
+
1651
+ if !Utils::Channel::isValid(channel)
1652
+ thing.send :numeric, ERR_BADCHANMASK, channel
1653
+ next
1654
+ end
1655
+
1656
+ jump = false
1657
+
1658
+ @semaphore.synchronize {
1659
+ if thing.channels[channel] || @joining[thing]
1660
+ jump = true
1661
+ break
1662
+ end
1663
+
1664
+ @joining[thing] = true
1665
+
1666
+ if !server.channels[channel]
1667
+ channel = server.channels[channel] = Channel.new(server, channel)
1668
+ else
1669
+ channel = server.channels[channel]
1670
+ end
1671
+ }
1672
+
1673
+ if jump
1674
+ next
1675
+ end
1676
+
1677
+ if !channel.modes[:bans]
1678
+ channel.modes[:bans] = []
1679
+ channel.modes[:exceptions] = []
1680
+ channel.modes[:invites] = []
1681
+ channel.modes[:invited] = ThreadSafeHash.new
1682
+ end
1683
+
1684
+ if channel.modes[:password]
1685
+ password = passwords.shift
1686
+ else
1687
+ password = ''
1688
+ end
1689
+
1690
+ if channel.modes[:l]
1691
+ if channel.users.length >= channel.modes[:l]
1692
+ @joining.delete(thing)
1693
+
1694
+ if channel.modes[:L]
1695
+ join thing, "JOIN #{channel.modes[:L]}"
1696
+ else
1697
+ thing.send :numeric, ERR_CHANNELISFULL, channel.name
1698
+ end
1699
+
1700
+ next
1701
+ end
1702
+ end
1703
+
1704
+ if channel.modes[:ssl_only] && !thing.modes[:ssl]
1705
+ thing.send :numeric, ERR_SSLREQUIRED, channel.name
1706
+ @joining.delete(thing)
1707
+ next
1708
+ end
1709
+
1710
+ if channel.modes[:password] && password != channel.modes[:password]
1711
+ thing.send :numeric, ERR_BADCHANNELKEY, channel.name
1712
+ @joining.delete(thing)
1713
+ next
1714
+ end
1715
+
1716
+ if channel.modes[:invite_only] && !Utils::Channel::invited?(channel, thing, true)
1717
+ thing.send :numeric, ERR_INVITEONLYCHAN, channel.name
1718
+ @joining.delete(thing)
1719
+ next
1720
+ end
1721
+
1722
+ if Utils::Channel::banned?(channel, thing) && !Utils::Channel::exception?(channel, thing) && !Utils::Channel::invited?(channel, thing)
1723
+ thing.send :numeric, ERR_BANNEDFROMCHAN, channel.name
1724
+ @joining.delete(thing)
1725
+ next
1726
+ end
1727
+
1728
+ server.dispatcher.execute(:join, thing, channel)
1729
+
1730
+ @joining.delete(thing)
1731
+ }
1732
+ end
1733
+
1734
+ def client_join (client, channel)
1735
+ empty = channel.empty?
1736
+ user = channel.add(client)
1737
+
1738
+ if empty
1739
+ handle_mode server, channel, "+o #{user.nick}", true
1740
+ else
1741
+ channel.modes[:invited].delete(client.nick)
1742
+ end
1743
+
1744
+ user.client.channels.add(channel)
1745
+
1746
+ if user.channel.modes[:anonymous]
1747
+ mask = Mask.new 'anonymous', 'anonymous', 'anonymous.'
1748
+ else
1749
+ mask = user.mask
1750
+ end
1751
+
1752
+ user.channel.send :raw, ":#{mask} JOIN :#{user.channel}"
1753
+
1754
+ if !user.channel.topic.nil?
1755
+ topic user.client, "TOPIC #{user.channel}"
1756
+ end
1757
+
1758
+ names user.client, "NAMES #{user.channel}"
1759
+ end
1760
+
1761
+ def part (thing, string)
1762
+ match = string.match(/PART\s+(.+?)(\s+:(.*))?$/i)
1763
+
1764
+ if !match
1765
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'PART'
1766
+ return
1767
+ end
1768
+
1769
+ names = match[1].split(/,/)
1770
+ message = match[3]
1771
+
1772
+ names.each {|name|
1773
+ if !Utils::Channel::type(name)
1774
+ name = "##{name}"
1775
+ end
1776
+
1777
+ channel = server.channels[name]
1778
+
1779
+ if !channel
1780
+ thing.send :numeric, ERR_NOSUCHCHANNEL, name
1781
+ elsif !thing.channels[name]
1782
+ thing.send :numeric, ERR_NOTONCHANNEL, name
1783
+ else
1784
+ server.dispatcher.execute(:part, channel.user(thing), message)
1785
+ end
1786
+ }
1787
+ end
1788
+
1789
+ def user_part (user, message)
1790
+ if user.client.modes[:quitting]
1791
+ return false
1792
+ end
1793
+
1794
+ text = eval(Utils::escapeMessage(@messages[:part]))
1795
+
1796
+ if user.channel.modes[:anonymous]
1797
+ mask = Mask.new 'anonymous', 'anonymous', 'anonymous.'
1798
+ else
1799
+ mask = user.mask
1800
+ end
1801
+
1802
+ user.channel.send :raw, ":#{mask} PART #{user.channel} :#{text}"
1803
+
1804
+ user.channel.delete(user)
1805
+ user.client.channels.delete(user.channel.name)
1806
+ end
1807
+
1808
+ def kick (thing, string)
1809
+ match = string.match(/KICK\s+(.+?)\s+(.+?)(\s+:(.*))?$/i)
1810
+
1811
+ if !match
1812
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'KICK'
1813
+ return
1814
+ end
1815
+
1816
+ channel = match[1]
1817
+ user = match[2]
1818
+ message = match[4]
1819
+
1820
+ if !Utils::Channel::isValid(channel)
1821
+ thing.send :numeric, ERR_BADCHANMASK, channel
1822
+ return
1823
+ end
1824
+
1825
+ if !server.channels[channel]
1826
+ thing.send :numeric, ERR_NOSUCHCHANNEL, channel
1827
+ return
1828
+ end
1829
+
1830
+ if !server.clients[user]
1831
+ thing.send :numeric, ERR_NOSUCHNICK, user
1832
+ return
1833
+ end
1834
+
1835
+ channel = server.channels[channel]
1836
+ user = channel[user]
1837
+
1838
+ if !user
1839
+ thing.send :numeric, ERR_NOTONCHANNEL, channel.name
1840
+ return
1841
+ end
1842
+
1843
+ if thing.channels[channel.name]
1844
+ thing = thing.channels[channel.name].user(thing)
1845
+ end
1846
+
1847
+ if Utils::checkFlag(thing, :can_kick)
1848
+ if channel.modes[:no_kicks]
1849
+ thing.send :numeric, ERR_NOKICKS
1850
+ else
1851
+ server.dispatcher.execute(:kick, thing, user, message)
1852
+ end
1853
+ else
1854
+ thing.send :numeric, ERR_CHANOPRIVSNEEDED, channel.name
1855
+ end
1856
+ end
1857
+
1858
+ def send_kick (kicker, kicked, message)
1859
+ kicked.channel.send :raw, ":#{kicker.mask} KICK #{kicked.channel} #{kicked.nick} :#{message}"
1860
+
1861
+ kicked.channel.delete(kicked)
1862
+ kicked.client.channels.delete(kicked.channel)
1863
+ end
1864
+
1865
+ def invite (thing, string)
1866
+ match = string.match(/INVITE\s+(.+?)\s+(.+?)$/i)
1867
+
1868
+ if !match
1869
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'INVITE'
1870
+ return
1871
+ end
1872
+
1873
+ nick = match[1].strip
1874
+ channel = match[2].strip
1875
+
1876
+ if !server.clients[nick]
1877
+ thing.send :numeric, ERR_NOSUCHNICK, nick
1878
+ return
1879
+ end
1880
+
1881
+ if server.channels[channel]
1882
+ requesting = server.channels[channel].user(thing) || thing
1883
+
1884
+ if !Utils::checkFlag(requesting, :can_invite) && !thing.channels[channel]
1885
+ thing.send :numeric, ERR_NOTONCHANNEL, channel
1886
+ return
1887
+ end
1888
+
1889
+ if !Utils::checkFlag(requesting, :can_invite)
1890
+ thing.send :numeric, ERR_CHANOPRIVSNEEDED, channel
1891
+ return
1892
+ end
1893
+
1894
+ if server.channels[channel].users[nick]
1895
+ thing.send :numeric, ERR_USERONCHANNEL, {
1896
+ :nick => nick,
1897
+ :channel => channel,
1898
+ }
1899
+
1900
+ return
1901
+ end
1902
+
1903
+ if server.channels[channel].modes[:no_invites]
1904
+ thing.send :numeric, ERR_NOINVITE, channel
1905
+ return false
1906
+ end
1907
+ end
1908
+
1909
+ client = server.clients[nick]
1910
+
1911
+ if client.modes[:away]
1912
+ thing.send :numeric, RPL_AWAY, client
1913
+ end
1914
+
1915
+ server.dispatcher.execute :invite, thing, client, channel
1916
+ end
1917
+
1918
+ def client_invite (from, to, channel)
1919
+ from.send :numeric, RPL_INVITING, {
1920
+ :nick => to.nick,
1921
+ :channel => channel,
1922
+ }
1923
+
1924
+ target = channel
1925
+
1926
+ if channel = server.channels[target]
1927
+ channel.modes[:invited][to.nick] = true
1928
+ server.dispatcher.execute :notice, :input, ref{:server}, ref{:channel}, "#{from.nick} invited #{to.nick} into the channel.", '@'
1929
+ end
1930
+
1931
+ to.send :raw, ":#{from.mask} INVITE #{to.nick} :#{target}"
1932
+ end
1933
+
1934
+ def knock (thing, string)
1935
+ match = string.match(/KNOCK\s+(.+?)(\s+:(.*))?$/i)
1936
+
1937
+ if !match
1938
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'KNOCK'
1939
+ return
1940
+ end
1941
+
1942
+ channel = match[1]
1943
+ message = match[3]
1944
+
1945
+ if !server.channels[channel]
1946
+ thing.send :numeric, ERR_NOKNOCK, { :channel => channel, :reason => 'Channel does not exist!' }
1947
+ return
1948
+ end
1949
+
1950
+ channel = server.channels[channel]
1951
+
1952
+ if !channel.modes[:i]
1953
+ thing.send :numeric, ERR_NOKNOCK, { :channel => channel.name, :reason => 'Channel is not invite only!' }
1954
+ return
1955
+ end
1956
+
1957
+ if channel.modes[:K]
1958
+ thing.send :numeric, ERR_NOKNOCK, { :channel => channel.name, :reason => 'No knocks are allowed! (+K)' }
1959
+ return
1960
+ end
1961
+
1962
+ server.dispatcher.execute :notice, :input, ref{:server}, ref{:channel}, "[Knock] by #{thing.mask} (#{message ? message : 'no reason specified'})", '@'
1963
+ server.dispatcher.execute :notice, :input, ref{:server}, ref{:thing}, "Knocked on #{channel.name}"
1964
+ end
1965
+
1966
+ def topic (thing, string)
1967
+ match = string.match(/TOPIC\s+(.*?)(\s+:(.*))?$/i)
1968
+
1969
+ if !match
1970
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'TOPIC'
1971
+ return
1972
+ end
1973
+
1974
+ channel = match[1].strip
1975
+
1976
+ if !server.channels[channel]
1977
+ thing.send :numeric, ERR_NOSUCHCHANNEL, channel
1978
+ return
1979
+ end
1980
+
1981
+ channel = server.channels[channel]
1982
+
1983
+ if !Utils::checkFlag(thing, :can_change_topic) && !thing.channels[channel.name] && !Utils::checkFlag(thing, :operator)
1984
+ thing.send :numeric, ERR_NOTONCHANNEL, channel
1985
+ else
1986
+ if match[2]
1987
+ topic = match[3].to_s
1988
+
1989
+ if channel.modes[:t] && !Utils::checkFlag(channel.user(thing), :can_change_topic)
1990
+ thing.send :numeric, ERR_CHANOPRIVSNEEDED, channel
1991
+ else
1992
+ server.dispatcher.execute :topic_change, channel, topic, ref{:thing}
1993
+ end
1994
+ else
1995
+ if !channel.topic
1996
+ thing.send :numeric, RPL_NOTOPIC, channel
1997
+ else
1998
+ thing.send :numeric, RPL_TOPIC, channel.topic
1999
+ thing.send :numeric, RPL_TOPICSETON, channel.topic
2000
+ end
2001
+ end
2002
+ end
2003
+ end
2004
+
2005
+ def topic_change (channel, topic, fromRef)
2006
+ channel.topic = [fromRef.value, topic]
2007
+
2008
+ channel.send :raw, ":#{channel.topic.setBy} TOPIC #{channel} :#{channel.topic}"
2009
+ end
2010
+
2011
+ def names (thing, string)
2012
+ match = string.match(/NAMES\s+(.*)$/i)
2013
+
2014
+ if !match
2015
+ thing.send :numeric, RPL_ENDOFNAMES, thing.nick
2016
+ return
2017
+ end
2018
+
2019
+ channel = match[1].strip
2020
+
2021
+ if channel = thing.channels[channel]
2022
+ users = String.new
2023
+ thing = channel.user(thing)
2024
+
2025
+ channel.users.each_value {|user|
2026
+ if channel.modes[:auditorium] && !Utils::User::isLevelEnough(user, '%') && !Utils::checkFlag(thing, :operator)
2027
+ if user.modes[:level]
2028
+ users << " #{user}"
2029
+ end
2030
+ else
2031
+ users << " #{user}"
2032
+ end
2033
+ }
2034
+
2035
+ users = users[1, users.length]
2036
+
2037
+ thing.send :numeric, RPL_NAMREPLY, {
2038
+ :channel => channel.name,
2039
+ :users => users,
2040
+ }
2041
+ end
2042
+
2043
+ thing.send :numeric, RPL_ENDOFNAMES, channel
2044
+ end
2045
+
2046
+ def list (thing, string)
2047
+ match = string.match(/LIST(\s+(.*))?$/)
2048
+
2049
+ channels = (match[2].strip || '').split(/,/)
2050
+
2051
+ thing.send :numeric, RPL_LISTSTART
2052
+
2053
+ if channels.empty?
2054
+ channels = server.channels
2055
+ else
2056
+ tmp = Channels.new(thing.server)
2057
+
2058
+ channels.each {|channel|
2059
+ if channel = server.channels[channel]
2060
+ tmp.add(channel)
2061
+ end
2062
+ }
2063
+
2064
+ channels = tmp
2065
+ end
2066
+
2067
+ channels.each_value {|channel|
2068
+ if !channel.modes[:secret] || thing.channels[channel.name]
2069
+ thing.send :numeric, RPL_LIST, channel
2070
+ end
2071
+ }
2072
+
2073
+ thing.send :numeric, RPL_LISTEND
2074
+ end
2075
+
2076
+ def who (thing, string)
2077
+ match = string.match(/WHO\s+(.*?)(\s+o)?$/i)
2078
+
2079
+ name = match[1].strip || '*'
2080
+
2081
+ if match
2082
+ op = match[2]
2083
+
2084
+ if Utils::Channel::isValid(name) && server.channels[name]
2085
+ channel = server.channels[name]
2086
+
2087
+ channel.users.each_value {|user|
2088
+ thing.send :numeric, RPL_WHOREPLY, {
2089
+ :channel => channel,
2090
+ :user => user,
2091
+ :hops => 0,
2092
+ }
2093
+ }
2094
+ else
2095
+
2096
+ end
2097
+ end
2098
+
2099
+ thing.send :numeric, RPL_ENDOFWHO, name
2100
+ end
2101
+
2102
+ def whois (thing, string)
2103
+ match = string.match(/WHOIS\s+(.+?)(\s+(.+?))?$/i)
2104
+
2105
+ if !match
2106
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'WHOIS'
2107
+ return
2108
+ end
2109
+
2110
+ names = (match[3] || match[1]).strip.split(/,/)
2111
+ server = match[3] ? match[1].strip : nil
2112
+
2113
+ names.each {|name|
2114
+ thing.server.dispatcher.execute(:whois, thing, name)
2115
+ }
2116
+ end
2117
+
2118
+ def send_whois (thing, name)
2119
+ if !server.clients[name]
2120
+ thing.send :numeric, ERR_NOSUCHNICK, name
2121
+ return
2122
+ end
2123
+
2124
+ client = server.clients[name]
2125
+
2126
+ thing.send :numeric, RPL_WHOISUSER, client
2127
+
2128
+ if !client.channels.empty?
2129
+ channels = ''
2130
+
2131
+ client.channels.each_value {|channel|
2132
+ if !channel.modes[:secret] || thing.channels[channel.name]
2133
+ channels << " #{channel.user(client).modes[:level]}#{channel.name}"
2134
+ end
2135
+ }
2136
+
2137
+ channels = channels[1, channels.length]
2138
+
2139
+ thing.send :numeric, RPL_WHOISCHANNELS, {
2140
+ :nick => client.nick,
2141
+ :channels => channels,
2142
+ }
2143
+ end
2144
+
2145
+ thing.send :numeric, RPL_WHOISSERVER, client
2146
+
2147
+ if client.modes[:ssl]
2148
+ thing.send :numeric, RPL_USINGSSL, client
2149
+ end
2150
+
2151
+ if client.modes[:away]
2152
+ thing.send :numeric, RPL_AWAY, client
2153
+ end
2154
+
2155
+ if client.modes[:message]
2156
+ thing.send :numeric, RPL_WHOISOPERATOR, client
2157
+ end
2158
+
2159
+ thing.send :numeric, RPL_WHOISIDLE, client
2160
+ thing.send :numeric, RPL_ENDOFWHOIS, client
2161
+ end
2162
+
2163
+ def whowas (thing, string)
2164
+ thing.send :raw, 'PHONE'
2165
+ end
2166
+
2167
+ def ison (thing, string)
2168
+ match = string.match(/ISON\s+(.+)$/i)
2169
+
2170
+ if !match
2171
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'ISON'
2172
+ return
2173
+ end
2174
+
2175
+ result = String.new
2176
+
2177
+ match.split(/\s+/).each {|nick|
2178
+ if server.clients[nick]
2179
+ result << " #{nick}"
2180
+ end
2181
+ }
2182
+
2183
+ result = result[1, result.length]
2184
+
2185
+ thing.send :numeric, RPL_ISON, result
2186
+ end
2187
+
2188
+ def privmsg (thing, string)
2189
+ match = string.match(/PRIVMSG\s+(.*?)(\s+:(.*))?$/i)
2190
+
2191
+ if !match
2192
+ thing.send :numeric, ERR_NORECIPIENT, 'PRIVMSG'
2193
+ return
2194
+ end
2195
+
2196
+ if !match[3]
2197
+ thing.send :numeric, ERR_NOTEXTTOSEND
2198
+ return
2199
+ end
2200
+
2201
+ receiver = match[1]
2202
+ message = match[3]
2203
+
2204
+ if Utils::Channel::isValid(receiver)
2205
+ channel = server.channels[receiver]
2206
+
2207
+ if !channel
2208
+ thing.send :numeric, ERR_NOSUCHNICK, receiver
2209
+ return
2210
+ end
2211
+
2212
+ thing = channel.user(thing) || thing
2213
+
2214
+ if channel.modes[:moderated] && !Utils::checkFlag(thing, :can_talk)
2215
+ thing.send :numeric, ERR_YOUNEEDVOICE, channel.name
2216
+ return
2217
+ end
2218
+
2219
+ if Utils::Channel::banned?(channel, thing)
2220
+ thing.send :numeric, ERR_YOUAREBANNED, channel.name
2221
+ return
2222
+ end
2223
+
2224
+ if thing.is_a?(Server::User)
2225
+ Utils::dispatchMessage(:message, thing, channel, message)
2226
+ else
2227
+ if server.channels[receiver].modes[:no_external_messages]
2228
+ thing.send :numeric, ERR_NOEXTERNALMESSAGES, channel.name
2229
+ else
2230
+ Utils::dispatchMessage(:message, thing, channel, message)
2231
+ end
2232
+ end
2233
+ else
2234
+ client = server.clients[receiver]
2235
+
2236
+ if !client
2237
+ thing.send :numeric, ERR_NOSUCHNICK, receiver
2238
+ else
2239
+ Utils::dispatchMessage(:message, thing, client, message)
2240
+ end
2241
+ end
2242
+ end
2243
+
2244
+ def handling_message (chain, fromRef, toRef, message)
2245
+ if chain != :input
2246
+ return
2247
+ end
2248
+
2249
+ from = fromRef.value
2250
+ to = toRef.value
2251
+
2252
+ if to.is_a?(Channel)
2253
+ if to.modes[:strip_colors]
2254
+ message.gsub!(/\x03((\d{1,2})?(,\d{1,2})?)?/, '')
2255
+ end
2256
+
2257
+ if to.modes[:no_colors] && message.include?("\x03")
2258
+ from.send :numeric, ERR_NOCOLORS, to.name
2259
+ return false
2260
+ end
2261
+
2262
+ to.users.each_value {|user|
2263
+ if user.client != from
2264
+ server.dispatcher.execute :message, :output, fromRef, ref{:user}, message
2265
+ end
2266
+ }
2267
+ elsif to.is_a?(Client)
2268
+ server.dispatcher.execute :message, :output, fromRef, toRef, message
2269
+ end
2270
+ end
2271
+
2272
+ def send_message (chain, fromRef, toRef, message)
2273
+ if chain != :output
2274
+ return
2275
+ end
2276
+
2277
+ from = fromRef.value
2278
+ to = toRef.value
2279
+
2280
+ if to.is_a?(Server::User)
2281
+ name = to.channel.name
2282
+
2283
+ if to.channel.modes[:anonymous]
2284
+ from = Mask.new 'anonymous', 'anonymous', 'anonymous.'
2285
+ end
2286
+ elsif to.is_a?(Server::Client)
2287
+ name = to.nick
2288
+ else
2289
+ return
2290
+ end
2291
+
2292
+ to.send :raw, ":#{from} PRIVMSG #{name} :#{message}"
2293
+ end
2294
+
2295
+ def notice (thing, string)
2296
+ match = string.match(/NOTICE\s+(.*?)\s+:(.*)$/i)
2297
+
2298
+ if !match
2299
+ return
2300
+ end
2301
+
2302
+ name = match[1]
2303
+ message = match[2]
2304
+
2305
+ if client = server.clients[name]
2306
+ Utils::dispatchMessage(:notice, thing, client, message)
2307
+ else
2308
+ if Utils::User::isLevel(name[0, 1])
2309
+ level = name[0, 1]
2310
+ channel = name[1, name.length]
2311
+ else
2312
+ level = nil
2313
+ channel = name
2314
+ end
2315
+
2316
+ if !server.channels[channel]
2317
+ # unrealircd sends an error if it can't find nick/channel, what should I do?
2318
+ return
2319
+ end
2320
+
2321
+ channel = server.channels[channel]
2322
+
2323
+ if !channel.modes[:no_external_messages] || channel.user(thing)
2324
+ Utils::dispatchMessage(:notice, thing, channel, message, level)
2325
+ end
2326
+ end
2327
+ end
2328
+
2329
+ def handling_notice (chain, fromRef, toRef, message, level=nil)
2330
+ if chain != :input
2331
+ return
2332
+ end
2333
+
2334
+ from = fromRef.value
2335
+ to = toRef.value
2336
+
2337
+ if to.is_a?(Channel)
2338
+ to.users.each_value {|user|
2339
+ if user.client != from && Utils::User::isLevelEnough(user, level)
2340
+ server.dispatcher.execute :notice, :output, fromRef, ref{:user}, message, level
2341
+ end
2342
+ }
2343
+ elsif to.is_a?(Client)
2344
+ server.dispatcher.execute :notice, :output, fromRef, toRef, message, level
2345
+ end
2346
+ end
2347
+
2348
+ def send_notice (chain, fromRef, toRef, message, level=nil)
2349
+ if chain != :output
2350
+ return
2351
+ end
2352
+
2353
+ from = fromRef.value
2354
+ to = toRef.value
2355
+
2356
+ if to.is_a?(Server::User)
2357
+ name = to.channel.name
2358
+
2359
+ if to.channel.modes[:anonymous]
2360
+ from = Mask.new 'anonymous', 'anonymous', 'anonymous.'
2361
+ end
2362
+ elsif to.is_a?(Server::Client)
2363
+ name = to.nick
2364
+ else
2365
+ return
2366
+ end
2367
+
2368
+ to.send :raw, ":#{from} NOTICE #{level}#{name} :#{message}"
2369
+ end
2370
+
2371
+ def handling_ctcp (chain, kind, fromRef, toRef, type, message, level=nil)
2372
+ if chain != :input
2373
+ return
2374
+ end
2375
+
2376
+ from = fromRef.value
2377
+ to = toRef.value
2378
+
2379
+ if to.is_a?(Channel)
2380
+ if to.modes[:no_ctcps]
2381
+ from.send :numeric, ERR_NOCTCPS, to.name
2382
+ return false
2383
+ end
2384
+
2385
+ to.users.each_value {|user|
2386
+ if user.client != from && Utils::User::isLevelEnough(user, level)
2387
+ server.dispatcher.execute :ctcp, :output, kind, fromRef, ref{:user}, type, message, level
2388
+ end
2389
+ }
2390
+ elsif to.is_a?(Client) || to.is_a?(User)
2391
+ server.dispatcher.execute :ctcp, :output, kind, fromRef, toRef, type, message, level
2392
+ end
2393
+ end
2394
+
2395
+ def send_ctcp (chain, kind, fromRef, toRef, type, message, level=nil)
2396
+ if chain != :output
2397
+ return
2398
+ end
2399
+
2400
+ from = fromRef.value
2401
+ to = toRef.value
2402
+
2403
+ if to.is_a?(Server::User)
2404
+ name = to.channel.name
2405
+
2406
+ if to.channel.modes[:anonymous]
2407
+ from = Mask.new 'anonymous', 'anonymous', 'anonymous.'
2408
+ end
2409
+ elsif to.is_a?(Server::Client)
2410
+ name = to.nick
2411
+ else
2412
+ return
2413
+ end
2414
+
2415
+ if message
2416
+ text = "#{type} #{message}"
2417
+ else
2418
+ text = type
2419
+ end
2420
+
2421
+ if kind == :message
2422
+ kind = 'PRIVMSG'
2423
+ level = ''
2424
+ elsif kind == :notice
2425
+ kind = 'NOTICE'
2426
+ end
2427
+
2428
+ if kind.is_a?(String)
2429
+ to.send :raw, ":#{from} #{kind} #{level}#{name} :\x01#{text}\x01"
2430
+ end
2431
+ end
2432
+
2433
+ def send_error (thing, message, type=nil)
2434
+ case type
2435
+ when :close
2436
+ send_error(thing, "Closing Link: #{thing.nick}[#{thing.ip}] (#{message})")
2437
+ else
2438
+ thing.send :raw, "ERROR :#{message}"
2439
+ end
2440
+ end
2441
+
2442
+ def map (thing, string)
2443
+ server.dispatcher.execute :notice, :input, ref{:server}, ref{:thing}, 'The X tells the point.'
2444
+ end
2445
+
2446
+ def version (thing, string)
2447
+ comments = eval(Utils::escapeMessage(@messages[:version]))
2448
+
2449
+ thing.send :numeric, RPL_VERSION
2450
+ end
2451
+
2452
+ def oper (thing, string)
2453
+ match = string.match(/OPER\s+(.*?)(\s+(.*?))?$/i)
2454
+
2455
+ if !match
2456
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'OPER'
2457
+ return
2458
+ end
2459
+
2460
+ password = match[3] || match[1]
2461
+ name = (match[3]) ? match[1] : nil
2462
+
2463
+ mask = thing.mask.clone
2464
+
2465
+ if name
2466
+ mask.nick = name
2467
+ end
2468
+
2469
+ server.config.elements['config/operators'].elements.each('operator') {|element|
2470
+ if mask.match(element.attributes['mask']) && password == element.attributes['password']
2471
+ element.attributes['flags'].split(/,/).each {|flag|
2472
+ Utils::setFlags(thing, flag.to_sym, true, false, true)
2473
+ }
2474
+
2475
+ thing.modes[:message] = 'is an IRC operator'
2476
+
2477
+ thing.send :numeric, RPL_YOUREOPER
2478
+ thing.send :raw, ":#{server} MODE #{thing.nick} #{thing.modes}"
2479
+ return
2480
+ end
2481
+ }
2482
+
2483
+ thing.send :numeric, ERR_NOOPERHOST
2484
+ end
2485
+
2486
+ def kill (thing, string)
2487
+ match = string.match(/KILL\s+(.*?)(\s+(:)?(.*))?$/i)
2488
+
2489
+ if !match
2490
+ thing.send :numeric, ERR_NEEDMOREPARAMS, 'KILL'
2491
+ return
2492
+ end
2493
+
2494
+ if !Utils::checkFlag(thing, :can_kill)
2495
+ thing.send :numeric, ERR_NOPRIVILEGES
2496
+ return
2497
+ end
2498
+
2499
+ nick = match[1]
2500
+ client = server.clients[nick]
2501
+ message = match[4]
2502
+
2503
+ if !client
2504
+ thing.send :numeric, ERR_NOSUCHNICK, nick
2505
+ return
2506
+ end
2507
+
2508
+ sender = thing
2509
+
2510
+ text = eval(Utils::escapeMessage(@messages[:kill]))
2511
+
2512
+ client.send :raw, ":#{client.mask} QUIT :#{text}"
2513
+
2514
+ server.kill client, text
2515
+ end
2516
+
2517
+ def quit (thing, string)
2518
+ match = /^QUIT((\s+)(:)?(.*)?)?$/i.match(string)
2519
+
2520
+ user = thing
2521
+ message = match[4] || user.nick
2522
+ text = eval(Utils::escapeMessage(@messages[:quit]))
2523
+
2524
+ server.kill(thing, text)
2525
+ end
2526
+
2527
+ def client_quit (thing, message)
2528
+ server.data[:nicks].delete(thing.nick)
2529
+
2530
+ @toPing.delete(thing.socket)
2531
+ @pingedOut.delete(thing.socket)
2532
+
2533
+ thing.channels.select {|name, channel| channel.modes[:anonymous]}.each_value {|channel|
2534
+ server.dispatcher.execute :part, channel.user(thing).clone, message
2535
+ }
2536
+
2537
+ thing.channels.unique_users.send :raw, ":#{thing.mask} QUIT :#{message}"
2538
+ end
2539
+ end
2540
+
2541
+ end
2542
+
2543
+ end
2544
+
2545
+ end