2005-06-04 08:15:10 +00:00
|
|
|
module Rex
|
|
|
|
|
|
|
|
###
|
|
|
|
#
|
|
|
|
# Transformer - more than meets the eye!
|
|
|
|
# -----------
|
|
|
|
#
|
|
|
|
# This class, aside from having a kickass name, is responsible for translating
|
|
|
|
# object instances of one or more types into a single list instance of one or
|
|
|
|
# more types. This is useful for translating object instances that be can
|
|
|
|
# either strings or an array of strings into an array of strings, for
|
|
|
|
# instance. It lets you make things take a uniform structure in an abstract
|
|
|
|
# manner.
|
|
|
|
#
|
|
|
|
###
|
|
|
|
class Transformer
|
|
|
|
|
|
|
|
# Translates the object instance supplied in src_instance to an instance of
|
|
|
|
# dst_class. The dst_class parameter's instance must support the <<
|
|
|
|
# operator. An example call to this method looks something like:
|
|
|
|
#
|
|
|
|
# Transformer.transform(string, Array, [ String ], target)
|
|
|
|
def Transformer.transform(src_instance, dst_class, supported_classes,
|
|
|
|
target = nil)
|
|
|
|
dst_instance = dst_class.new
|
|
|
|
|
|
|
|
if (src_instance.kind_of?(Array))
|
|
|
|
src_instance.each { |src_inst|
|
|
|
|
Transformer.transform_single(src_inst, dst_instance,
|
|
|
|
supported_classes, target)
|
|
|
|
}
|
|
|
|
elsif (!src_instance.kind_of?(NilClass))
|
|
|
|
Transformer.transform_single(src_instance, dst_instance,
|
|
|
|
supported_classes, target)
|
|
|
|
end
|
|
|
|
|
|
|
|
return dst_instance
|
|
|
|
end
|
|
|
|
|
|
|
|
protected
|
|
|
|
|
|
|
|
# Transform a single source instance.
|
|
|
|
def Transformer.transform_single(src_instance, dst_instance,
|
|
|
|
supported_classes, target)
|
|
|
|
# If the src instance's class is supported, just add it to the dst
|
|
|
|
# instance
|
|
|
|
if (supported_classes.include?(src_instance.class))
|
|
|
|
dst_instance << src_instance
|
2005-06-05 00:03:23 +00:00
|
|
|
# If the src instance's class is an array, then we should check to see
|
|
|
|
# if any of the supporting classes support from_a. If they do, we'll
|
|
|
|
# call it and try to rock that shit, otherwise we'll bomb out.
|
|
|
|
elsif (src_instance.kind_of?(Array))
|
|
|
|
new_src_instance = nil
|
|
|
|
|
|
|
|
# Walk each supported class calling from_a if exported
|
|
|
|
supported_classes.each { |sup_class|
|
|
|
|
next if (sup_class.respond_to?('from_a') == false)
|
|
|
|
|
|
|
|
new_src_instance = sup_class.from_a(src_instance)
|
|
|
|
|
|
|
|
if (new_src_instance != nil)
|
|
|
|
dst_instance << new_src_instance
|
|
|
|
break
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
# If we don't have a valid new src instance, then we suck
|
|
|
|
if (new_src_instance == nil)
|
|
|
|
bomb_translation(src_instance, target)
|
|
|
|
end
|
|
|
|
|
2005-06-04 08:15:10 +00:00
|
|
|
# If the source instance is a string, query each of the supported
|
|
|
|
# classes to see if they can serialize it to their particular data
|
|
|
|
# type.
|
|
|
|
elsif (src_instance.kind_of?(String))
|
|
|
|
new_src_instance = nil
|
|
|
|
|
|
|
|
# Walk each supported class calling from_s if exported
|
|
|
|
supported_classes.each { |sup_class|
|
2005-06-05 00:03:23 +00:00
|
|
|
next if (sup_class.respond_to?('from_s') == false)
|
|
|
|
|
2005-06-04 08:15:10 +00:00
|
|
|
new_src_instance = sup_class.from_s(src_instance)
|
|
|
|
|
|
|
|
if (new_src_instance != nil)
|
|
|
|
dst_instance << new_src_instance
|
|
|
|
break
|
|
|
|
end
|
|
|
|
}
|
|
|
|
|
|
|
|
# If we don't have a valid new src instance, then we suck
|
|
|
|
if (new_src_instance == nil)
|
|
|
|
bomb_translation(src_instance, target)
|
|
|
|
end
|
|
|
|
# Otherwise, bomb translation
|
|
|
|
else
|
|
|
|
bomb_translation(src_instance, target)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def Transformer.bomb_translation(src_instance, target)
|
|
|
|
error = "Invalid source class (#{src_instance.class})"
|
|
|
|
|
|
|
|
if (target != nil)
|
|
|
|
error += " for #{target}"
|
|
|
|
end
|
|
|
|
|
|
|
|
raise ArgumentError, error, caller
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|