Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Index: lib/rbot/botuser.rb
- ===================================================================
- --- lib/rbot/botuser.rb (revision 1211)
- +++ lib/rbot/botuser.rb (working copy)
- @@ -9,6 +9,7 @@
- require 'singleton'
- require 'set'
- +require 'rbot/maskdb'
- # This would be a good idea if it was failproof, but the truth
- # is that other methods can indirectly modify the hash. *sigh*
- @@ -240,9 +241,18 @@
- # when modifying data
- attr_reader :data
- attr_writer :login_by_mask
- - attr_writer :autologin
- attr_writer :transient
- + def autologin=(vnew)
- + vold = @autologin
- + @autologin = vnew
- + if vold && !vnew
- + @netmasks.each { |n| Auth.manager.maskdb.remove(self, n) }
- + elsif vnew && !vold
- + @netmasks.each { |n| Auth.manager.maskdb.add(self, n) }
- + end
- + end
- +
- # Checks if the BotUser is transient
- def transient?
- @transient
- @@ -363,10 +373,13 @@
- def from_hash(h)
- @username = h[:username] if h.has_key?(:username)
- @password = h[:password] if h.has_key?(:password)
- - @netmasks = h[:netmasks] if h.has_key?(:netmasks)
- - @perm = h[:perm] if h.has_key?(:perm)
- @login_by_mask = h[:login_by_mask] if h.has_key?(:login_by_mask)
- @autologin = h[:autologin] if h.has_key?(:autologin)
- + if h.has_key?(:netmasks)
- + @netmasks = h[:netmasks]
- + @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } if @autologin
- + end
- + @perm = h[:perm] if h.has_key?(:perm)
- @data.replace(h[:data]) if h.has_key?(:data)
- end
- @@ -427,7 +440,9 @@
- # Adds a Netmask
- #
- def add_netmask(mask)
- - @netmasks << mask.to_irc_netmask
- + m = mask.to_irc_netmask
- + @netmasks << m
- + Auth.manager.maskdb.add(self, m) if self.autologin?
- end
- # Removes a Netmask
- @@ -435,26 +450,14 @@
- def delete_netmask(mask)
- m = mask.to_irc_netmask
- @netmasks.delete(m)
- + Auth.manager.maskdb.remove(self, m) if self.autologin?
- end
- - # Removes all <code>Netmask</code>s
- - #
- - def reset_netmasks
- - @netmasks = NetmaskList.new
- - end
- -
- # This method checks if BotUser has a Netmask that matches _user_
- #
- def knows?(usr)
- user = usr.to_irc_user
- - known = false
- - @netmasks.each { |n|
- - if user.matches?(n)
- - known = true
- - break
- - end
- - }
- - return known
- + [email protected] { |n| user.matches? n }
- end
- # This method gets called when User _user_ wants to log in.
- @@ -550,12 +553,6 @@
- return true
- end
- - # Resets the NetmaskList
- - def reset_netmasks
- - super
- - add_netmask("*!*@*")
- - end
- -
- # DefaultBotUser will check the default_perm after checking
- # the global ones
- # or on all channels if _chan_ is nil
- @@ -608,6 +605,7 @@
- include Singleton
- + attr_reader :maskdb
- attr_reader :everyone
- attr_reader :botowner
- attr_reader :bot
- @@ -649,10 +647,11 @@
- # resets the hashes
- def reset_hashes
- @botusers = Hash.new
- + @maskdb = NetmaskDb.new
- @allbotusers = Hash.new
- - [everyone, botowner].each { |x|
- + [everyone, botowner].each do |x|
- @allbotusers[x.username.to_sym] = x
- - }
- + end
- @transients = Set.new
- end
- @@ -740,14 +739,12 @@
- ircuser = user.to_irc_user
- debug "Trying to autologin #{ircuser}"
- return @botusers[ircuser] if @botusers.has_key?(ircuser)
- - @allbotusers.each { |n, bu|
- - debug "Checking with #{n}"
- - return bu if bu.autologin? and login(ircuser, n)
- - }
- - # Check with transient users
- - @transients.each { |bu|
- - return bu if bu.login(ircuser)
- - }
- + bu = maskdb.find(ircuser)
- + if bu
- + debug "trying #{bu}"
- + bu.login(ircuser) or raise '...what?!'
- + return bu
- + end
- # Finally, create a transient if we're set to allow it
- if @bot.config['auth.autouser']
- bu = create_transient_botuser(ircuser)
- Index: lib/rbot/maskdb.rb
- ===================================================================
- --- lib/rbot/maskdb.rb (revision 0)
- +++ lib/rbot/maskdb.rb (revision 0)
- @@ -0,0 +1,160 @@
- +module Irc
- + class NetmaskDb
- + # helper backend class: generic nested radix tree
- + class Tree
- + attr_reader :pre, :chi
- +
- + def initialize(pre = '', chi = Hash.new)
- + @pre = pre
- + @chi = chi
- + end
- +
- + def add(val, *prefs)
- + str = prefs.shift or raise 'empty prefs'
- + @pre = str if @chi.empty?
- +
- + n = 0
- + @pre.size.times do
- + break if @pre[n] != str[n]
- + n += 1
- + end
- +
- + rest = str.slice(n .. -1)
- +
- + if n != @pre.size
- + prest = @pre.slice!(n .. -1)
- + pc = prest.slice! 0
- + @chi = {pc => Tree.new(prest, @chi)}
- + end
- +
- + c = rest.slice!(0)
- +
- + if c
- + (@chi[c] ||= Tree.new).add(val, rest, *prefs)
- + else
- + if prefs.empty?
- + (@chi[''] ||= Array.new).push val
- + else
- + (@chi[''] ||= Tree.new).add(val, *prefs)
- + end
- + end
- + end
- +
- + def empty?
- + @chi.empty?
- + end
- +
- + def remove(*prefs, &block)
- + str = prefs.shift or raise 'empty prefs?'
- + return nil unless @pre.empty? or str.index(@pre) == 0
- + c = str.slice(@pre.size) || ''
- + return nil unless @chi.include? c
- + if c == ''
- + if prefs.empty?
- + @chi[c].reject!(&block)
- + else
- + @chi[c].remove(*prefs, &block)
- + end
- + else
- + @chi[c].remove(str.slice((@pre.size + 1) .. -1), *prefs, &block)
- + end
- + @chi.delete(c) if @chi[c].empty?
- +
- + if @chi.size == 1
- + k = @chi.keys.shift
- + return nil if k == ''
- + @pre << k << @chi[k].pre
- + @chi = @chi[k].chi
- + end
- + end
- +
- + def find(*prefs)
- + str = prefs.shift or raise 'empty prefs?'
- + self.find_helper(str, *prefs) + self.find_helper(str.reverse, *prefs)
- + end
- +
- + protected
- + def find_helper(*prefs)
- + str = prefs.shift or raise 'empty prefs?'
- + return [] unless @pre.empty? or str.index(@pre) == 0
- + # puts "#{self.inspect}: #{str} == #{@pre} pfx matched"
- + if [email protected]? ''
- + matches = []
- + elsif Array === @chi['']
- + matches = @chi['']
- + else
- + matches = @chi[''].find(*prefs)
- + end
- +
- + c = str.slice(@pre.size)
- +
- + more = []
- + if c and @chi.include?(c)
- + more = @chi[c].find_helper(str.slice((@pre.size + 1) .. -1), *prefs)
- + end
- + return more + matches
- + end
- + end
- +
- + # api wrapper for netmasks
- +
- + def initialize
- + @tree = Tree.new
- + end
- +
- + def cook_component(str)
- + s = (str && !str.empty?) ? str : '*'
- + l = s.index(/[\?\*]/)
- + if l
- + l2 = s.size - s.rindex(/[\?\*]/) - 1
- + if l2 > l
- + s = s.reverse
- + l = l2
- + end
- +
- + return (l > 0) ? s.slice(0 .. (l - 1)) : ''
- + else
- + return s
- + end
- + end
- +
- + def mask2keys(m)
- + [m.host, m.user, m.nick].map { |c| cook_component(c) }
- + end
- +
- + def add(user, *masks)
- + masks.each do |m|
- + debug "adding user #{user} with mask #{m}"
- + @tree.add([user, m], *mask2keys(m))
- + end
- + end
- +
- + def remove(user, mask)
- + debug "trying to remove user #{user} with mask #{mask}"
- + @tree.remove(*mask2keys(m)) do |val|
- + val[0] == user and val[1].fullform == mask.fullform
- + end
- + end
- +
- + def metric(iu, bu, mask)
- + ret = nil
- + if iu.matches? mask
- + ret = iu.fullform.length - mask.fullform.length
- + ret += 10 if bu.transient?
- + end
- + return ret
- + end
- +
- + def find(iu)
- + debug "find(#{iu.fullform})"
- + matches = @tree.find(iu.host, iu.user, iu.nick).uniq.map do |val|
- + m = metric(iu, *val)
- + m ? [val[0], m] : nil
- + end.compact.sort { |a, b| a[1] <=> a[1] }
- + debug "matches: " + (matches.map do |m|
- + "#{m[0].username}: [#{m[1]}]"
- + end.join(', '))
- + return matches.empty? ? nil : matches[0][0]
- + end
- + end
- +end
Add Comment
Please, Sign In to add comment