def getCourses(req): """ Returns a JSON object containing the list of available courses """ req.content_type = 'text/html' s = Session.Session(req) if s.is_new(): s.invalidate() return json.dumps({ 'errorType': websutil.ERR_AUTH, 'errorMessage': "", 'errorTrace': "" }) # Reset the timeout s.save() course_arr = [] strout = websutil.OutputString() try: clist = CourseList() for course_id in clist.course_names(): course_cfg_fname = clist.course_config(course_id) course_cfg = CourseConfig(course_cfg_fname) course_title = course_cfg.course_name() course_arr.append({'id': course_id, 'title': course_title}) except: traceback.print_exc(file=strout) return json.dumps({ 'errorType': websutil.ERR_EXCEPTION, 'errorMessage': "", 'errorTrace': strout.get() }) return json.dumps(course_arr)
def getCourses(req): """ Returns a JSON object containing the list of available courses """ req.content_type = 'text/html' s = Session.Session(req) if s.is_new(): s.invalidate() return json.dumps({'errorType':ERR_AUTH, 'errorMessage':"", 'errorTrace':""}) # Reset the timeout s.save() course_arr = [] strout = websutil.OutputString() try: clist = CourseList() for course_id in clist.course_names(): course_cfg_fname = clist.course_config(course_id) course_cfg = CourseConfig(course_cfg_fname) course_title = course_cfg.course_name() course_arr.append({'id' : course_id, 'title' : course_title}) except: traceback.print_exc(file = strout) return json.dumps({'errorType':ERR_EXCEPTION, 'errorMessage':"", 'errorTrace':strout.get()}) return json.dumps(course_arr)
def get_storagedir_contents(courseId, assignmentId, username): """Get the content of a the archive coresponding to a MD5Submission-type homework""" client = paramiko.SSHClient() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) assignments = vmcfg.assignments() storage_hostname = assignments.get(assignmentId, "AssignmentStorageHost") storage_username = assignments.get(assignmentId, "AssignmentStorageQueryUser") storage_basepath = assignments.storage_basepath(assignmentId, username) client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect( storage_hostname, username=storage_username, key_filename=vmcfg.storer_sshid(), look_for_keys=False ) cmd = "find " + storage_basepath + "/" + username + " \( ! -regex '.*/\..*' \) -type f" stdin, stdout, stderr = client.exec_command(cmd) result = [] for d in stdout.readlines(): result.append({"fileName": d}) for f in [stdin, stdout, stderr]: f.close() return json.dumps(result) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({"errorTrace": strout.get()}, indent=4) finally: client.close()
def submission_upload_info(courseId, user, assignment): """Return a string explaining the submission upload time, deadline and the late submission penalty """ vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) sbroot = vmpaths.dir_cur_submission_root(assignment, user) grade_file = paths.submission_results_grade(sbroot) sbcfg = paths.submission_config_file(sbroot) if not os.path.exists(sbcfg): return "Tema nu a fost încă trimisă" late_penalty = update_db.compute_late_penalty(assignment, user, vmcfg) ta_penalty = update_db.compute_TA_penalty(grade_file) deadline_str = vmcfg.assignments().get(assignment, 'Deadline') total_points = int(vmcfg.assignments().get(assignment, 'TotalPoints')) deadline_struct = time.strptime(vmcfg.assignments().get(assignment, 'Deadline'), penalty.DATE_FORMAT) sss = submissions.Submissions(vmpaths) upload_time_str = sss.get_upload_time_str(assignment, user) upload_time_struct = sss.get_upload_time_struct(assignment, user) # XXX hack, we should move this language = 'ro' deadline_explanation = penalty.verbose_time_difference(upload_time_struct, deadline_struct, language) ret = "" if language is 'ro': ret += "Data trimiterii temei : " + upload_time_str + "\n" ret += "Deadline temă : " + deadline_str + "\n" ret += deadline_explanation + "\n" ret += "\n" ret += "Depunctare întârziere : " + str(late_penalty) + "\n" ret += "Depunctare corectare : " + str(ta_penalty) + "\n" ret += "Total depunctări : " + str(ta_penalty + late_penalty) + "\n" ret += "-----------------------\n" ret += "Nota : " + str(total_points + ta_penalty + late_penalty) + "\n" else: # another language ret += "Submision date : " + upload_time_str + "\n" ret += "Assignment deadline : " + deadline_str + "\n" ret += deadline_explanation + "\n" ret += "\n" ret += "Penalty (late submission): " + str(late_penalty) + "\n" ret += "Penalty (grading) : " + str(ta_penalty) + "\n" ret += "Penalty (total) : " + str(ta_penalty + late_penalty) + "\n" ret += "---------------------------\n" ret += "Grade : " + str(total_points + ta_penalty + late_penalty) + "\n" ret += "\n" return ret
def getCourses(): course_arr = [] strout = websutil.OutputString() try: clist = CourseList() for course_id in clist.course_names(): course_cfg_fname = clist.course_config(course_id) course_cfg = CourseConfig(course_cfg_fname) course_title = course_cfg.course_name() course_arr.append({'id' : course_id, 'title' : course_title}) except: traceback.print_exc(file = strout) return json.dumps({'errorType':ERR_EXCEPTION, 'errorMessage':"", 'errorTrace':strout.get()}) return json.dumps(course_arr)
def getAllGrades(req, courseId): """Returns a table with all the grades of all students for a given course""" req.content_type = 'text/html' try: # XXX: DON'T DO THIS: performance degrades very much! #update_db.update_grades(courseId) vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) db_conn = sqlite3.connect(vmpaths.db_file()) assignments = vmcfg.assignments() sorted_assg = sorted(assignments, lambda x, y: int(assignments.get(x, "OrderNumber")) - int(assignments.get(y, "OrderNumber"))) grades = {} try: db_cursor = db_conn.cursor() db_cursor.execute( 'SELECT users.name, assignments.name, grades.grade ' 'FROM users, assignments, grades ' 'WHERE 1 ' 'AND users.id = grades.user_id ' 'AND assignments.id = grades.assignment_id') for row in db_cursor: user, assignment, grade = row deadline = time.strptime(vmcfg.assignments().get(assignment, 'Deadline'), DATE_FORMAT) deadtime = time.mktime(deadline) if time.time() < deadtime: continue grades.setdefault(user, {})[assignment] = grade db_cursor.close() finally: db_conn.close() ret = [] for user in sorted(grades.keys()): ret.append({'studentName' : user, 'studentId' : user, 'results' : grades.get(user)}) return json.dumps(ret) except: strout = websutil.OutputString() traceback.print_exc(file = strout) return json.dumps({'errorType' : ERR_EXCEPTION, 'errorMessage' : "", 'errorTrace' : strout.get()})
def get_user_from_auth_files(username, password): """Search all courseses for auth_files and if we can login in any course, return the login from there""" for coursecfg_fname in CourseList().course_configs(): vmpaths = paths.VmcheckerPaths( CourseConfig(coursecfg_fname).root_path()) r = get_user_from_auth_file(vmpaths, username, password) if not r is None: return r return None
def getAllGrades(req, courseId): """Returns a table with all the grades of all students for a given course""" req.content_type = 'text/html' try: # XXX: DON'T DO THIS: performance degrades very much! #update_db.update_grades(courseId) vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) db_conn = sqlite3.connect(vmpaths.db_file()) assignments = vmcfg.assignments() sorted_assg = sorted(assignments, lambda x, y: int(assignments.get(x, "OrderNumber")) - int(assignments.get(y, "OrderNumber"))) grades = {} try: db_cursor = db_conn.cursor() db_cursor.execute( 'SELECT users.name, assignments.name, grades.grade ' 'FROM users, assignments, grades ' 'WHERE 1 ' 'AND users.id = grades.user_id ' 'AND assignments.id = grades.assignment_id') for row in db_cursor: user, assignment, grade = row grades.setdefault(user, {})[assignment] = grade db_cursor.close() finally: db_conn.close() ret = [] for user in sorted(grades.keys()): ret.append({'studentName' : user, 'studentId' : user, 'results' : grades.get(user)}) return json.dumps(ret) except: strout = websutil.OutputString() traceback.print_exc(file = strout) return json.dumps({'errorType' : ERR_EXCEPTION, 'errorMessage' : "", 'errorTrace' : strout.get()})
def getAllGrades(req, courseId): """Returns a table with all the grades of all students for a given course""" req.content_type = "text/html" try: update_db.update_all(courseId) vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) db_conn = sqlite3.connect(vmpaths.db_file()) assignments = vmcfg.assignments() sorted_assg = sorted( assignments, lambda x, y: int(assignments.get(x, "OrderNumber")) - int(assignments.get(y, "OrderNumber")) ) grades = {} try: db_cursor = db_conn.cursor() db_cursor.execute( "SELECT users.name, assignments.name, grades.grade " "FROM users, assignments, grades " "WHERE 1 " "AND users.id = grades.user_id " "AND assignments.id = grades.assignment_id" ) for row in db_cursor: user, assignment, grade = row grades.setdefault(user, {})[assignment] = grade db_cursor.close() finally: db_conn.close() ret = [] for user in sorted(grades.keys()): ret.append({"studentName": user, "studentId": user, "results": grades.get(user)}) return json.dumps(ret) except: strout = websutil.OutputString() traceback.print_exc(file=strout) return json.dumps({"errorType": ERR_EXCEPTION, "errorMessage": "", "errorTrace": strout.get()})
def submission_upload_info(courseId, user, assignment): """Return a string explaining the submission upload time, deadline and the late submission penalty """ vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) sbroot = vmpaths.dir_cur_submission_root(assignment, user) grade_file = paths.submission_results_grade(sbroot) sbcfg = paths.submission_config_file(sbroot) if not os.path.exists(sbcfg): return "Tema nu a fost încă trimisă" late_penalty = update_db.compute_late_penalty(assignment, user, vmcfg) ta_penalty = update_db.compute_TA_penalty(grade_file) deadline_str = vmcfg.assignments().get(assignment, 'Deadline') total_points = int(vmcfg.assignments().get(assignment, 'TotalPoints')) deadline_struct = time.strptime( vmcfg.assignments().get(assignment, 'Deadline'), penalty.DATE_FORMAT) sss = submissions.Submissions(vmpaths) upload_time_str = sss.get_upload_time_str(assignment, user) upload_time_struct = sss.get_upload_time_struct(assignment, user) # XXX hack, we should move this language = 'ro' deadline_explanation = penalty.verbose_time_difference( upload_time_struct, deadline_struct, language) ret = "" if language is 'ro': ret += "Data trimiterii temei : " + upload_time_str + "\n" ret += "Deadline temă : " + deadline_str + "\n" ret += deadline_explanation + "\n" ret += "\n" ret += "Depunctare întârziere : " + str(late_penalty) + "\n" ret += "Depunctare corectare : " + str(ta_penalty) + "\n" ret += "Total depunctări : " + str(ta_penalty + late_penalty) + "\n" ret += "-----------------------\n" ret += "Nota : " + str(total_points + ta_penalty + late_penalty) + "\n" else: # another language ret += "Submision date : " + upload_time_str + "\n" ret += "Assignment deadline : " + deadline_str + "\n" ret += deadline_explanation + "\n" ret += "\n" ret += "Penalty (late submission): " + str(late_penalty) + "\n" ret += "Penalty (grading) : " + str(ta_penalty) + "\n" ret += "Penalty (total) : " + str(ta_penalty + late_penalty) + "\n" ret += "---------------------------\n" ret += "Grade : " + str(total_points + ta_penalty + late_penalty) + "\n" ret += "\n" return ret
def get_test_queue_contents(courseId): """Get the contents of the test queues for all testers configured in the system.""" try: vmcfg = CourseConfig(CourseList().course_config(courseId)) tstcfg = vmcfg.testers() queue_contents = [] # array of strings for tester_id in tstcfg: # connect to the tester client = paramiko.SSHClient() try: client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect( tstcfg.hostname(tester_id), username=tstcfg.login_username(tester_id), key_filename=vmcfg.storer_sshid(), look_for_keys=False, ) # run 'ls' in the queue_path and get it's output. cmd = "ls -ctgG " + tstcfg.queue_path(tester_id) stdin, stdout, stderr = client.exec_command(cmd) data = stdout.readlines() for f in [stdin, stdout, stderr]: f.close() if len(data) > 0: data = data[1:] queue_contents.append(data) finally: client.close() # print the concatenation of all 'ls' instances return json.dumps(queue_contents, indent=4) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({"errorTrace": strout.get()}, indent=4)
def get_test_queue_contents(courseId): """Get the contents of the test queues for all testers configured in the system.""" try: vmcfg = CourseConfig(CourseList().course_config(courseId)) tstcfg = vmcfg.testers() queue_contents = [] # array of strings for tester_id in tstcfg: # connect to the tester client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect(tstcfg.hostname(tester_id), username=tstcfg.login_username(tester_id), key_filename=vmcfg.storer_sshid(), look_for_keys=False) # run 'ls' in the queue_path and get it's output. cmd = 'ls -ctgG ' + tstcfg.queue_path(tester_id) stdin, stdout, stderr = client.exec_command(cmd) data = stdout.readlines() for f in [stdin, stdout, stderr]: f.close() if len(data) > 0: data = data[1:] queue_contents.append(data) finally: client.close() # print the concatenation of all 'ls' instances return json.dumps(queue_contents, indent=4) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({'errorTrace': strout.get()}, indent=4)
def get_storagedir_contents(courseId, assignmentId, username): """Get the content of a the archive coresponding to a MD5Submission-type homework""" client = paramiko.SSHClient() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) assignments = vmcfg.assignments() storage_hostname = assignments.get(assignmentId, 'AssignmentStorageHost') storage_username = assignments.get(assignmentId, 'AssignmentStorageQueryUser') storage_basepath = assignments.storage_basepath(assignmentId, username) client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect(storage_hostname, username=storage_username, key_filename=vmcfg.storer_sshid(), look_for_keys=False) cmd = "find " + storage_basepath + '/' + username + \ " \( ! -regex '.*/\..*' \) -type f" stdin, stdout, stderr = client.exec_command(cmd) result = [] for d in stdout.readlines(): result.append({'fileName': d}) for f in [stdin, stdout, stderr]: f.close() return json.dumps(result) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({'errorTrace': strout.get()}, indent=4) finally: client.close()
def getUserResultsHelper(req, courseId, assignmentId, username): # assume that the session was already checked strout = OutputString() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) except: traceback.print_exc(file=strout) return json.dumps({ 'errorType': ERR_EXCEPTION, 'errorMessage': "", 'errorTrace': strout.get() }) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) submission_dir = vmpaths.dir_cur_submission_root(assignmentId, username) r_path = paths.dir_submission_results(submission_dir) assignments = vmcfg.assignments() ignored_vmrs = assignments.ignored_vmrs(assignmentId) strout = OutputString() try: result_files = [] if os.path.isdir(r_path): update_db.update_grades(courseId, user=username, assignment=assignmentId) for fname in os.listdir(r_path): # skill all files not ending in '.vmr' if not fname.endswith('.vmr'): continue if fname in ignored_vmrs: continue f_path = os.path.join(r_path, fname) if os.path.isfile(f_path): overflow_msg = '' f_size = os.path.getsize(f_path) if f_size > MAX_VMR_FILE_SIZE: overflow_msg = '\n\n<b>File truncated! Actual size: ' + str( f_size) + ' bytes</b>\n' # decode as utf-8 and ignore any errors, because # characters will be badly encoded as json. with codecs.open(f_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read(MAX_VMR_FILE_SIZE) + overflow_msg content = xssescape(content) result_files.append({fname: content}) if len(result_files) == 0: msg = "In the meantime have a fortune cookie: <blockquote>" try: process = subprocess.Popen('/usr/games/fortune', shell=False, stdout=subprocess.PIPE) msg += process.communicate()[0] + "</blockquote>" except: msg += "Knock knock. Who's there? [Silence] </blockquote>" result_files = [{'fortune.vmr': msg}] result_files.append( {'queue-contents.vmr': get_test_queue_contents(courseId)}) if 'late-submission.vmr' not in ignored_vmrs: result_files.append({ 'late-submission.vmr': submission_upload_info(courseId, username, assignmentId) }) result_files = sortResultFiles(result_files, 'en') return json.dumps(result_files) except: traceback.print_exc(file=strout) return json.dumps({ 'errorType': ERR_EXCEPTION, 'errorMessage': "", 'errorTrace': strout.get() })
def validate_md5_submission(courseId, assignmentId, username, archiveFileName): """Checks whether a MD5Submission is valid: * checks that the uploaded md5 corresponds to the one of the machine * checks that the archive uploaded by the student is a zip file On success returns 'ok'. On failure reports the source of the failure: - 'md5' - the uploaded md5 does not match the one computed on the archive - 'zip' - the uploaded archive is not zip. """ md5_calculated = "" md5_uploaded = "" archive_file_type = "" client = paramiko.SSHClient() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) assignments = vmcfg.assignments() storage_hostname = assignments.get(assignmentId, 'AssignmentStorageHost') storage_username = assignments.get(assignmentId, 'AssignmentStorageQueryUser') storage_basepath = assignments.storage_basepath(assignmentId, username) client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect(storage_hostname, username=storage_username, key_filename=vmcfg.storer_sshid(), look_for_keys=False) archive_abs = os.path.join(storage_basepath, username, archiveFileName) # XXX: This will take ages to compute! I wonder how many # connections will Apache hold. stdin, stdout, stderr = client.exec_command("md5sum " + QuoteForPOSIX(archive_abs)) md5_calculated = stdout.readline().split()[0] for f in [stdin, stdout, stderr]: f.close() stdin, stdout, stderr = client.exec_command("file " + QuoteForPOSIX(archive_abs)) archive_file_type = stdout.readline()[len(archive_abs):].split( )[1].lower() for f in [stdin, stdout, stderr]: f.close() vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) submission_dir = vmpaths.dir_cur_submission_root( assignmentId, username) md5_fpath = paths.submission_md5_file(submission_dir) if os.path.isfile(md5_fpath): with open(md5_fpath, 'r') as f: md5_uploaded = f.read(32) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({'errorTrace': strout.get()}, indent=4) finally: client.close() if not md5_calculated == md5_uploaded: return "md5" # report the type of the problem if not archive_file_type == "zip": return "zip" # report the type of the problem return "ok" # no problemo
def getAllGrades(req, courseId): """Returns a table with all the grades of all students for a given course""" websutil.sanityCheckCourseId(courseId) req.content_type = 'text/html' # Check permission s = Session.Session(req) if s.is_new(): s.invalidate() return json.dumps({ 'errorType': websutil.ERR_AUTH, 'errorMessage': "", 'errorTrace': "" }) # Reset the timeout s.save() try: # XXX: DON'T DO THIS: performance degrades very much! #update_db.update_grades(courseId) vmcfg = CourseConfig(CourseList().course_config(courseId)) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) db_conn = sqlite3.connect(vmpaths.db_file()) assignments = vmcfg.assignments() sorted_assg = sorted( assignments, lambda x, y: int(assignments.get(x, "OrderNumber")) - int( assignments.get(y, "OrderNumber"))) grades = {} try: db_cursor = db_conn.cursor() db_cursor.execute( 'SELECT users.name, assignments.name, grades.grade ' 'FROM users, assignments, grades ' 'WHERE 1 ' 'AND users.id = grades.user_id ' 'AND assignments.id = grades.assignment_id') for row in db_cursor: user, assignment, grade = row if not vmcfg.assignments().show_grades_before_deadline( assignment): deadline = time.strptime( vmcfg.assignments().get(assignment, 'Deadline'), DATE_FORMAT) deadtime = time.mktime(deadline) if time.time() < deadtime: continue grades.setdefault(user, {})[assignment] = grade db_cursor.close() finally: db_conn.close() ret = [] for user in sorted(grades.keys()): ret.append({ 'studentName': user, 'studentId': user, 'results': grades.get(user) }) return json.dumps(ret) except: strout = websutil.OutputString() traceback.print_exc(file=strout) return json.dumps({ 'errorType': websutil.ERR_EXCEPTION, 'errorMessage': "", 'errorTrace': strout.get() })
def validate_md5_submission(courseId, assignmentId, username, archiveFileName): """Checks whether a MD5Submission is valid: * checks that the uploaded md5 corresponds to the one of the machine * checks that the archive uploaded by the student is a zip file On success returns 'ok'. On failure reports the source of the failure: - 'md5' - the uploaded md5 does not match the one computed on the archive - 'zip' - the uploaded archive is not zip. """ md5_calculated = "" md5_uploaded = "" archive_file_type = "" client = paramiko.SSHClient() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) assignments = vmcfg.assignments() storage_hostname = assignments.get(assignmentId, "AssignmentStorageHost") storage_username = assignments.get(assignmentId, "AssignmentStorageQueryUser") storage_basepath = assignments.storage_basepath(assignmentId, username) client.load_system_host_keys(vmcfg.known_hosts_file()) client.connect( storage_hostname, username=storage_username, key_filename=vmcfg.storer_sshid(), look_for_keys=False ) archive_abs = os.path.join(storage_basepath, username, archiveFileName) # XXX: This will take ages to compute! I wonder how many # connections will Apache hold. stdin, stdout, stderr = client.exec_command("md5sum " + QuoteForPOSIX(archive_abs)) md5_calculated = stdout.readline().split()[0] for f in [stdin, stdout, stderr]: f.close() stdin, stdout, stderr = client.exec_command("file " + QuoteForPOSIX(archive_abs)) archive_file_type = stdout.readline()[len(archive_abs) :].split()[1].lower() for f in [stdin, stdout, stderr]: f.close() vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) submission_dir = vmpaths.dir_cur_submission_root(assignmentId, username) md5_fpath = paths.submission_md5_file(submission_dir) if os.path.isfile(md5_fpath): with open(md5_fpath, "r") as f: md5_uploaded = f.read(32) except: strout = OutputString() traceback.print_exc(file=strout) return json.dumps({"errorTrace": strout.get()}, indent=4) finally: client.close() if not md5_calculated == md5_uploaded: return "md5" # report the type of the problem if not archive_file_type == "zip": return "zip" # report the type of the problem return "ok" # no problemo
def getUserResultsHelper(req, courseId, assignmentId, username): # assume that the session was already checked strout = OutputString() try: vmcfg = CourseConfig(CourseList().course_config(courseId)) except: traceback.print_exc(file = strout) return json.dumps({'errorType' : ERR_EXCEPTION, 'errorMessage' : "", 'errorTrace' : strout.get()}) vmpaths = paths.VmcheckerPaths(vmcfg.root_path()) submission_dir = vmpaths.dir_cur_submission_root(assignmentId, username) r_path = paths.dir_submission_results(submission_dir) assignments = vmcfg.assignments() ignored_vmrs = assignments.ignored_vmrs(assignmentId) strout = OutputString() try: result_files = [] if os.path.isdir(r_path): update_db.update_grades(courseId, user=username, assignment=assignmentId) for fname in os.listdir(r_path): # skill all files not ending in '.vmr' if not fname.endswith('.vmr'): continue if fname in ignored_vmrs: continue f_path = os.path.join(r_path, fname) if os.path.isfile(f_path): overflow_msg = '' f_size = os.path.getsize(f_path) if f_size > MAX_VMR_FILE_SIZE: overflow_msg = '\n\n<b>File truncated! Actual size: ' + str(f_size) + ' bytes</b>\n' # decode as utf-8 and ignore any errors, because # characters will be badly encoded as json. with codecs.open(f_path, 'r', encoding='utf-8', errors='ignore') as f: content = f.read(MAX_VMR_FILE_SIZE) + overflow_msg content = xssescape(content) result_files.append({fname : content}) if len(result_files) == 0: msg = "In the meantime have a fortune cookie: <blockquote>" try: process = subprocess.Popen('/usr/games/fortune', shell=False, stdout=subprocess.PIPE) msg += process.communicate()[0] + "</blockquote>" except: msg += "Knock knock. Who's there? [Silence] </blockquote>" result_files = [ {'fortune.vmr' : msg } ] result_files.append({'queue-contents.vmr' : get_test_queue_contents(courseId) }) if 'late-submission.vmr' not in ignored_vmrs: result_files.append({'late-submission.vmr' : submission_upload_info(courseId, username, assignmentId)}) result_files = sortResultFiles(result_files, 'en') return json.dumps(result_files) except: traceback.print_exc(file = strout) return json.dumps({'errorType' : ERR_EXCEPTION, 'errorMessage' : "", 'errorTrace' : strout.get()})