CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/transformer.rb
Views: 1904
1
# -*- coding: binary -*-
2
module Rex
3
4
###
5
#
6
# Transformer - more than meets the eye!
7
#
8
# This class, aside from having a kickass name, is responsible for translating
9
# object instances of one or more types into a single list instance of one or
10
# more types. This is useful for translating object instances that be can
11
# either strings or an array of strings into an array of strings, for
12
# instance. It lets you make things take a uniform structure in an abstract
13
# manner.
14
#
15
###
16
class Transformer
17
18
#
19
# Translates the object instance supplied in src_instance to an instance of
20
# dst_class. The dst_class parameter's instance must support the <<
21
# operator. An example call to this method looks something like:
22
#
23
# Transformer.transform(string, Array, [ String ], target)
24
#
25
def Transformer.transform(src_instance, dst_class, supported_classes,
26
target = nil)
27
dst_instance = dst_class.new
28
29
if (src_instance.kind_of?(Array))
30
src_instance.each { |src_inst|
31
Transformer.transform_single(src_inst, dst_instance,
32
supported_classes, target)
33
}
34
elsif (!src_instance.kind_of?(NilClass))
35
Transformer.transform_single(src_instance, dst_instance,
36
supported_classes, target)
37
end
38
39
return dst_instance
40
end
41
42
protected
43
44
#
45
# Transform a single source instance.
46
#
47
def Transformer.transform_single(src_instance, dst_instance,
48
supported_classes, target)
49
# If the src instance's class is supported, just add it to the dst
50
# instance
51
if (supported_classes.include?(src_instance.class))
52
dst_instance << src_instance
53
# If the src instance's class is an array, then we should check to see
54
# if any of the supporting classes support from_a.
55
elsif (src_instance.kind_of?(Array))
56
new_src_instance = nil
57
58
# Walk each supported class calling from_a if exported
59
supported_classes.each { |sup_class|
60
next if (sup_class.respond_to?('from_a') == false)
61
62
new_src_instance = sup_class.from_a(src_instance)
63
64
if (new_src_instance != nil)
65
dst_instance << new_src_instance
66
break
67
end
68
}
69
70
# If we don't have a valid new src instance, then we suck
71
if (new_src_instance == nil)
72
bomb_translation(src_instance, target)
73
end
74
75
# If the source instance is a string, query each of the supported
76
# classes to see if they can serialize it to their particular data
77
# type.
78
elsif (src_instance.kind_of?(String))
79
new_src_instance = nil
80
81
# Walk each supported class calling from_s if exported
82
supported_classes.each { |sup_class|
83
next if (sup_class.respond_to?('from_s') == false)
84
85
new_src_instance = sup_class.from_s(src_instance)
86
87
if (new_src_instance != nil)
88
dst_instance << new_src_instance
89
break
90
end
91
}
92
93
# If we don't have a valid new src instance, then we suck
94
if (new_src_instance == nil)
95
bomb_translation(src_instance, target)
96
end
97
# Otherwise, bomb translation
98
else
99
bomb_translation(src_instance, target)
100
end
101
end
102
103
def Transformer.bomb_translation(src_instance, target) # :nodoc:
104
error = "Invalid source class (#{src_instance.class})"
105
106
if (target != nil)
107
error += " for #{target}"
108
end
109
110
raise ArgumentError, error, caller
111
end
112
113
end
114
115
end
116
117
118