spam_protection.rb
上传用户:netsea168
上传日期:2022-07-22
资源大小:4652k
文件大小:3k
源码类别:

Ajax

开发平台:

Others

  1. class SpamProtection
  2.   IP_RBLS = [ 'opm.blitzed.us', 'bsb.empty.us' ]
  3.   HOST_RBLS = [ 'multi.surbl.org', 'bsb.empty.us' ]
  4.   SECOND_LEVEL = [ 'co', 'com', 'net', 'org', 'gov' ]
  5.   attr_accessor :this_blog
  6.   def initialize(a_blog)
  7.     self.this_blog = a_blog
  8.   end
  9.   def is_spam?(string)
  10.     return false unless this_blog.sp_global
  11.     return false if string.blank?
  12.     reason = catch(:hit) do
  13.       case string
  14.         when Format::IP_ADDRESS: self.scan_ip(string)
  15.         when Format::HTTP_URI: self.scan_uris(string) rescue URI::InvalidURIError
  16.         else self.scan_text(string)
  17.       end
  18.     end
  19.     if reason
  20.       logger.info("[SP] Hit: #{reason}")
  21.       return true
  22.     end
  23.   end
  24.   protected
  25.   def scan_ip(ip_address)
  26.     logger.info("[SP] Scanning IP #{ip_address}")
  27.     query_rbls(IP_RBLS, ip_address.split('.').reverse.join('.'))
  28.   end
  29.   def scan_text(string)
  30.     uri_list = string.scan(/(http://[^s"]+)/m).flatten
  31.     check_uri_count(uri_list)
  32.     scan_uris(uri_list)
  33.     return false
  34.   end
  35.   def check_uri_count(uris)
  36.     limit = this_blog.sp_url_limit
  37.     return if limit.to_i.zero?
  38.     if uris.size > limit
  39.       throw :hit, "Hard URL Limit hit: #{uris.size} > #{limit}"
  40.     end
  41.   end
  42.   def scan_uris(uris = [])
  43.     uris.each do |uri|
  44.       host = URI.parse(uri).host rescue next
  45.       return scan_ip(host) if host =~ Format::IP_ADDRESS
  46.       host_parts = host.split('.').reverse
  47.       domain = Array.new
  48.       # Check for two level TLD
  49.       (SECOND_LEVEL.include?(host_parts[1]) ? 3:2).times do
  50.         domain.unshift(host_parts.shift)
  51.       end
  52.       logger.info("[SP] Scanning domain #{domain.join('.')}")
  53.       query_rbls(HOST_RBLS, host, domain.join('.'))
  54.       logger.info("[SP] Finished domain scan #{domain.join('.')}")
  55.       return false
  56.     end
  57.   end
  58.   def query_rbls(rbls, *subdomains)
  59.     rbls.each do |rbl|
  60.       subdomains.uniq.each do |d|
  61.         begin
  62.           response = IPSocket.getaddress([d, rbl].join('.'))
  63.           if response =~ /^127.0.0./
  64.             throw :hit,
  65.               "#{rbl} positively resolved subdomain #{d} => #{response}"
  66.           end
  67.         rescue SocketError
  68.           # NXDOMAIN response => negative:  d is not in RBL
  69.         end
  70.       end
  71.     end
  72.     return false
  73.   end
  74.   def logger
  75.     @logger ||= RAILS_DEFAULT_LOGGER || Logger.new(STDOUT)
  76.   end
  77. end
  78. module ActiveRecord
  79.   module Validations
  80.     module ClassMethods
  81.       def validates_against_spamdb(*attr_names)
  82.         configuration = { :message => "blocked by SpamProtection" }
  83.         configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
  84.         validates_each(attr_names, configuration) do |record, attr_name, value|
  85.           record.errors.add(attr_name, configuration[:message]) if SpamProtection.new(record.blog).is_spam?(value)
  86.         end
  87.       end
  88.     end
  89.   end
  90. end