-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathapp.rb
142 lines (117 loc) · 4.17 KB
/
app.rb
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
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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
require 'sinatra'
require 'open3'
require 'digest/sha1'
require 'dalli'
require 'json'
set :challenge_paths, JSON.parse(File.read 'challenge_paths.json')["challenge_paths"]
if ENV["ENVIRONMENT"] == "heroku"
set :simplify_error_trace, true
set :enable_uglify_ruby, true
set :enable_cache, true
set :cache_adapter, Dalli::Client.new(ENV["MEMCACHIER_SERVERS"].split(","),
{username: ENV["MEMCACHIER_USERNAME"],
password: ENV["MEMCACHIER_PASSWORD"]})
set :allowed_origins, %w{http://nyan.catcyb.org}
else
simulate_heroku = false
set :simplify_error_trace, simulate_heroku
set :enable_uglify_ruby, simulate_heroku
set :enable_cache, simulate_heroku
set :cache_adapter, Dalli::Client.new('localhost:11211')
set :allowed_origins, %w{http://localhost:4567}
end
def uglify_ruby(script)
return script if !script || !settings.enable_uglify_ruby
script.split("\n").join(";") + ";"
end
set :snippet_prefix, uglify_ruby(File.read('snippet_prefix.rb'))
def allowed_origin(server_name)
if server_name
server_name = server_name.to_s.strip
return server_name if settings.allowed_origins.include?(server_name)
end
end
def eval_snippet(snippet, load_fake_root=false)
cache_key = Digest::SHA1.hexdigest(snippet)
if settings.enable_cache && cached_output = settings.cache_adapter.get(cache_key)
cached_output
else
file = Tempfile.new("mengenal-ruby-eval-#{Time.now.to_i}")
eval_output = ''
begin
file.write settings.snippet_prefix + snippet
file.rewind
prefix = load_fake_root ? "FAKE_ROOT=1 " : ""
stdin, stdout, stderr = Open3.popen3(prefix + "ruby #{file.path}")
error_message = stderr.readlines.join
error_message.gsub!(/^?\s*\/[^:]*:/, " ruby:") if settings.simplify_error_trace
eval_output += stdout.readlines.join + error_message
ensure
file.close
file.unlink
end
eval_output = eval_output.strip
settings.cache_adapter.set(cache_key, eval_output)
eval_output
end
end
def validate_snippet!(snippet)
snippet_size = snippet.bytesize
if snippet_size > 1048576
halt 400, "Ups error... Kodenya kepanjangan. Kurangin yah... Thx :)"
elsif snippet_size <= 0
halt 400, "Ups error... Kodenya kosong. Ketik sesuatu dong... Thx yah :)"
end
end
def eval_snippet!(snippet, load_fake_root=false)
validate_snippet! snippet
eval_snippet snippet, load_fake_root
end
def should_load_fake_root(challenge_path)
challenge_path.start_with?("05/") || challenge_path.start_with?("06/")
end
def generate_answer!(snippet, challenge_path)
is_correct = false
output = ""
if (answer_path = Dir["answers/#{challenge_path}*"].first)
answer_content = File.read(answer_path)
if answer_path.end_with? ".rb"
snippet += "\np #{answer_content}"
output = eval_snippet! snippet, should_load_fake_root(challenge_path)
output_lines = output.lines
is_correct = output_lines.last.strip == "true"
output = output_lines[0...-1].join.strip
else
output = eval_snippet! snippet, should_load_fake_root(challenge_path)
is_correct = output.match(/(^|\s*|\A)#{Regexp.escape answer_content}$/) != nil
end
else
output = eval_snippet! snippet, should_load_fake_root(challenge_path)
end
{ is_correct: is_correct, output: output }
end
###################
### End Points
###################
post '/' do
content_type 'text/plain'
if server_name = allowed_origin(request.env["HTTP_ORIGIN"])
headers['Access-Control-Allow-Origin'] = server_name
headers['Access-Control-Allow-Methods'] = "POST"
end
eval_snippet! params[:snippet]
end
post '/coba-ruby.json' do
content_type 'application/json'
if server_name = allowed_origin(request.env["HTTP_ORIGIN"])
headers['Access-Control-Allow-Origin'] = server_name
headers['Access-Control-Allow-Methods'] = "POST"
end
answer_hash = generate_answer! params[:snippet], params[:challenge_path]
challenge_index = settings.challenge_paths.index params[:challenge_path]
next_challenge_path = settings.challenge_paths[challenge_index+1] if challenge_index
if answer_hash[:is_correct] && next_challenge_path
answer_hash.merge!(next_challenge_path: next_challenge_path)
end
answer_hash.to_json
end