CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/http/handler/erb.rb
Views: 11766
1
# -*- coding: binary -*-
2
require 'erb'
3
include ERB::Util
4
5
module Rex
6
module Proto
7
module Http
8
9
###
10
#
11
# This class implements a handler for ERB (.rhtml) template files. This is
12
# based off the webrick handler.
13
#
14
###
15
class Handler::Erb < Handler
16
17
#
18
# ERB handlers required a relative resource so that the full path name can
19
# be computed.
20
#
21
def self.relative_resource_required?
22
true
23
end
24
25
#
26
# Initializes the ERB handler
27
#
28
def initialize(server, root_path, opts = {})
29
super(server)
30
31
self.root_path = root_path
32
self.opts = opts
33
34
self.opts['MimeType'] = "text/html" unless self.opts['MimeType']
35
end
36
37
#
38
# Called when a request arrives.
39
#
40
def on_request(cli, req)
41
resource = req.relative_resource
42
43
# Make sure directory traversals aren't happening
44
if (resource =~ /\.\./)
45
wlog("Erb::on_request: Dangerous request performed: #{resource}",
46
LogSource)
47
return
48
# If the request is for the root directory, use the document index file.
49
elsif (resource == '/')
50
resource << opts['DocumentIndex'] || 'index.rhtml'
51
end
52
53
begin
54
resp = Response.new
55
56
# Calculate the actual file path on disk.
57
file_path = root_path + resource
58
59
# Serialize the contents of the file
60
data = ''
61
62
File.open(file_path, 'rb') { |f|
63
data = f.read
64
}
65
66
# Set the content-type to text/html by default. We do this before
67
# evaluation so that the script can change it.
68
resp['Content-Type'] = server ? server.mime_type(resource) : 'text/html'
69
70
# If the requested file is a ruby html file, evaluate it.
71
if (File.extname(file_path) == ".rhtml")
72
# Evaluate the data and set the output as the response body.
73
resp.body = evaluate(ERB.new(data), cli, req, resp)
74
# Otherwise, just set the body to the data that was read.
75
else
76
resp.body = data
77
end
78
rescue Errno::ENOENT
79
server.send_e404(cli, req)
80
rescue => e
81
elog('Erb::on_request', LogSource, error: e)
82
83
resp.code = 500
84
resp.message = "Internal Server Error"
85
resp.body =
86
"<html><head>" +
87
"<title>Internal Server Error</title>" +
88
"</head><body> " +
89
"<h1>Internal Server Error</h1>" +
90
"The server encountered an error:<br/><br/> <b>" + html_escape($!) + "</b><br/><br/>" +
91
"Stack trace:<br/><br/>" +
92
$@.map { |e| html_escape(e.to_s) }.join("<br/>") +
93
"</body></html>"
94
end
95
96
# Send the response to the
97
if (cli and resp)
98
cli.send_response(resp)
99
end
100
101
resp
102
end
103
104
#
105
# Evaluates the ERB context in a specific binding context.
106
#
107
def evaluate(erb, cli, request, response)
108
# If the thing that created this handler wanted us to use a callback
109
# instead of the default behavior, then let's do that.
110
if (opts['ErbCallback'])
111
opts['ErbCallback'].call(erb, cli, request, response)
112
else
113
Module.new.module_eval {
114
query_string = request.qstring
115
meta_vars = request.meta_vars
116
erb.result(binding)
117
}
118
end
119
end
120
121
protected
122
123
attr_accessor :root_path, :opts # :nodoc:
124
125
end
126
127
end
128
end
129
end
130
131