Class: Rex::Proto::Http::Handler::Erb

Inherits:
Rex::Proto::Http::Handler show all
Defined in:
lib/rex/proto/http/handler/erb.rb

Overview

This class implements a handler for ERB (.rhtml) template files. This is based off the webrick handler.

Instance Attribute Summary collapse

Attributes inherited from Rex::Proto::Http::Handler

#server

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Rex::Proto::Http::Handler

#relative_resource_required?

Constructor Details

#initialize(server, root_path, opts = {}) ⇒ Erb

Initializes the ERB handler



28
29
30
31
32
33
34
35
# File 'lib/rex/proto/http/handler/erb.rb', line 28

def initialize(server, root_path, opts = {})
  super(server)

  self.root_path = root_path
  self.opts = opts

  self.opts['MimeType'] = "text/html" unless self.opts['MimeType']
end

Instance Attribute Details

#optsObject (protected)

:nodoc:



123
124
125
# File 'lib/rex/proto/http/handler/erb.rb', line 123

def opts
  @opts
end

#root_pathObject (protected)

:nodoc:



123
124
125
# File 'lib/rex/proto/http/handler/erb.rb', line 123

def root_path
  @root_path
end

Class Method Details

.relative_resource_required?Boolean

ERB handlers required a relative resource so that the full path name can be computed.

Returns:

  • (Boolean)


21
22
23
# File 'lib/rex/proto/http/handler/erb.rb', line 21

def self.relative_resource_required?
  true
end

Instance Method Details

#evaluate(erb, cli, request, response) ⇒ Object

Evaluates the ERB context in a specific binding context.



107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/rex/proto/http/handler/erb.rb', line 107

def evaluate(erb, cli, request, response)
  # If the thing that created this handler wanted us to use a callback
  # instead of the default behavior, then let's do that.
  if (opts['ErbCallback'])
    opts['ErbCallback'].call(erb, cli, request, response)
  else
    Module.new.module_eval {
      query_string = request.qstring
      meta_vars = request.meta_vars
      erb.result(binding)
    }
  end
end

#on_request(cli, req) ⇒ Object

Called when a request arrives.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/rex/proto/http/handler/erb.rb', line 40

def on_request(cli, req)
  resource = req.relative_resource

  # Make sure directory traversals aren't happening
  if (resource =~ /\.\./)
    wlog("Erb::on_request: Dangerous request performed: #{resource}",
      LogSource)
    return
  # If the request is for the root directory, use the document index file.
  elsif (resource == '/')
    resource << opts['DocumentIndex'] || 'index.rhtml'
  end

  begin
    resp = Response.new

    # Calculate the actual file path on disk.
    file_path = root_path + resource

    # Serialize the contents of the file
    data = ''

    File.open(file_path, 'rb') { |f|
      data = f.read
    }

    # Set the content-type to text/html by default.  We do this before
    # evaluation so that the script can change it.
    resp['Content-Type'] = server ? server.mime_type(resource) : 'text/html'

    # If the requested file is a ruby html file, evaluate it.
    if (File.extname(file_path) == ".rhtml")
      # Evaluate the data and set the output as the response body.
      resp.body = evaluate(ERB.new(data), cli, req, resp)
    # Otherwise, just set the body to the data that was read.
    else
      resp.body = data
    end
  rescue Errno::ENOENT
    server.send_e404(cli, req)
  rescue => e
    elog('Erb::on_request', LogSource, error: e)

    resp.code    = 500
    resp.message = "Internal Server Error"
    resp.body =
      "<html><head>" +
      "<title>Internal Server Error</title>" +
      "</head><body> " +
      "<h1>Internal Server Error</h1>" +
      "The server encountered an error:<br/><br/> <b>" + html_escape($!) + "</b><br/><br/>" +
      "Stack trace:<br/><br/>" +
      $@.map { |e| html_escape(e.to_s) }.join("<br/>") +
      "</body></html>"
  end

  # Send the response to the
  if (cli and resp)
    cli.send_response(resp)
  end

  resp
end