diff --git a/app/controllers/tasks_controller.rb b/app/controllers/tasks_controller.rb --- a/app/controllers/tasks_controller.rb +++ b/app/controllers/tasks_controller.rb @@ -8,22 +8,45 @@ def list @problems = Problem.find_available_problems - @user = User.find(session[:user_id]) end + # this has contest-wide access control def view base_name = params[:file] - if !check_user_viewability(base_name) + base_filename = File.basename("#{base_name}.#{params[:ext]}") + filename = "#{Problem.download_file_basedir}/#{base_filename}" + + if !FileTest.exists?(filename) redirect_to :action => 'index' and return end - base_filename = File.basename("#{base_name}.#{params[:ext]}") - filename = "#{Problem.download_file_basedir}/#{base_filename}" + send_file_to_user(filename, base_filename) + end - if !check_user_viewability(base_name) or !FileTest.exists?(filename) + # this has problem-level access control + def download + problem = Problem.find(params[:id]) + if !problem or !problem.available or !@user.can_view_problem? problem redirect_to :action => 'index' and return end + base_name = params[:file] + base_filename = File.basename("#{base_name}.#{params[:ext]}") + filename = "#{Problem.download_file_basedir}/#{params[:id]}/#{base_filename}" + puts "SENDING: #{filename}" + + if !FileTest.exists?(filename) + redirect_to :action => 'index' and return + end + + puts "SENDING: #{filename}" + + send_file_to_user(filename, base_filename) + end + + protected + + def send_file_to_user(filename, base_filename) if defined?(USE_APACHE_XSENDFILE) and USE_APACHE_XSENDFILE response.headers['Content-Type'] = "application/force-download" response.headers['Content-Disposition'] = "attachment; filename=\"#{File.basename(filename)}\"" @@ -41,8 +64,6 @@ end end - protected - def check_viewability @user = User.find(session[:user_id]) if @user==nil or !Configuration.show_tasks_to?(@user) @@ -51,10 +72,4 @@ end end - def check_user_viewability(filename) - # individual file access control shall be added here - return false if not @user - return Configuration.show_tasks_to?(@user) - end - end diff --git a/app/helpers/main_helper.rb b/app/helpers/main_helper.rb --- a/app/helpers/main_helper.rb +++ b/app/helpers/main_helper.rb @@ -6,7 +6,8 @@ elsif !problem.description_filename.blank? basename, ext = problem.description_filename.split('.') options[:controller] = 'tasks' - options[:action] = 'view' + options[:action] = 'download' + options[:id] = problem.id options[:file] = basename options[:ext] = ext return link_to name, options diff --git a/app/models/user.rb b/app/models/user.rb --- a/app/models/user.rb +++ b/app/models/user.rb @@ -182,6 +182,29 @@ end end + def problem_in_user_contests?(problem) + problem_contests = problem.contests.all + + if problem_contests.length == 0 # this is public contest + return true + end + + contests.each do |contest| + if problem_contests.find {|c| c.id == contest.id } + return true + end + end + return false + end + + def can_view_problem?(problem) + if not Configuration.multicontests? + return problem.available + else + return problem_in_user_contests? problem + end + end + protected def encrypt_new_password return if password.blank? diff --git a/config/routes.rb b/config/routes.rb --- a/config/routes.rb +++ b/config/routes.rb @@ -23,6 +23,7 @@ map.connect ':controller/service.wsdl', :action => 'wsdl' map.connect 'tasks/view/:file.:ext', :controller => 'tasks', :action => 'view' + map.connect 'tasks/download/:id/:file.:ext', :controller => 'tasks', :action => 'download' # Install the default route as the lowest priority. map.connect ':controller/:action/:id.:format' diff --git a/lib/testdata_importer.rb b/lib/testdata_importer.rb --- a/lib/testdata_importer.rb +++ b/lib/testdata_importer.rb @@ -51,10 +51,15 @@ ext = TestdataImporter.long_ext(tempfile.original_filename) extract_dir = File.join(GraderScript.raw_dir, @problem.name) - begin - Dir.mkdir extract_dir - rescue Errno::EEXIST + if File.exists? extract_dir + backup_count = 0 + begin + backup_count += 1 + backup_dirname = "#{extract_dir}.backup.#{backup_count}" + end while File.exists? backup_dirname + File.rename(extract_dir, backup_dirname) end + Dir.mkdir extract_dir if ext=='.tar.gz' or ext=='.tgz' cmd = "tar -zxvf #{testdata_filename} -C #{extract_dir}" @@ -138,9 +143,23 @@ def import_problem_pdf(dirname) pdf_files = Dir["#{dirname}/*.pdf"] + puts "CHECKING... #{dirname}" if pdf_files.length != 0 + puts "HAS PDF FILE" filename = pdf_files[0] - out_filename = "#{Problem.download_file_basedir}/#{@problem.name}.pdf" + + @problem.save if not @problem.id + out_dirname = "#{Problem.download_file_basedir}/#{@problem.id}" + if not FileTest.exists? out_dirname + Dir.mkdir out_dirname + end + + out_filename = "#{out_dirname}/#{@problem.name}.pdf" + + if FileTest.exists? out_filename + File.delete out_filename + end + File.rename(filename, out_filename) @problem.description_filename = "#{@problem.name}.pdf" @problem.save