Class: Metasploit::Model::Spec::Template
- Extended by:
- ActiveModel::Callbacks
- Includes:
- ActiveModel::Validations::Callbacks
- Defined in:
- app/models/metasploit/model/spec/template.rb
Overview
Processes '.rb.erb' templates to create Module::Ancestor#contents that contain the same metadata as the Module::Ancestor, Module::Class, Module::Instance and associations for those contents. This ensures that when the Module::Ancestor#contents are loaded in metasploit-framework, the same metadata instances are derived from the contents ensuring idempotency of the contents and metadata parsing loop.
Direct Known Subclasses
Defined Under Namespace
Modules: Write
Constant Summary collapse
- BACKTRACE_FILE_REGEXP =
Regular expression to parse file from backtrace line
/(?<file>.*):\d+:in .*/- EXPLICIT_TRIM_MODE =
Trim mode for ERB templates so that lines using <%- -%> will be trimmed of new lines
'-'- EXTENSION =
File extension for templates.
'.rb.erb'
Instance Attribute Summary collapse
-
#destination_pathname ⇒ String
The pathname where to #write the template results.
-
#locals ⇒ Hash{Symbol => Object}
Local variables to exposed to partials.
-
#overwrite ⇒ Boolean
Whether to overwrite a pre-existing file.
-
#search_pathnames ⇒ Array<Pathname>
Pathnames to search for partials.
-
#source_relative_name ⇒ String
Name of template under #search_pathnames without EXTENSION similar to how to refer to partials.
Class Method Summary collapse
-
.root ⇒ Pathname
The root of all relative #search_pathnames.
-
.root=(root) ⇒ Pathname
Sets the #root pathname for all #search_pathnames, including those on subclasses.
Instance Method Summary collapse
-
#find_pathname(relative_path) ⇒ Pathname?
private
Finds relative_path under #search_pathnames.
-
#partial_pathname(partial_relative_path) ⇒ Pathname?
Converts the
partial_relative_pathto a real (absolute) pathname that can be passed to #result by finding the corresponding file in the #search_pathnames. -
#render(partial_relative_path, options = {}) ⇒ String?
Renders partial in templates.
-
#render_super ⇒ String?
Renders the super template of the current template by searching for the template of the same name under super #search_pathnames (those that have a higher index).
- #result(pathname, options = {}) ⇒ Object
-
#search_real_pathnames ⇒ void
private
Makes sure all #search_pathnames are real (absolute).
-
#source_pathname ⇒ Pathname?
Converts #source_relative_name to a real (absolute) pathname.
-
#write ⇒ void
Writes result of template to #destination_pathname.
Methods inherited from Base
Constructor Details
This class inherits a constructor from Metasploit::Model::Base
Instance Attribute Details
#destination_pathname ⇒ String
The pathname where to #write the template results.
29 30 31 |
# File 'app/models/metasploit/model/spec/template.rb', line 29 def destination_pathname @destination_pathname end |
#locals ⇒ Hash{Symbol => Object}
Local variables to exposed to partials.
35 36 37 |
# File 'app/models/metasploit/model/spec/template.rb', line 35 def locals @locals end |
#overwrite ⇒ Boolean
Whether to overwrite a pre-existing file.
41 42 43 |
# File 'app/models/metasploit/model/spec/template.rb', line 41 def overwrite @overwrite end |
#search_pathnames ⇒ Array<Pathname>
Pathnames to search for partials. First item is search first, etc.
47 48 49 |
# File 'app/models/metasploit/model/spec/template.rb', line 47 def search_pathnames @search_pathnames end |
#source_relative_name ⇒ String
Name of template under #search_pathnames without EXTENSION similar to how to refer to partials.
53 54 55 |
# File 'app/models/metasploit/model/spec/template.rb', line 53 def source_relative_name @source_relative_name end |
Class Method Details
.root ⇒ Pathname
The root of all relative #search_pathnames. By changing root you can use your own set of templates.
195 196 197 |
# File 'app/models/metasploit/model/spec/template.rb', line 195 def root @@root ||= Metasploit::Model.root.join('spec', 'support', 'templates', 'metasploit', 'model') end |
.root=(root) ⇒ Pathname
Sets the #root pathname for all #search_pathnames, including those on subclasses.
203 204 205 |
# File 'app/models/metasploit/model/spec/template.rb', line 203 def root=(root) @@root = root end |
Instance Method Details
#find_pathname(relative_path) ⇒ Pathname? (private)
Finds relative_path under #search_pathnames
246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'app/models/metasploit/model/spec/template.rb', line 246 def find_pathname(relative_path) found_pathname = nil search_pathnames.each do |search_pathname| real_pathname = search_pathname.join(relative_path) if real_pathname.exist? found_pathname = real_pathname break end end found_pathname end |
#partial_pathname(partial_relative_path) ⇒ Pathname?
Converts the partial_relative_path to a real (absolute) pathname that can be passed to #result by finding the
corresponding file in the #search_pathnames.
92 93 94 95 96 97 98 99 100 |
# File 'app/models/metasploit/model/spec/template.rb', line 92 def partial_pathname(partial_relative_path) partial_relative_pathname = Pathname.new(partial_relative_path) relative_directory = partial_relative_pathname.dirname raw_basename = partial_relative_pathname.basename partial_basename = "_#{raw_basename}#{EXTENSION}" relative_pathname = relative_directory.join(partial_basename) find_pathname(relative_pathname) end |
#render(partial_relative_path, options = {}) ⇒ String?
Renders partial in templates.
109 110 111 112 |
# File 'app/models/metasploit/model/spec/template.rb', line 109 def render(partial_relative_path, ={}) pathname = partial_pathname(partial_relative_path) result(pathname, ) end |
#render_super ⇒ String?
Renders the super template of the current template by searching for the template of the same name under super #search_pathnames (those that have a higher index).
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'app/models/metasploit/model/spec/template.rb', line 120 def render_super super_pathname = nil backtrace = caller match = BACKTRACE_FILE_REGEXP.match(backtrace[0]) if match real_path = match[:file] current_search_pathname_found = false relative_pathname = nil search_pathnames.each do |search_pathname| # find the current index unless current_search_pathname_found if real_path.starts_with?(search_pathname.to_path) current_search_pathname_found = true real_pathname = Pathname.new(real_path) relative_pathname = real_pathname.relative_path_from(search_pathname) end # then switch to finding the next (super) index else real_pathname = search_pathname.join(relative_pathname) if real_pathname.exist? super_pathname = real_pathname break end end end unless super_pathname raise IOError, "Couldn't find super template" end else raise RegexpError, "Can't parse file from backtrace to determine current search path" end result(super_pathname) end |
#result(pathname, options = {}) ⇒ Object
Must be an instance method
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'app/models/metasploit/model/spec/template.rb', line 165 def result(pathname, ={}) .assert_valid_keys(:locals) if pathname content = pathname.read safe_level = nil template = ERB.new content, safe_level, EXPLICIT_TRIM_MODE template.filename = pathname.to_path erb_binding = binding.dup locals = self.locals || {} result_locals = [:locals] || {} merged_locals = locals.merge(result_locals) merged_locals.each do |name, value| erb_binding.eval("#{name} = nil; lambda { |value| #{name} = value }").call(value) end # use current binding to allow templates to call {#render} and then use {#method_missing} to allow access to # locals template.result(erb_binding) else '' end end |
#search_real_pathnames ⇒ void (private)
This method returns an undefined value.
Makes sure all #search_pathnames are real (absolute). Relative pathnames are resolved against root.
264 265 266 267 268 269 270 271 272 |
# File 'app/models/metasploit/model/spec/template.rb', line 264 def search_real_pathnames search_pathnames.collect! { |search_pathname| if search_pathname.relative? self.class.root.join(search_pathname) else search_pathname end } end |
#source_pathname ⇒ Pathname?
Converts #source_relative_name to a real (absolute) pathname.
211 212 213 214 215 216 217 218 |
# File 'app/models/metasploit/model/spec/template.rb', line 211 def source_pathname unless instance_variable_defined? :@source_pathname relative_path = "#{source_relative_name}#{EXTENSION}" @source_pathname = find_pathname(relative_path) end @source_pathname end |
#write ⇒ void
This method returns an undefined value.
Writes result of template to #destination_pathname.
225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'app/models/metasploit/model/spec/template.rb', line 225 def write unless overwrite Metasploit::Model::Spec::PathnameCollision.check!(destination_pathname) end result = self.result(source_pathname) # make directory destination_pathname.parent.mkpath destination_pathname.open('wb') do |f| f.write(result) end end |