-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrack-cgi.rb
More file actions
executable file
·72 lines (62 loc) · 1.58 KB
/
rack-cgi.rb
File metadata and controls
executable file
·72 lines (62 loc) · 1.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
module Rack
class Cgi
F = ::File # Since there is a Rack::File
attr_accessor :cgi_root
attr_accessor :path
def initialize(opts={})
@cgi_root = opts[:cgi_root]
@env = ENV.to_hash
end
def response(code,body)
[code, {"Content-Type" => "text/plain",
"Content-Length" => body.size.to_s},
[body]]
end
def call(env)
@path_info = Utils.unescape(env["PATH_INFO"])
# Don't allow any tricks, I'm not sure if I should be doing
# more (or less)
if @path_info.include? ".." || @path_info.match(/\s/)
return response(403,"Forbidden\n")
end
@path = F.join(@cgi_root, @path_info)
begin
if F.file?(@path) && F.executable?(@path)
run_cgi(env)
else
raise Errno::EPERM
end
rescue SystemCallError => e
response(404, "File not found: #{@path_info}\n")
end
end
def run_cgi(env)
req = Rack::Request.new(env)
header = {}
body = []
env.each do |k,v|
ENV[k] = v if env[k].is_a? String
end
do_header = true
data = open("| #{@path}") do |fd|
fd.each_line do |l|
if do_header
if l =~ /^\s*$/
do_header = false
else
m = l.match(/^(\S+):\s*(.*\S)\s*$/)
header[m[1]] = m[2] if m
end
else
body << l
end
end
end
env.each do |k,v|
ENV[k].clear if env[k].is_a? String
end
[ 200, header, body]
end
private
end
end