コード例 #1
0
ファイル: GoalsParser.py プロジェクト: lukixx3/Labtainers
def ValidateTag(parameter_list, studentdir, goal_type, inputtag, allowed_special_answer, logger):
    # if allowed_special_answer is true, then allow 'answer=<string>'
    # UNLESS if the goal_type is matchacross
    returntag = ""
    if '=' in inputtag:
        if not allowed_special_answer:
            logger.error("goals.config only answertag is allowed answer=<string>, resulttag (%s) is not" % inputtag)
            sys.exit(1)
        if goal_type == "matchacross":
            logger.error("goals.config answer=<string> and goal_type==matchacross is not allowed")
            sys.exit(1)
        (target, finaltag) = inputtag.split('=')
        returntag = getTagValue(parameter_list, target, finaltag, logger)
 
    elif inputtag.startswith('(') and inputtag.endswith(')'):
        returntag = 'result.%s' % inputtag
    elif '.' in inputtag:
        logger.debug("tag %s contains '.'" % inputtag)
        (target, finaltag) = inputtag.split('.')
        if not target in answer_tokens:
            logger.error("goals.config tag=<string> then tag must be:(%s), got %s" % (','.join(answer_tokens), inputtag))
            sys.exit(1)
        if not MyUtil.CheckAlphaDashUnder(finaltag):
            logger.error("Invalid characters in goals.config's tag (%s)" % inputtag)
            sys.exit(1)

        returntag = getTagValue(parameter_list, target, finaltag, logger)
    else:
        logger.debug("tag is %s" % inputtag)
        if not MyUtil.CheckAlphaDashUnder(inputtag):
            logger.error("Invalid characters in goals.config's tag (%s)" % inputtag)
            sys.exit(1)
        returntag = 'result.%s' % inputtag

    return returntag
コード例 #2
0
def ValidateUniqueConfig(actual_parsing, studentlabdir, container_list,
                         labidname, each_key, each_value, logger):
    valid_field_types = ['CHECKSUM']
    if not MyUtil.CheckAlphaDashUnder(each_key):
        logger.error("Not allowed characters in unique.config's key (%s)" %
                     each_key)
        sys.exit(1)
    values = []
    # expecting:
    # . - [ filename ] : [<field_type>]
    #    field_type = (a valid_field_type defined above) - currently only CHECKSUM is supported

    # NOTE: Split using ' : ' - i.e., "space colon space"
    values = [x.strip() for x in each_value.split(' : ')]
    #print values
    numvalues = len(values)
    logger.debug("each_value is %s -- numvalues is (%d)" %
                 (each_value, numvalues))
    if numvalues < 2:
        logger.error("found no ':' delimiter in %s" % each_value)
        sys.exit(1)
    if numvalues < 3 and values[1] not in line_types:
        logger.error(
            "Offending line: (%s).\n Perhaps there is a missing ':'?" %
            each_value)
        logger.error("unique.config expected %s to be one of these: %s." %
                     (values[1], str(line_types)))
        sys.exit(1)

    line_at = findLineIndex(values)
    if line_at is None:
        logger.error('No line_type in %s' % each_value)
        sys.exit(1)
    num_splits = line_at + 1
    #print "line_at is (%d) and num_splits is (%d)" % (line_at, num_splits)

    # NOTE: Split using ' : ' - i.e., "space colon space"
    values = [x.strip() for x in each_value.split(' : ', num_splits)]

    newfilename = values[0].strip()
    logger.debug('newfilename is %s' % newfilename)
    # <cfgcontainername>:<filename>
    if ':' in newfilename:
        cfgcontainername, filename = newfilename.split(':', 1)
    else:
        if len(container_list) > 1:
            logger.error(
                'No container name found in multi container lab entry (%s = %s)'
                % (each_key, each_value))
            sys.exit(1)
        cfgcontainername = ""
        filename = newfilename
    # Construct proper containername from cfgcontainername
    if cfgcontainername == "":
        containername = ""
    else:
        containername = labidname + "." + cfgcontainername + ".student"

    if filename not in logfilelist:
        logfilelist.append(filename)

    return newfilename
コード例 #3
0
ファイル: GoalsParser.py プロジェクト: lukixx3/Labtainers
def ParseGoals(homedir, studentdir, logger_in):
    MYHOME = homedir
    logger = logger_in
    nametags = []
    configfilename = os.path.join(MYHOME,'.local','instr_config', 'goals.config')
    configfile = open(configfilename)
    configfilelines = configfile.readlines()
    configfile.close()
    lab_instance_seed = GetLabInstanceSeed(studentdir, logger)
    container_user = ""
    param_filename = os.path.join(MYHOME, '.local', 'config',
          'parameter.config')

    pp = ParameterParser.ParameterParser(None, container_user, lab_instance_seed, logger)

    parameter_list = pp.ParseParameterConfig(param_filename)

    for line in configfilelines:
        linestrip = line.rstrip()
        if linestrip:
            if not linestrip.startswith('#'):
                logger.debug("Current linestrip is (%s)" % linestrip)
                try:
                    (each_key, each_value) = linestrip.split('=', 1)
                except:
                     logger.error('goal lacks "=" character, %s' % linestrip)
                     sys.exit(1)
                each_key = each_key.strip()
                if not MyUtil.CheckAlphaDashUnder(each_key):
                    logger.error("Invalid characters in goals.config's key (%s)" % each_key)
                    sys.exit(1)
                if len(each_key) > 15:
                    logger.debug("goal (%s) is more than 15 characters long\n" % each_key)

                values = []
                # expecting - either:
                # <type> : <operator> : <resulttag> : <answertag>
                # <type> : <goal1tag> : <goal2tag>
                # <type> : <string>
                values = each_value.split(" : ")
                numvalues = len(values)
                logger.debug('numvalues is %d  values are: %s' % (numvalues, str(values)))
                if not (numvalues == 4 or numvalues == 3 or numvalues == 2):
                    logger.error("goals.config contains unexpected value (%s) format" % each_value)
                    sys.exit(1)
                if numvalues == 4:
                    ''' <type> : <operator> : <resulttag> : <answertag> '''
                    goal_type = values[0].strip()
                    goal_operator = values[1].strip()
                    resulttag = values[2].strip()
                    answertag = values[3].strip()
                    # Allowed 'answer=<string>' for answertag only
                    valid_answertag = ValidateTag(parameter_list, studentdir, goal_type, answertag, True, logger)
                    valid_resulttag = ValidateTag(parameter_list, studentdir, goal_type, resulttag, False, logger)
                    if not (goal_type == "matchany" or
                        goal_type == "matchlast" or
                        goal_type == "matchacross" or
                        goal_type == "count" or
                        goal_type == "value" or
                        goal_type == "execute"):
                        logger.error("Error found in line (%s)" % linestrip)
                        logger.error("goals.config contains unrecognized type (1) (%s)" % goal_type)
                        sys.exit(1)
                    if not (goal_type == "execute"):
                        # If goal_type is not 'execute' then check the goal_operator
                        if not (goal_operator == "string_equal" or
                            goal_operator == "hash_equal" or
                            goal_operator == "string_diff" or
                            goal_operator == "string_start" or
                            goal_operator == "string_end" or
                            goal_operator == "string_contains" or
                            goal_operator == "integer_equal" or
                            goal_operator == "integer_greater" or
                            goal_operator == "integer_lessthan"):
                            logger.error("Error found in line (%s)" % linestrip)
                            logger.error("goals.config contains unrecognized operator (%s)" % (goal_operator))
                            sys.exit(1)
                    else:
                        # Make sure the file to be executed exist
                        execfile = os.path.join(MYHOME, '.local', 'bin', goal_operator)
                        if not (os.path.exists(execfile) and os.path.isfile(execfile)):
                            logger.error("Error found in line (%s)" % linestrip)
                            logger.error("goals.config contains execute goals with missing exec file (%s)" % (goal_operator))
                            sys.exit(1)
                    nametags.append(MyGoal(each_key, goal_type, goaloperator=goal_operator, answertag=valid_answertag, resulttag=valid_resulttag))
                    #print "goal_type non-boolean"
                    #print nametags[each_key].goal_dict()
                elif numvalues == 3:
                    ''' <type> : <goal1tag> : <goal2tag> '''
                    goal_type = values[0].strip()
                    if goal_type == 'time_before' or goal_type == 'time_during' or goal_type == 'time_not_during':
                        goal1tag = values[1].strip()
                        goal2tag = values[2].strip()
                        nametags.append(MyGoal(each_key, goal_type, goal1tag=goal1tag, goal2tag=goal2tag))
                    elif goal_type == 'count_greater':
                        answertag = values[1].strip()
                        subgoal_list = values[2].strip()
                        nametags.append(MyGoal(each_key, goal_type, answertag=answertag, boolean_string=subgoal_list))
                    else:
                        logger.error('Could not parse goals.config line %s' % each_value)
                        sys.exit(1)
                    #print "goal_type non-boolean"
                    #print nametags[each_key].goal_dict()
                else:
                    ''' <type> : <string> '''
                    goal_type = values[0].strip()
                    if goal_type == 'boolean':
                        boolean_string = values[1].strip()
                        nametags.append(MyGoal(each_key, goal_type, boolean_string=boolean_string))
                    elif goal_type == 'is_true' or goal_type == 'is_false':
                        resulttag = values[1].strip()
                        #print('parsegoals type is %s result %s' % (goal_type, resulttag))
                        nametags.append(MyGoal(each_key, goal_type, resulttag=resulttag))
                    elif goal_type == 'count' or goal_type == 'value':
                        resulttag = values[1].strip()
                        nametags.append(MyGoal(each_key, goal_type, resulttag=resulttag))
                    elif goal_type == 'count_greater':
                        logger.error('missing count_greater value in %s ?' % linestrip)
                        sys.exit(1)
                    else:
                        logger.error('Could not parse goals.config line %s' % linestrip)
                        sys.exit(1)
       
                    #print "goal_type boolean"
                    #print nametags[each_key].goal_dict()

                #nametags[each_key].toJSON()
                #nametags[each_key].goal_type = goal_type
                #nametags[each_key].goal_operator = goal_operator
                #nametags[each_key].answertag = valid_answertag
                #nametags[each_key].resulttag = valid_resulttag
                #nametags[each_key].boolean_string = boolean_string

        #else:
        #    print "Skipping empty linestrip is (%s)" % linestrip


    #print nametags["crash"].toJSON()
    #for (each_key, each_goal) in nametags.items():
    #    print nametags[each_key].toJSON()
    student_parent_dir = os.path.dirname(studentdir)
    resultsdir = os.path.join(student_parent_dir, '.local','result')
    try:
        os.makedirs(resultsdir)
    except:
        pass
    outputjsonfname = os.path.join(resultsdir,'goals.json')
    #print "GoalsParser: Outputjsonfname is (%s)" % outputjsonfname
        
    #print nametags
    jsonoutput = open(outputjsonfname, "w")
    jsondumpsoutput = json.dumps([x.goal_dict() for x in nametags], indent=4)
    jsonoutput.write(jsondumpsoutput)
    jsonoutput.write('\n')
    jsonoutput.close()

    return parameter_list
コード例 #4
0
ファイル: ResultParser.py プロジェクト: robbyoconnor/SecGen
def ProcessConfigLine(actual_parsing, studentlabdir, container_list, labidname,
                      result_key, result_value, logger):
    '''
    This function populates a set of global structures used in processing the results
    '''
    valid_field_types = [
        'TOKEN', 'GROUP', 'PARENS', 'QUOTES', 'SLASH', 'LINE_COUNT',
        'CHECKSUM', 'CONTAINS', 'FILE_REGEX', 'FILE_REGEX_TS', 'SEARCH',
        'PARAM', 'STRING_COUNT', 'COMMAND_COUNT'
    ]
    if not MyUtil.CheckAlphaDashUnder(result_key):
        logger.ERROR("Not allowed characters in results.config's key (%s)" %
                     result_key)
        sys.exit(1)
    values = []
    # See the Labtainer Lab Designer User guide for syntax

    # NOTE: Split using ' : ' - i.e., "space colon space"
    values = [x.strip() for x in result_value.split(' : ')]
    #print values
    numvalues = len(values)
    logger.DEBUG("result_value is %s -- numvalues is (%d)" %
                 (result_value, numvalues))
    if numvalues < 2:
        logger.ERROR("found no ':' delimiter in %s" % result_value)
        sys.exit(1)
    if numvalues < 3 and values[1] not in just_field_type:
        logger.ERROR(
            "Offending line: (%s).\n Perhaps there is a missing ':'?" %
            result_value)
        logger.ERROR("results.config expected %s to be one of these: %s." %
                     (values[1], str(just_field_type)))
        sys.exit(1)

    line_at = findLineIndex(values)
    if line_at is None:
        logger.ERROR('No line_type in %s' % result_value)
        sys.exit(1)
    num_splits = line_at + 1
    #print "line_at is (%d) and num_splits is (%d)" % (line_at, num_splits)

    # NOTE: Split using ' : ' - i.e., "space colon space"
    values = [x.strip() for x in result_value.split(' : ', num_splits)]

    # get optional container name and determine if it is 'stdin' or 'stdout'
    newprogname_type = values[0].strip()
    logger.DEBUG('newprogname_type is %s' % newprogname_type)
    cmd = values[1].strip()
    # <cfgcontainername>:<exec_program>.<type>
    if ':' in newprogname_type:
        '''
        [container_name:]<prog>.[stdin | stdout] | [container_name:]file_path[:time_program]

        '''
        cfgcontainername = ''
        parts = newprogname_type.split(':')
        if len(parts) == 2:
            if parts[0].startswith('/'):
                progname_type = parts[0]
                if len(container_list) > 1:
                    logger.ERROR(
                        'No container name found in multi container lab entry (%s = %s)'
                        % (result_key, result_value))
                    sys.exit(1)
            else:
                cfgcontainername = parts[0]
                progname_type = parts[1]
        elif len(parts) == 3:
            cfgcontainername = parts[0]
            progname_type = parts[1]
    else:
        if len(container_list) > 1:
            logger.ERROR(
                'No container name found in multi container lab entry (%s = %s)'
                % (result_key, result_value))
            sys.exit(1)
        if newprogname_type.endswith('stdin') or newprogname_type.endswith('stdout') \
             or newprogname_type.endswith('prgout'):
            cfgcontainername = container_list[0].split('.')[1]
            #print('assigned to %s' % cfgcontainername)
        else:
            cfgcontainername = ""
        progname_type = newprogname_type
    # Construct proper containername from cfgcontainername
    if cfgcontainername == "":
        containername = ""
    else:
        containername = labidname + "." + cfgcontainername + ".student"

    logger.DEBUG('Start to populate exec_program_list, progname_type is %s' %
                 progname_type)
    # No longer restricted to stdin/stdout filenames
    if ('stdin' not in progname_type) and ('stdout' not in progname_type) and (
            'prgout' not in progname_type):
        # Not stdin/stdout - add the full name
        logger.DEBUG('Not a STDIN or STDOUT: %s ' % progname_type)
    else:
        (exec_program, targetfile) = progname_type.rsplit('.', 1)
        exec_program_list = []
        # Can only parse for wildcard if it is actual parsing - not validation
        if exec_program == "*" and actual_parsing:
            exec_program_list = GetExecProgramList(containername,
                                                   studentlabdir,
                                                   container_list, targetfile)
            logger.DEBUG("wildcard, exec_program_list is %s" %
                         exec_program_list)
        else:
            exec_program_list.append(exec_program)
            logger.DEBUG('exec_program %s, append to list, container is %s' %
                         (exec_program, containername))
        if containername != "":
            #print('containername is %s' % containername)
            if containername not in container_exec_proglist:
                container_exec_proglist[containername] = []
            for cur_exec_program in exec_program_list:
                if cur_exec_program not in container_exec_proglist[
                        containername]:
                    container_exec_proglist[containername].append(
                        cur_exec_program)
            logger.DEBUG('proglist is %s' %
                         str(container_exec_proglist[containername]))
        else:
            if "CURRENT" not in container_exec_proglist:
                container_exec_proglist["CURRENT"] = []
            for cur_exec_program in exec_program_list:
                if cur_exec_program not in container_exec_proglist["CURRENT"]:
                    container_exec_proglist["CURRENT"].append(cur_exec_program)
            #print container_exec_proglist["CURRENT"]

        #print container_exec_proglist

    # Validate <field_type> - if exists (i.e., line_at == 3)
    #                       - because <field_type> is optional
    field_type = None
    if line_at == 3:
        field_type = values[1].strip()
        if field_type not in valid_field_types:
            logger.ERROR("results.config line (%s)\n" % result_value)
            logger.ERROR("results.config invalid field_type")
            sys.exit(1)

    # Sanity check for 'PARAM' type
    if values[line_at] == 'PARAM':
        logger.DEBUG("progname_type is (%s)" % progname_type)
        if not progname_type.endswith('stdin'):
            logger.ERROR("results.config line (%s)\n" % result_value)
            logger.ERROR("PARAM field_type on non stdin file")
            sys.exit(1)
        paramtoken_id = values[2].strip()
        try:
            paramindex = int(paramtoken_id)
        except:
            logger.ERROR("results.config line (%s)\n" % result_value)
            logger.ERROR('PARAM field_type could not parse int from %s' %
                         paramtoken_id)
            sys.exit(1)

    # If line_type1 (line_at != 1) - verify token id
    if field_type != 'SEARCH' and line_at != 1:
        token_index = 1
        if line_at == 3:
            token_index = 2
        ValidateTokenId(result_value, values[token_index], logger)

    if values[line_at] == 'LINE':
        try:
            int(values[line_at + 1])
        except:
            logger.ERROR('Expected integer following LINE type, got %s in %s' %
                         (values[line_at + 1], result_value))
            sys.exit(1)

    return newprogname_type, cmd