Description:
prevents user from viewing own sources submitted to unavailable problems
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r305:a5e98b239050 - - 1 file changed: 3 inserted, 1 deleted

@@ -1,376 +1,378
1 class MainController < ApplicationController
1 class MainController < ApplicationController
2
2
3 before_filter :authenticate, :except => [:index, :login]
3 before_filter :authenticate, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
4 before_filter :check_viewability, :except => [:index, :login]
5
5
6 append_before_filter :confirm_and_update_start_time,
6 append_before_filter :confirm_and_update_start_time,
7 :except => [:index,
7 :except => [:index,
8 :login,
8 :login,
9 :confirm_contest_start]
9 :confirm_contest_start]
10
10
11 # to prevent log in box to be shown when user logged out of the
11 # to prevent log in box to be shown when user logged out of the
12 # system only in some tab
12 # system only in some tab
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
13 prepend_before_filter :reject_announcement_refresh_when_logged_out,
14 :only => [:announcements]
14 :only => [:announcements]
15
15
16 # COMMENTED OUT: filter in each action instead
16 # COMMENTED OUT: filter in each action instead
17 # before_filter :verify_time_limit, :only => [:submit]
17 # before_filter :verify_time_limit, :only => [:submit]
18
18
19 verify :method => :post, :only => [:submit],
19 verify :method => :post, :only => [:submit],
20 :redirect_to => { :action => :index }
20 :redirect_to => { :action => :index }
21
21
22 # COMMENT OUT: only need when having high load
22 # COMMENT OUT: only need when having high load
23 # caches_action :index, :login
23 # caches_action :index, :login
24
24
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
25 # NOTE: This method is not actually needed, 'config/routes.rb' has
26 # assigned action login as a default action.
26 # assigned action login as a default action.
27 def index
27 def index
28 redirect_to :action => 'login'
28 redirect_to :action => 'login'
29 end
29 end
30
30
31 def login
31 def login
32 saved_notice = flash[:notice]
32 saved_notice = flash[:notice]
33 reset_session
33 reset_session
34 flash.now[:notice] = saved_notice
34 flash.now[:notice] = saved_notice
35
35
36 # EXPERIMENT:
36 # EXPERIMENT:
37 # Hide login if in single user mode and the url does not
37 # Hide login if in single user mode and the url does not
38 # explicitly specify /login
38 # explicitly specify /login
39 #
39 #
40 # logger.info "PATH: #{request.path}"
40 # logger.info "PATH: #{request.path}"
41 # if Configuration['system.single_user_mode'] and
41 # if Configuration['system.single_user_mode'] and
42 # request.path!='/main/login'
42 # request.path!='/main/login'
43 # @hidelogin = true
43 # @hidelogin = true
44 # end
44 # end
45
45
46 @announcements = Announcement.find_for_frontpage
46 @announcements = Announcement.find_for_frontpage
47 render :action => 'login', :layout => 'empty'
47 render :action => 'login', :layout => 'empty'
48 end
48 end
49
49
50 def list
50 def list
51 prepare_list_information
51 prepare_list_information
52 end
52 end
53
53
54 def help
54 def help
55 @user = User.find(session[:user_id])
55 @user = User.find(session[:user_id])
56 end
56 end
57
57
58 def submit
58 def submit
59 user = User.find(session[:user_id])
59 user = User.find(session[:user_id])
60
60
61 @submission = Submission.new(params[:submission])
61 @submission = Submission.new(params[:submission])
62 @submission.user = user
62 @submission.user = user
63 @submission.language_id = 0
63 @submission.language_id = 0
64 if (params['file']) and (params['file']!='')
64 if (params['file']) and (params['file']!='')
65 @submission.source = params['file'].read
65 @submission.source = params['file'].read
66 @submission.source_filename = params['file'].original_filename
66 @submission.source_filename = params['file'].original_filename
67 end
67 end
68 @submission.submitted_at = Time.new.gmtime
68 @submission.submitted_at = Time.new.gmtime
69
69
70 if Configuration.time_limit_mode? and user.contest_finished?
70 if Configuration.time_limit_mode? and user.contest_finished?
71 @submission.errors.add_to_base "The contest is over."
71 @submission.errors.add_to_base "The contest is over."
72 prepare_list_information
72 prepare_list_information
73 render :action => 'list' and return
73 render :action => 'list' and return
74 end
74 end
75
75
76 if @submission.valid?
76 if @submission.valid?
77 if @submission.save == false
77 if @submission.save == false
78 flash[:notice] = 'Error saving your submission'
78 flash[:notice] = 'Error saving your submission'
79 elsif Task.create(:submission_id => @submission.id,
79 elsif Task.create(:submission_id => @submission.id,
80 :status => Task::STATUS_INQUEUE) == false
80 :status => Task::STATUS_INQUEUE) == false
81 flash[:notice] = 'Error adding your submission to task queue'
81 flash[:notice] = 'Error adding your submission to task queue'
82 end
82 end
83 else
83 else
84 prepare_list_information
84 prepare_list_information
85 render :action => 'list' and return
85 render :action => 'list' and return
86 end
86 end
87 redirect_to :action => 'list'
87 redirect_to :action => 'list'
88 end
88 end
89
89
90 def source
90 def source
91 submission = Submission.find(params[:id])
91 submission = Submission.find(params[:id])
92 - if submission.user_id == session[:user_id]
92 + if ((submission.user_id == session[:user_id]) and
93 + (submission.problem != nil) and
94 + (submission.problem.available))
93 send_data(submission.source,
95 send_data(submission.source,
94 {:filename => submission.download_filename,
96 {:filename => submission.download_filename,
95 :type => 'text/plain'})
97 :type => 'text/plain'})
96 else
98 else
97 flash[:notice] = 'Error viewing source'
99 flash[:notice] = 'Error viewing source'
98 redirect_to :action => 'list'
100 redirect_to :action => 'list'
99 end
101 end
100 end
102 end
101
103
102 def compiler_msg
104 def compiler_msg
103 @submission = Submission.find(params[:id])
105 @submission = Submission.find(params[:id])
104 if @submission.user_id == session[:user_id]
106 if @submission.user_id == session[:user_id]
105 render :action => 'compiler_msg', :layout => 'empty'
107 render :action => 'compiler_msg', :layout => 'empty'
106 else
108 else
107 flash[:notice] = 'Error viewing source'
109 flash[:notice] = 'Error viewing source'
108 redirect_to :action => 'list'
110 redirect_to :action => 'list'
109 end
111 end
110 end
112 end
111
113
112 def submission
114 def submission
113 @user = User.find(session[:user_id])
115 @user = User.find(session[:user_id])
114 @problems = @user.available_problems
116 @problems = @user.available_problems
115 if params[:id]==nil
117 if params[:id]==nil
116 @problem = nil
118 @problem = nil
117 @submissions = nil
119 @submissions = nil
118 else
120 else
119 @problem = Problem.find_by_name(params[:id])
121 @problem = Problem.find_by_name(params[:id])
120 if not @problem.available
122 if not @problem.available
121 redirect_to :action => 'list'
123 redirect_to :action => 'list'
122 flash[:notice] = 'Error: submissions for that problem are not viewable.'
124 flash[:notice] = 'Error: submissions for that problem are not viewable.'
123 return
125 return
124 end
126 end
125 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
127 @submissions = Submission.find_all_by_user_problem(@user.id, @problem.id)
126 end
128 end
127 end
129 end
128
130
129 def result
131 def result
130 if !Configuration.show_grading_result
132 if !Configuration.show_grading_result
131 redirect_to :action => 'list' and return
133 redirect_to :action => 'list' and return
132 end
134 end
133 @user = User.find(session[:user_id])
135 @user = User.find(session[:user_id])
134 @submission = Submission.find(params[:id])
136 @submission = Submission.find(params[:id])
135 if @submission.user!=@user
137 if @submission.user!=@user
136 flash[:notice] = 'You are not allowed to view result of other users.'
138 flash[:notice] = 'You are not allowed to view result of other users.'
137 redirect_to :action => 'list' and return
139 redirect_to :action => 'list' and return
138 end
140 end
139 prepare_grading_result(@submission)
141 prepare_grading_result(@submission)
140 end
142 end
141
143
142 def load_output
144 def load_output
143 if !Configuration.show_grading_result or params[:num]==nil
145 if !Configuration.show_grading_result or params[:num]==nil
144 redirect_to :action => 'list' and return
146 redirect_to :action => 'list' and return
145 end
147 end
146 @user = User.find(session[:user_id])
148 @user = User.find(session[:user_id])
147 @submission = Submission.find(params[:id])
149 @submission = Submission.find(params[:id])
148 if @submission.user!=@user
150 if @submission.user!=@user
149 flash[:notice] = 'You are not allowed to view result of other users.'
151 flash[:notice] = 'You are not allowed to view result of other users.'
150 redirect_to :action => 'list' and return
152 redirect_to :action => 'list' and return
151 end
153 end
152 case_num = params[:num].to_i
154 case_num = params[:num].to_i
153 out_filename = output_filename(@user.login,
155 out_filename = output_filename(@user.login,
154 @submission.problem.name,
156 @submission.problem.name,
155 @submission.id,
157 @submission.id,
156 case_num)
158 case_num)
157 if !FileTest.exists?(out_filename)
159 if !FileTest.exists?(out_filename)
158 flash[:notice] = 'Output not found.'
160 flash[:notice] = 'Output not found.'
159 redirect_to :action => 'list' and return
161 redirect_to :action => 'list' and return
160 end
162 end
161
163
162 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
164 if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE
163 response.headers['Content-Type'] = "application/force-download"
165 response.headers['Content-Type'] = "application/force-download"
164 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
166 response.headers['Content-Disposition'] = "attachment; filename=\"output-#{case_num}.txt\""
165 response.headers["X-Sendfile"] = out_filename
167 response.headers["X-Sendfile"] = out_filename
166 response.headers['Content-length'] = File.size(out_filename)
168 response.headers['Content-length'] = File.size(out_filename)
167 render :nothing => true
169 render :nothing => true
168 else
170 else
169 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
171 send_file out_filename, :stream => false, :filename => "output-#{case_num}.txt", :type => "text/plain"
170 end
172 end
171 end
173 end
172
174
173 def error
175 def error
174 @user = User.find(session[:user_id])
176 @user = User.find(session[:user_id])
175 end
177 end
176
178
177 # announcement refreshing and hiding methods
179 # announcement refreshing and hiding methods
178
180
179 def announcements
181 def announcements
180 if params.has_key? 'recent'
182 if params.has_key? 'recent'
181 prepare_announcements(params[:recent])
183 prepare_announcements(params[:recent])
182 else
184 else
183 prepare_announcements
185 prepare_announcements
184 end
186 end
185 render(:partial => 'announcement',
187 render(:partial => 'announcement',
186 :collection => @announcements,
188 :collection => @announcements,
187 :locals => {:announcement_effect => true})
189 :locals => {:announcement_effect => true})
188 end
190 end
189
191
190 def confirm_contest_start
192 def confirm_contest_start
191 user = User.find(session[:user_id])
193 user = User.find(session[:user_id])
192 if request.method == :post
194 if request.method == :post
193 user.update_start_time
195 user.update_start_time
194 redirect_to :action => 'list'
196 redirect_to :action => 'list'
195 else
197 else
196 @contests = user.contests
198 @contests = user.contests
197 @user = user
199 @user = user
198 end
200 end
199 end
201 end
200
202
201 protected
203 protected
202
204
203 def prepare_announcements(recent=nil)
205 def prepare_announcements(recent=nil)
204 if Configuration.show_tasks_to?(@user)
206 if Configuration.show_tasks_to?(@user)
205 @announcements = Announcement.find_published(true)
207 @announcements = Announcement.find_published(true)
206 else
208 else
207 @announcements = Announcement.find_published
209 @announcements = Announcement.find_published
208 end
210 end
209 if recent!=nil
211 if recent!=nil
210 recent_id = recent.to_i
212 recent_id = recent.to_i
211 @announcements = @announcements.find_all { |a| a.id > recent_id }
213 @announcements = @announcements.find_all { |a| a.id > recent_id }
212 end
214 end
213 end
215 end
214
216
215 def prepare_list_information
217 def prepare_list_information
216 @user = User.find(session[:user_id])
218 @user = User.find(session[:user_id])
217 if not Configuration.multicontests?
219 if not Configuration.multicontests?
218 @problems = @user.available_problems
220 @problems = @user.available_problems
219 else
221 else
220 @contest_problems = @user.available_problems_group_by_contests
222 @contest_problems = @user.available_problems_group_by_contests
221 @problems = @user.available_problems
223 @problems = @user.available_problems
222 end
224 end
223 @prob_submissions = {}
225 @prob_submissions = {}
224 @problems.each do |p|
226 @problems.each do |p|
225 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
227 sub = Submission.find_last_by_user_and_problem(@user.id,p.id)
226 if sub!=nil
228 if sub!=nil
227 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
229 @prob_submissions[p.id] = { :count => sub.number, :submission => sub }
228 else
230 else
229 @prob_submissions[p.id] = { :count => 0, :submission => nil }
231 @prob_submissions[p.id] = { :count => 0, :submission => nil }
230 end
232 end
231 end
233 end
232 prepare_announcements
234 prepare_announcements
233 end
235 end
234
236
235 def check_viewability
237 def check_viewability
236 @user = User.find(session[:user_id])
238 @user = User.find(session[:user_id])
237 if (!Configuration.show_tasks_to?(@user)) and
239 if (!Configuration.show_tasks_to?(@user)) and
238 ((action_name=='submission') or (action_name=='submit'))
240 ((action_name=='submission') or (action_name=='submit'))
239 redirect_to :action => 'list' and return
241 redirect_to :action => 'list' and return
240 end
242 end
241 end
243 end
242
244
243 def prepare_grading_result(submission)
245 def prepare_grading_result(submission)
244 if Configuration.task_grading_info.has_key? submission.problem.name
246 if Configuration.task_grading_info.has_key? submission.problem.name
245 grading_info = Configuration.task_grading_info[submission.problem.name]
247 grading_info = Configuration.task_grading_info[submission.problem.name]
246 else
248 else
247 # guess task info from problem.full_score
249 # guess task info from problem.full_score
248 cases = submission.problem.full_score / 10
250 cases = submission.problem.full_score / 10
249 grading_info = {
251 grading_info = {
250 'testruns' => cases,
252 'testruns' => cases,
251 'testcases' => cases
253 'testcases' => cases
252 }
254 }
253 end
255 end
254 @test_runs = []
256 @test_runs = []
255 if grading_info['testruns'].is_a? Integer
257 if grading_info['testruns'].is_a? Integer
256 trun_count = grading_info['testruns']
258 trun_count = grading_info['testruns']
257 trun_count.times do |i|
259 trun_count.times do |i|
258 @test_runs << [ read_grading_result(@user.login,
260 @test_runs << [ read_grading_result(@user.login,
259 submission.problem.name,
261 submission.problem.name,
260 submission.id,
262 submission.id,
261 i+1) ]
263 i+1) ]
262 end
264 end
263 else
265 else
264 grading_info['testruns'].keys.sort.each do |num|
266 grading_info['testruns'].keys.sort.each do |num|
265 run = []
267 run = []
266 testrun = grading_info['testruns'][num]
268 testrun = grading_info['testruns'][num]
267 testrun.each do |c|
269 testrun.each do |c|
268 run << read_grading_result(@user.login,
270 run << read_grading_result(@user.login,
269 submission.problem.name,
271 submission.problem.name,
270 submission.id,
272 submission.id,
271 c)
273 c)
272 end
274 end
273 @test_runs << run
275 @test_runs << run
274 end
276 end
275 end
277 end
276 end
278 end
277
279
278 def grading_result_dir(user_name, problem_name, submission_id, case_num)
280 def grading_result_dir(user_name, problem_name, submission_id, case_num)
279 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
281 return "#{GRADING_RESULT_DIR}/#{user_name}/#{problem_name}/#{submission_id}/test-result/#{case_num}"
280 end
282 end
281
283
282 def output_filename(user_name, problem_name, submission_id, case_num)
284 def output_filename(user_name, problem_name, submission_id, case_num)
283 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
285 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
284 return "#{dir}/output.txt"
286 return "#{dir}/output.txt"
285 end
287 end
286
288
287 def read_grading_result(user_name, problem_name, submission_id, case_num)
289 def read_grading_result(user_name, problem_name, submission_id, case_num)
288 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
290 dir = grading_result_dir(user_name,problem_name, submission_id, case_num)
289 result_file_name = "#{dir}/result"
291 result_file_name = "#{dir}/result"
290 if !FileTest.exists?(result_file_name)
292 if !FileTest.exists?(result_file_name)
291 return {:num => case_num, :msg => 'program did not run'}
293 return {:num => case_num, :msg => 'program did not run'}
292 else
294 else
293 results = File.open(result_file_name).readlines
295 results = File.open(result_file_name).readlines
294 run_stat = extract_running_stat(results)
296 run_stat = extract_running_stat(results)
295 output_filename = "#{dir}/output.txt"
297 output_filename = "#{dir}/output.txt"
296 if FileTest.exists?(output_filename)
298 if FileTest.exists?(output_filename)
297 output_file = true
299 output_file = true
298 output_size = File.size(output_filename)
300 output_size = File.size(output_filename)
299 else
301 else
300 output_file = false
302 output_file = false
301 output_size = 0
303 output_size = 0
302 end
304 end
303
305
304 return {
306 return {
305 :num => case_num,
307 :num => case_num,
306 :msg => results[0],
308 :msg => results[0],
307 :run_stat => run_stat,
309 :run_stat => run_stat,
308 :output => output_file,
310 :output => output_file,
309 :output_size => output_size
311 :output_size => output_size
310 }
312 }
311 end
313 end
312 end
314 end
313
315
314 # copied from grader/script/lib/test_request_helper.rb
316 # copied from grader/script/lib/test_request_helper.rb
315 def extract_running_stat(results)
317 def extract_running_stat(results)
316 running_stat_line = results[-1]
318 running_stat_line = results[-1]
317
319
318 # extract exit status line
320 # extract exit status line
319 run_stat = ""
321 run_stat = ""
320 if !(/[Cc]orrect/.match(results[0]))
322 if !(/[Cc]orrect/.match(results[0]))
321 run_stat = results[0].chomp
323 run_stat = results[0].chomp
322 else
324 else
323 run_stat = 'Program exited normally'
325 run_stat = 'Program exited normally'
324 end
326 end
325
327
326 logger.info "Stat line: #{running_stat_line}"
328 logger.info "Stat line: #{running_stat_line}"
327
329
328 # extract running time
330 # extract running time
329 if res = /r(.*)u(.*)s/.match(running_stat_line)
331 if res = /r(.*)u(.*)s/.match(running_stat_line)
330 seconds = (res[1].to_f + res[2].to_f)
332 seconds = (res[1].to_f + res[2].to_f)
331 time_stat = "Time used: #{seconds} sec."
333 time_stat = "Time used: #{seconds} sec."
332 else
334 else
333 seconds = nil
335 seconds = nil
334 time_stat = "Time used: n/a sec."
336 time_stat = "Time used: n/a sec."
335 end
337 end
336
338
337 # extract memory usage
339 # extract memory usage
338 if res = /s(.*)m/.match(running_stat_line)
340 if res = /s(.*)m/.match(running_stat_line)
339 memory_used = res[1].to_i
341 memory_used = res[1].to_i
340 else
342 else
341 memory_used = -1
343 memory_used = -1
342 end
344 end
343
345
344 return {
346 return {
345 :msg => "#{run_stat}\n#{time_stat}",
347 :msg => "#{run_stat}\n#{time_stat}",
346 :running_time => seconds,
348 :running_time => seconds,
347 :exit_status => run_stat,
349 :exit_status => run_stat,
348 :memory_usage => memory_used
350 :memory_usage => memory_used
349 }
351 }
350 end
352 end
351
353
352 def confirm_and_update_start_time
354 def confirm_and_update_start_time
353 user = User.find(session[:user_id])
355 user = User.find(session[:user_id])
354 if (Configuration.indv_contest_mode? and
356 if (Configuration.indv_contest_mode? and
355 Configuration['contest.confirm_indv_contest_start'] and
357 Configuration['contest.confirm_indv_contest_start'] and
356 !user.contest_started?)
358 !user.contest_started?)
357 redirect_to :action => 'confirm_contest_start' and return
359 redirect_to :action => 'confirm_contest_start' and return
358 end
360 end
359 user.update_start_time
361 user.update_start_time
360 end
362 end
361
363
362 def reject_announcement_refresh_when_logged_out
364 def reject_announcement_refresh_when_logged_out
363 if not session[:user_id]
365 if not session[:user_id]
364 render :text => 'Access forbidden', :status => 403
366 render :text => 'Access forbidden', :status => 403
365 end
367 end
366
368
367 if Configuration.multicontests?
369 if Configuration.multicontests?
368 user = User.find(session[:user_id])
370 user = User.find(session[:user_id])
369 if user.contest_stat.forced_logout
371 if user.contest_stat.forced_logout
370 render :text => 'Access forbidden', :status => 403
372 render :text => 'Access forbidden', :status => 403
371 end
373 end
372 end
374 end
373 end
375 end
374
376
375 end
377 end
376
378
You need to be logged in to leave comments. Login now