failirc 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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