103 lines
2.3 KiB
Ruby
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
|