Land #7647, Search with an intersect instead of a union

bug/bundler_fix
wchen-r7 2016-12-02 13:55:50 -06:00
commit 7ee9408da3
No known key found for this signature in database
GPG Key ID: 2384DB4EF06F730B
1 changed files with 40 additions and 81 deletions

View File

@ -25,11 +25,7 @@ module Msf::DBManager::ModuleCache
# @param values [Set<String>, #each] a list of strings. # @param values [Set<String>, #each] a list of strings.
# @return [Arrray<String>] strings wrapped like %<string>% # @return [Arrray<String>] strings wrapped like %<string>%
def match_values(values) def match_values(values)
wrapped_values = values.collect { |value| values.collect { |value| "%#{value}%" }
"%#{value}%"
}
wrapped_values
end end
def module_to_details_hash(m) def module_to_details_hash(m)
@ -200,102 +196,65 @@ module Msf::DBManager::ModuleCache
end end
end end
query = Mdm::Module::Detail.all
ActiveRecord::Base.connection_pool.with_connection do ActiveRecord::Base.connection_pool.with_connection do
# Although AREL supports taking the union or two queries, the ActiveRecord where syntax only supports @query = Mdm::Module::Detail.all
# intersection, so creating the where clause has to be delayed until all conditions can be or'd together and
# passed to one call ot where. @archs = Set.new
union_conditions = [] @authors = Set.new
@names = Set.new
@os = Set.new
@refs = Set.new
@stances = Set.new
@text = Set.new
@types = Set.new
value_set_by_keyword.each do |keyword, value_set| value_set_by_keyword.each do |keyword, value_set|
formatted_values = match_values(value_set)
case keyword case keyword
when 'author'
formatted_values = match_values(value_set)
query = query.includes(:authors).references(:authors)
module_authors = Mdm::Module::Author.arel_table
union_conditions << module_authors[:email].matches_any(formatted_values)
union_conditions << module_authors[:name].matches_any(formatted_values)
when 'name'
formatted_values = match_values(value_set)
module_details = Mdm::Module::Detail.arel_table
union_conditions << module_details[:fullname].matches_any(formatted_values)
union_conditions << module_details[:name].matches_any(formatted_values)
when 'os', 'platform'
formatted_values = match_values(value_set)
query = query.includes(:platforms).references(:platforms)
union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values)
query = query.includes(:targets).references(:targets)
union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values)
when 'text'
formatted_values = match_values(value_set)
module_details = Mdm::Module::Detail.arel_table
union_conditions << module_details[:description].matches_any(formatted_values)
union_conditions << module_details[:fullname].matches_any(formatted_values)
union_conditions << module_details[:name].matches_any(formatted_values)
query = query.includes(:actions).references(:actions)
union_conditions << Mdm::Module::Action.arel_table[:name].matches_any(formatted_values)
query = query.includes(:archs).references(:archs)
union_conditions << Mdm::Module::Arch.arel_table[:name].matches_any(formatted_values)
query = query.includes(:authors).references(:authors)
union_conditions << Mdm::Module::Author.arel_table[:name].matches_any(formatted_values)
query = query.includes(:platforms).references(:platforms)
union_conditions << Mdm::Module::Platform.arel_table[:name].matches_any(formatted_values)
query = query.includes(:refs).references(:refs)
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values)
query = query.includes(:targets).references(:targets)
union_conditions << Mdm::Module::Target.arel_table[:name].matches_any(formatted_values)
when 'type'
formatted_values = match_values(value_set)
union_conditions << Mdm::Module::Detail.arel_table[:mtype].matches_any(formatted_values)
when 'app' when 'app'
formatted_values = value_set.collect { |value| formatted_values = value_set.collect { |value|
formatted_value = 'aggressive' formatted_value = 'aggressive'
if value == 'client' if value == 'client'
formatted_value = 'passive' formatted_value = 'passive'
end end
formatted_value formatted_value
} }
@stances << formatted_values
union_conditions << Mdm::Module::Detail.arel_table[:stance].eq_any(formatted_values) when 'arch'
@archs << formatted_values
when 'author'
@authors << formatted_values
when 'name'
@names << formatted_values
when 'os', 'platform'
@os << formatted_values
when 'ref' when 'ref'
formatted_values = match_values(value_set) @refs << formatted_values
query = query.includes(:refs).references(:refs)
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values)
when 'cve', 'bid', 'edb' when 'cve', 'bid', 'edb'
formatted_values = value_set.collect { |value| formatted_values = value_set.collect { |value|
prefix = keyword.upcase prefix = keyword.upcase
"#{prefix}-%#{value}%" "#{prefix}-%#{value}%"
} }
@refs << formatted_values
query = query.includes(:refs).references(:refs) when 'text'
union_conditions << Mdm::Module::Ref.arel_table[:name].matches_any(formatted_values) @text << formatted_values
when 'type'
@types << formatted_values
end end
end end
unioned_conditions = union_conditions.inject { |union, condition|
union.or(condition)
}
query = query.where(unioned_conditions).to_a.uniq { |m| m.fullname }
end end
query @query = @query.module_arch( @archs.to_a.flatten ) if @archs.any?
@query = @query.module_author( @authors.to_a.flatten ) if @authors.any?
@query = @query.module_name( @names.to_a.flatten ) if @names.any?
@query = @query.module_os_or_platform( @os.to_a.flatten ) if @os.any?
@query = @query.module_text( @text.to_a.flatten ) if @text.any?
@query = @query.module_type( @types.to_a.flatten ) if @types.any?
@query = @query.module_stance( @stances.to_a.flatten ) if @stances.any?
@query = @query.module_ref( @refs.to_a.flatten ) if @refs.any?
@query.uniq
end end
# Destroys the old Mdm::Module::Detail and creates a new Mdm::Module::Detail for # Destroys the old Mdm::Module::Detail and creates a new Mdm::Module::Detail for