metasploit-framework/lib/msf/core/plugin_manager.rb

103 lines
2.3 KiB
Ruby

# -*- coding: binary -*-
require 'msf/core/plugin'
module Msf
###
#
# This class manages the loading and unloading plugins. All plugins must
# implement the Plugin base class interface.
#
###
class PluginManager < Array
include Framework::Offspring
#
# The hash of path names to classes that is used during load.
#
@@path_hash = {}
#
# Check the hash using the supplied path name to see if there is already a
# class association.
#
def self.check_path_hash(path)
@@path_hash[path]
end
#
# Set the class that's associated with the supplied hash.
#
def self.set_path_hash(path, klass)
@@path_hash[path] = klass
end
#
# Initializes the plugin manager.
#
def initialize(framework)
self.framework = framework
end
#
# Loads a plugin from the supplied path and returns the instance that is
# created as a result.
#
def load(path, opts = {})
# Check to see if a plugin from this path has already been loaded
# before.
if ((klass = self.class.check_path_hash(path)) == nil)
old = Msf::Plugin.constants
require(path)
new = Msf::Plugin.constants
# No new classes added?
if ((diff = new - old).empty?)
raise RuntimeError, "No classes were loaded from #{path} in the Msf::Plugin namespace."
end
# Grab the class
klass = Msf::Plugin.const_get(diff[0])
# Cache the path to class association for future reference
self.class.set_path_hash(path, klass)
# If it's already been loaded, go ahead and try to re-load it in case
# the contents have changed.
else
Kernel.load(path + ".rb")
end
# Force unloading if already loaded
plugin = self.find { |p| p.class == klass }
unload(plugin) if plugin
# Create an instance of the plugin and let it initialize
instance = klass.create(framework, opts)
# Add it to the list of plugins
if (self.member?(instance) == false)
self.unshift(instance)
end
# Return the instance to the caller
instance
end
#
# Unloads a plugin using the instance that was returned from a previous
# call to load.
#
def unload(inst)
# If the reference count drops to zero, remove it from the list of
# loaded plugins. This will indirectly call the cleanup method on the
# plugin.
if (inst.deref == true)
delete(inst)
end
end
end
end