示例#1
0
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)
示例#2
0
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)
示例#3
0
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()
示例#4
0
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
示例#5
0
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)
示例#6
0
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()})
示例#7
0
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
示例#8
0
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()})
示例#9
0
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()})
示例#10
0
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
示例#11
0
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)
示例#12
0
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)
示例#13
0
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()
示例#14
0
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()
        })
示例#15
0
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
示例#16
0
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()
        })
示例#17
0
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
示例#18
0
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()})