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.

Defined Under Namespace

Classes: UnitTest

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



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

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

Class Method Details

.relative_resource_required?Boolean

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

Returns:

  • (Boolean)


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

def self.relative_resource_required?
	true
end

Instance Method Details

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

Evaulates the ERB context in a specific binding context.



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

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.



39
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
# File 'lib/rex/proto/http/handler/erb.rb', line 39

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
		elog("Erb::on_request: #{$!}\n#{$@.join("\n")}", LogSource)

		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