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

[View source]

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)
[View source]

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.

[View source]

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.

[View source]

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