diff --git a/compair/api/report.py b/compair/api/report.py index 8b832c3b8..bb49d4959 100644 --- a/compair/api/report.py +++ b/compair/api/report.py @@ -3,6 +3,7 @@ import time import unicodecsv as csv import re +import string from bouncer.constants import MANAGE from flask import Blueprint, current_app @@ -38,7 +39,11 @@ def name_generator(course, report_name, group_name, file_type="csv"): group_name_output = "" if group_name: group_name_output = group_name + '-' - return course.name + "-" + group_name_output + report_name + "--" + date + "." + file_type + # from https://gist.github.com/seanh/93666 + # return a file system safe filename + valid_chars = "-_.() %s%s" % (string.ascii_letters, string.digits) + filename = course.name + "-" + group_name_output + report_name + "--" + date + "." + file_type + return ''.join(char for char in filename if char in valid_chars) class ReportRootAPI(Resource): diff --git a/compair/tests/api/test_report.py b/compair/tests/api/test_report.py index b0a9b3969..5d0598479 100644 --- a/compair/tests/api/test_report.py +++ b/compair/tests/api/test_report.py @@ -484,6 +484,18 @@ def test_generate_report(self): # skip user with no comments row = next(reader) + # test file unsafe course name + with self.login(self.fixtures.instructor.username): + self.fixtures.course.name = self.fixtures.course.name + " 2016/2017" + db.session.commit() + input = { + 'group_name': None, + 'type': "participation", + 'assignment': None + } + rv = self.client.post(self.url, data=json.dumps(input), content_type='application/json') + self.assert200(rv) + def _check_participation_stat_report_heading_rows(self, heading): expected_heading = ['Assignment', 'User UUID', 'Last Name', 'First Name', 'Answer Submitted', 'Answer ID', 'Evaluations Submitted', 'Evaluations Required',