Ejemplo n.º 1
0
    def visit(self, item):

        import statements
        import expressions
        import lib_functions

        if (item in self.visited):
            return False
        self.visited.add(item)
        if (isinstance(item, statements.Call_Statement)):
            if (not isinstance(item.name, expressions.MemberAccessExpression)):
                self.called_funcs.add(safe_str_convert(item.name))
        if (isinstance(item, expressions.Function_Call)):
            self.called_funcs.add(safe_str_convert(item.name))
        if (isinstance(item, statements.File_Open)):
            self.called_funcs.add("Open")
        if (isinstance(item, statements.Print_Statement)):
            self.called_funcs.add("Print")
        if (isinstance(item, lib_functions.Chr)):
            self.called_funcs.add("Chr")
        if (isinstance(item, lib_functions.Asc)):
            self.called_funcs.add("Asc")
        if (isinstance(item, lib_functions.StrReverse)):
            self.called_funcs.add("StrReverse")
        if (isinstance(item, lib_functions.Environ)):
            self.called_funcs.add("Environ")
        return True
Ejemplo n.º 2
0
def _handle_shapes_access(r, arg, context, got_constant_math):
    """Finish handling a partially handled Shapes() access.

    @param arg (VBA_Object object) The item being evaluated.

    @param context (Context object) The current program state.
    
    @param got_constant_math (boolean) If True the given arg is an all
    numeric literal expression, if False it is not.
    
    @return (??) On success the evaluated item is returned, None is
    returned on error.

    """

    # Is this a Shapes() access that still needs to be handled?
    poss_shape_txt = ""
    if isinstance(r, (VBA_Object, str)):
        poss_shape_txt = safe_str_convert(r)
    if ((poss_shape_txt.startswith("Shapes("))
            or (poss_shape_txt.startswith("InlineShapes("))):
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("eval_arg: Handling intermediate Shapes() access for " +
                      safe_str_convert(r))
        r = eval_arg(r, context)
        if got_constant_math: set_cached_value(arg, r)
        return r

    # Not handled.
    return None
Ejemplo n.º 3
0
    def eval(self, context, params=None):

        # Exit if an exit function statement was previously called.
        #if (context.exit_func):
        #    return

        # Assign all const variables first.
        do_const_assignments(self.block, context)

        # Emulate the statements in the block.
        log.info("Emulating " + safe_str_convert(self) + " ...")
        context.global_scope = True
        for curr_statement in self.block:

            # Don't emulate declared functions.
            if isinstance(curr_statement, (External_Function, Function, Sub)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line eval of " +
                              safe_str_convert(curr_statement))
                continue

            # Is this something we can emulate?
            if (not isinstance(curr_statement, VBA_Object)):
                continue
            curr_statement.eval(context, params=params)

            # Was there an error that will make us jump to an error handler?
            if (context.must_handle_error()):
                break
            context.clear_error()

        # Run the error handler if we have one and we broke out of the statement
        # loop with an error.
        context.handle_error(params)
Ejemplo n.º 4
0
def _fix_sheet_name(sheet_name):
    """Replace characters given as hex with the actual character values.

    @param sheet_name (str) The name of the sheet to fix.

    @return (str) The given name with 0xNN substrings replaced with
    chr(0xNN).

    """

    # Get the characters given as hex strings in the name.
    pat = r"(0x[0-9a-f]{2})"
    r = safe_str_convert(sheet_name)
    hex_strs = re.findall(pat, r)
    if (len(hex_strs) == 0):
        return sheet_name

    # Replace them with the actual values.
    for hex_val in hex_strs:
        try:
            chr_val = int(hex_val, 16)
            r = r.replace(hex_val, chr(chr_val))
        except Exception as e:
            log.error("Fixing sheet named failed. " + safe_str_convert(e))
    return r
Ejemplo n.º 5
0
    def dump_actions(self):
        """Return a table of all actions recorded by trace(), as a
        prettytable object that can be printed or reused.

        @return (PrettyTable object) The actions performed during
        emulation saved as a PrettyTable object.

        """
        t = prettytable.PrettyTable(('Action', 'Parameters', 'Description'))
        t.align = 'l'
        t.max_width['Action'] = 20
        t.max_width['Parameters'] = 45
        t.max_width['Description'] = 35
        for action in self.actions:
            # Cut insanely large results down to size.
            str_action = safe_str_convert(action)
            if (len(str_action) > 50000):
                new_params = safe_str_convert(action[1])
                if (len(new_params) > 50000):
                    new_params = new_params[:
                                            25000] + "... <SNIP> ..." + new_params[
                                                -25000:]
                action = (action[0], new_params, action[2])
            t.add_row(action)
        return t
Ejemplo n.º 6
0
    def visit(self, item):
        from expressions import SimpleNameExpression
        from expressions import MemberAccessExpression

        # Already looked at this?
        if (item in self.visited):
            return False
        self.visited.add(item)

        # Simple variable?
        if (isinstance(item, SimpleNameExpression)):
            self.variables.add(safe_str_convert(item.name))

        # Array access?
        if (("Function_Call" in safe_str_convert(type(item)))
                and (self.context is not None)):

            # Is this an array or function?
            if (hasattr(item, "name") and (self.context.contains(item.name))):
                ref = self.context.get(item.name)
                if isinstance(ref, (list, str)):
                    self.variables.add(safe_str_convert(item.name))

        # Member access expression used as a variable?
        if (isinstance(item, MemberAccessExpression)):
            rhs = item.rhs
            if (isinstance(rhs, list)):
                rhs = rhs[-1]
            if (isinstance(rhs, SimpleNameExpression)):
                self.variables.add(safe_str_convert(item))

        return True
Ejemplo n.º 7
0
    def eval(self, context, params=None):

        # Perform all of the const assignments first.
        for block in self.loose_lines:
            if isinstance(block, (External_Function, Function, Sub)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line const eval of " +
                              safe_str_convert(block))
                continue
            if (isinstance(block, LooseLines)):
                context.global_scope = True
                do_const_assignments(block.block, context)
                context.global_scope = False

        # Emulate the loose line blocks (statements that appear outside sub/func
        # defs) in order.
        done_emulation = False
        for block in self.loose_lines:
            if isinstance(block, (External_Function, Function, Sub)):
                if (log.getEffectiveLevel() == logging.DEBUG):
                    log.debug("Skip loose line eval of " +
                              safe_str_convert(block))
                continue
            context.global_scope = True
            block.eval(context, params)
            context.global_scope = False
            done_emulation = True

        # Return if we ran anything.
        return done_emulation
Ejemplo n.º 8
0
def _read_from_excel(arg, context):
    """Try to evaluate an argument by reading from the loaded Excel
    spreadsheet.

    @param arg (VBA_Object object) The argument to evaluate.

    @param context (Context object) The current program state.
    
    @return (any) The result of the evaluation on success, None on
    failure.

    """

    # Try handling reading value from an Excel spreadsheet cell.
    # ThisWorkbook.Sheets('YHRPN').Range('J106').Value
    if ("MemberAccessExpression" not in safe_str_convert(type(arg))):
        return None
    arg_str = safe_str_convert(arg)
    if (("sheets(" in arg_str.lower()) and (("range(" in arg_str.lower()) or
                                            ("cells(" in arg_str.lower()))):

        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Try as Excel cell read...")

        return arg.eval(context)

    # Not handled.
    return None
Ejemplo n.º 9
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the floor division of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute floor div " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x // y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) // int(y), evaluated_args)
            except Exception as e:
                if (safe_str_convert(e).strip() != "division by zero"):
                    log.error(
                        'Impossible to divide arguments of different types. ' +
                        safe_str_convert(e))
                # TODO
                return 0
        except ZeroDivisionError as e:
            context.set_error(safe_str_convert(e))
Ejemplo n.º 10
0
def set_cached_value(arg, val):
    """Set the cached value of an all constant numeric expression.

    @param arg (VBA_Object object) The unresolved expression to
    cache. 

    @param val (int, float, complex) The value of the resolved
    expression.

    """

    # We should be setting this to a numeric expression
    if ((not isinstance(val, int)) and (not isinstance(val, float))
            and (not isinstance(val, complex))):
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.warning("Expression '" + safe_str_convert(val) + "' is a " +
                        safe_str_convert(type(val)) +
                        ", not an int. Not caching.")
        return

    # Don't cache things that contain Excel sheets or workbooks.
    if contains_excel(arg):
        return

    # We have a number. Cache it.
    arg_str = safe_str_convert(arg)
    try:
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Cache value of " + arg_str + " = " +
                      safe_str_convert(val))
    except UnicodeEncodeError:
        pass
    constant_expr_cache[arg_str] = val
Ejemplo n.º 11
0
def _handle_wscriptshell_run(arg, context, got_constant_math):
    """Handle cases where wscriptshell.run() is being called and there is
    a local run() function.

    @param arg (VBA_Object object) The item being evaluated.

    @param context (Context object) The current program state.
    
    @param got_constant_math (boolean) If True the given arg is an all
    numeric literal expression, if False it is not.
    
    @return (??) On success the evaluated item is returned, None is
    returned on error.

    """

    # Handle cases where wscriptshell.run() is being called and there is a local run() function.
    if ((".run(" in safe_str_convert(arg).lower())
            and (context.contains("run"))):

        # Resolve the run() call.
        if ("MemberAccessExpression" in safe_str_convert(type(arg))):
            arg_evaled = arg.eval(context)
            if got_constant_math: set_cached_value(arg, arg_evaled)
            return arg_evaled

    # Not handled.
    return None
Ejemplo n.º 12
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the exponentiation of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute pow " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: pow(x, y),
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: pow(int(x), int(y)), evaluated_args)
            except Exception as e:
                log.error(
                    'Impossible to do exponentiation with arguments of different types. '
                    + safe_str_convert(e))
                return 0
Ejemplo n.º 13
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the xor of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute xor " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x ^ y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(lambda x, y: int(x) ^ int(y), evaluated_args)
            except Exception as e:
                log.error(
                    'Impossible to xor arguments of different types. Arg list = '
                    + safe_str_convert(self.arg) + ". " + safe_str_convert(e))
                return 0
        except RuntimeError as e:
            log.error("overflow trying eval xor: %r" % self.arg)
            raise e
Ejemplo n.º 14
0
    def eval(self, context, params=None):

        # We are emulating some string or numeric
        # expression. Therefore any boolean operators we find in the
        # expression are actually bitwise operators.
        # Track that in the context.
        set_flag = False
        if (not context.in_bitwise_expression):
            context.in_bitwise_expression = True
            set_flag = True

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            if set_flag:
                context.in_bitwise_expression = False
            return "**MATCH ANY**"

        try:
            args = vba_conversion.coerce_args(evaluated_args)
            ret = args[0]
            for op, arg in zip(self.operators, args[1:]):
                try:
                    ret = self.operator_map[op](ret, arg)
                except OverflowError:
                    log.error("overflow trying eval: %r" %
                              safe_str_convert(self))
            if set_flag:
                context.in_bitwise_expression = False
            return ret
        except (TypeError, ValueError):
            # Try converting strings to numbers.
            # TODO: Need to handle floats in strings.
            try:
                args = map(vba_conversion.coerce_to_num, evaluated_args)
                ret = args[0]
                for op, arg in zip(self.operators, args[1:]):
                    ret = self.operator_map[op](ret, arg)
                if set_flag:
                    context.in_bitwise_expression = False
                return ret
            except ZeroDivisionError:
                context.set_error("Division by 0 error. Returning 'NULL'.")
                if set_flag:
                    context.in_bitwise_expression = False
                return 'NULL'
            except Exception as e:
                log.error(
                    'Impossible to operate on arguments of different types. ' +
                    safe_str_convert(e))
                if set_flag:
                    context.in_bitwise_expression = False
                return 0
        except ZeroDivisionError:
            context.set_error("Division by 0 error. Returning 'NULL'.")
            if set_flag:
                context.in_bitwise_expression = False
            return 'NULL'
Ejemplo n.º 15
0
def coerce_to_str(obj, zero_is_null=False):
    """Coerce a VBA object (integer, Null, etc) to a string.

    @param obj (VBA_Object object) The VBA object to convert to a
    string.

    @param zero_is_null (boolean) If True treat integer 0 as a zero
    length string, if False just convert 0 to '0'.

    @return (str) The given VBA object as a string.

    """

    # in VBA, Null/None is equivalent to an empty string
    if ((obj is None) or (obj == "NULL")):
        return ''

    # 0 can be a NULL also.
    if (zero_is_null and (obj == 0)):
        return ''

    # Not NULL. We have data.

    # Easy case. Is this already some sort of a string?
    if (isinstance(obj, basestring)):

        # Convert to a regular str if needed.
        return safe_str_convert(obj)

    # Do we have a list of byte values? If so convert the bytes to chars.
    if (isinstance(obj, list)):
        r = ""
        bad = False
        for c in obj:

            # Skip null bytes.
            if (c == 0):
                continue
            try:
                r += chr(c)
            except (TypeError, ValueError):

                # Invalid character value. Don't do string
                # conversion of array.
                bad = True
                break

        # Return the byte array as a string if it makes sense.
        if (not bad):
            return r

    # Is this an Excel cell dict?
    if (isinstance(obj, dict) and ("value" in obj)):

        # Return the value as a string.
        return (coerce_to_str(obj["value"]))

    # Not a character byte array. Just convert to a string.
    return safe_str_convert(obj)
Ejemplo n.º 16
0
    def add_compiled_module(self, m, stream):
        """Add an already parsed and processed module.

        @param m (Module object) The parsed object.

        @param stream (str) The OLE stream name containing the module.

        """
        if (m is None):
            return
        self.modules.append(m)
        for name, _sub in m.subs.items():

            # Append the stream name for duplicate subs
            if (name in self.globals):
                new_name = safe_str_convert(stream) + "::" + safe_str_convert(
                    name)
                log.warn("Renaming duplicate function " + name + " to " +
                         new_name)
                name = new_name

            # Save the sub.
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing sub "%s" in globals' % name)
            self.globals[name.lower()] = _sub
            self.globals[name] = _sub

        # Functions.
        for name, _function in m.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing function "%s" in globals' % name)
            self.globals[name.lower()] = _function
            self.globals[name] = _function

        # Properties.
        for name, _prop in m.functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing property let "%s" in globals' % name)
            self.globals[name.lower()] = _prop
            self.globals[name] = _prop

        # External DLL functions.
        for name, _function in m.external_functions.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing external function "%s" in globals' %
                          name)
            self.globals[name.lower()] = _function
            self.externals[name.lower()] = _function

        # Global variables.
        for name, _var in m.global_vars.items():
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug('(1) storing global var "%s" = %s in globals (1)' %
                          (name, safe_str_convert(_var)))
            if (isinstance(name, str)):
                self.globals[name.lower()] = _var
            if (isinstance(name, list)):
                self.globals[name[0].lower()] = _var
                self.types[name[0].lower()] = name[1]
Ejemplo n.º 17
0
def _called_funcs_to_python(loop, context, indent):
    """Convert all the functions called in the given loop to Python JIT
    code.

    @param loop (VBA_Object object) The loop for which to generate
    Python JIT code.

    @param context (Context object) The current program state.

    @param indent (int) The number of spaces to indent the generated
    Python code.

    @return (str) Python JIT code.

    """
    
    # Get the definitions for all local functions called directly in the loop.
    local_funcs = _get_all_called_funcs(loop, context)
    local_func_hashes = set()
    for curr_func in local_funcs:
        curr_func_hash = hashlib.md5(safe_str_convert(curr_func).encode()).hexdigest()
        local_func_hashes.add(curr_func_hash)
        
    # Now get the definitions of all the local functions called by the local
    # functions.
    seen_funcs = set()
    funcs_to_handle = list(local_funcs)
    while (len(funcs_to_handle) > 0):

        # Get the current function definition to check for calls.
        curr_func = funcs_to_handle.pop()
        curr_func_hash = hashlib.md5(safe_str_convert(curr_func).encode()).hexdigest()
        
        # Already looked at this one?
        if (curr_func_hash in seen_funcs):
            continue
        seen_funcs.add(curr_func_hash)

        # Get the functions called in the current function.
        curr_local_funcs = _get_all_called_funcs(curr_func, context)

        # Save the new functions for processing.
        for new_func in curr_local_funcs:
            new_func_hash = hashlib.md5(safe_str_convert(new_func).encode()).hexdigest()
            if (new_func_hash not in local_func_hashes):
                local_func_hashes.add(new_func_hash)
                local_funcs.append(new_func)
                funcs_to_handle.append(new_func)
                
    # Convert each local function to Python.
    r = ""
    for local_func in local_funcs:
        r += to_python(local_func, context, indent=indent) + "\n"

    # Done.
    indent_str = " " * indent
    r = indent_str + "# VBA Local Function Definitions\n" + r
    return r
Ejemplo n.º 18
0
 def visit(self, item):
     if (item in self.visited):
         return False
     self.visited.add(item)
     if (isinstance(item, Dim_Statement)):
         for name, _, _, _ in item.variables:
             self.variables.add(safe_str_convert(name))
     if (isinstance(item, Let_Statement)):
         self.variables.add(safe_str_convert(item.name))
     return True
 def visit(self, item):
     if (item in self.visited):
         return False
     self.visited.add(item)
     if (isinstance(item, statements.External_Function)):
         self.funcs[safe_str_convert(item.name)] = safe_str_convert(
             item.alias_name)
         self.names.add(safe_str_convert(item.alias_name))
         self.aliases.add(safe_str_convert(item.name))
     return True
Ejemplo n.º 20
0
    def visit(self, item):
        if (safe_str_convert(item) in self.visited):
            return False
        self.visited.add(safe_str_convert(item))
        if ("Let_Statement" in safe_str_convert(type(item))):
            if (isinstance(item.name, str)):
                self.variables.add(item.name)
            elif (isinstance(item.name, pyparsing.ParseResults) and
                  (item.name[0].lower().replace("$", "").replace("#", "").replace("%", "") == "mid")):
                self.variables.add(safe_str_convert(item.name[1]))

        return True
Ejemplo n.º 21
0
def _updated_vars_to_python(loop, context, indent):
    """Generate Python JIT code for saving the variables updated in a loop
    in Python. These updates are saved in the Python var_updates
    variable.

    @param loop (VBA_Object object) The loop for which to generate
    Python JIT code.

    @param context (Context object) The current program state.

    @param indent (int) The number of spaces to indent the generated
    Python code.

    @return (str) Python JIT code.

    """
    import statements
    
    indent_str = " " * indent
    lhs_visitor = lhs_var_visitor()
    loop.accept(lhs_visitor)
    lhs_var_names = lhs_visitor.variables
    # Handle With variables if needed.
    if (context.with_prefix_raw is not None):
        lhs_var_names.add(safe_str_convert(context.with_prefix_raw))
    # Handle For loop index variables if needed.
    if (isinstance(loop, statements.For_Statement)):
        lhs_var_names.add(safe_str_convert(loop.name))
    var_dict_str = "{"
    first = True
    for var in lhs_var_names:
        py_var = utils.fix_python_overlap(var)
        if (not first):
            var_dict_str += ", "
        first = False
        var = var.replace(".", "")
        var_dict_str += '"' + var + '" : ' + py_var
    var_dict_str += "}"
    save_vals = indent_str + "try:\n"
    save_vals += indent_str + " " * 4 + "var_updates\n"
    save_vals += indent_str + " " * 4 + "var_updates.update(" + var_dict_str + ")\n"
    save_vals += indent_str + "except (NameError, UnboundLocalError):\n"
    save_vals += indent_str + " " * 4 + "var_updates = " + var_dict_str + "\n"
    save_vals += indent_str + 'var_updates["__shell_code__"] = core.vba_library.get_raw_shellcode_data()\n'
    save_vals = indent_str + "# Save the updated variables for reading into ViperMonkey.\n" + save_vals
    if (log.getEffectiveLevel() == logging.DEBUG):
        save_vals += indent_str + "print \"UPDATED VALS!!\"\n"
        save_vals += indent_str + "print var_updates\n"
    return save_vals
Ejemplo n.º 22
0
def load_excel_xlrd(data):
    """Read in an Excel file into an ExceBook object directly with the
    xlrd Excel library.

    @param data (str) The Excel file contents.

    @return (core.excel.ExceBook object) On success return the Excel
    spreadsheet as an ExcelBook object. Returns None on error.

    """

    # Only use this on Office 97 Excel files.
    if (not filetype.is_office97_file(data, True)):
        log.warning("File is not an Excel 97 file. Not reading with xlrd2.")
        return None

    # It is Office 97. See if we can read it with xlrd2.
    try:
        if (log.getEffectiveLevel() == logging.DEBUG):
            log.debug("Trying to load with xlrd...")
        r = xlrd.open_workbook(file_contents=data)
        return r
    except Exception as e:
        log.error("Reading in file as Excel with xlrd failed. " +
                  safe_str_convert(e))
        return None
Ejemplo n.º 23
0
def get_cached_value(arg):
    """Get the cached value of an all constant numeric expression if we
    have it.

    @param arg (VBA_Object object) The argument to check.

    @return (int or VBA_Object) The cached value of the all constant
    numeric expression if it is in the cache, the original given
    argument if not.

    """

    # Don't do any more work if this is already a resolved value.
    if isinstance(arg, (dict, int)):
        return arg

    # If it is something that may be hard to convert to a string, no cached value.
    if contains_excel(arg):
        return None

    # This is not already resolved to an int. See if we computed this before.
    arg_str = safe_str_convert(arg)
    if (arg_str not in constant_expr_cache.keys()):
        return None
    return constant_expr_cache[arg_str]
Ejemplo n.º 24
0
    def full_str(self):
        """Full string representation of the object.

        @return (str) Object as a string.

        """
        return safe_str_convert(self)
Ejemplo n.º 25
0
    def cell(self, row, col):
        """Get a cell from the sheet.

        @param row (int) The cell's row index.

        @param col (int) The cell's column index.

        @return (str) The cell value if the cell is found.

        @throws KeyError This is thrown if the cell is not found.

        """
        if ((row, col) in self.cells):
            return self.cells[(row, col)]
        raise KeyError("Cell (" + safe_str_convert(row) + ", " +
                       safe_str_convert(col) + ") not found.")
Ejemplo n.º 26
0
    def __repr__(self):
        """Full string representation of the object.

        @return (str) Object as a string.

        """
        raise NotImplementedError("__repr__() not implemented in " +
                                  safe_str_convert(type(self)))
Ejemplo n.º 27
0
    def eval(self, context, params=None):

        # The wildcard for matching propagates through operations.
        evaluated_args = eval_args(self.arg, context)
        if ((isinstance(evaluated_args, Iterable))
                and ("**MATCH ANY**" in evaluated_args)):
            return "**MATCH ANY**"

        # return the subtraction of all the arguments:
        try:
            if (log.getEffectiveLevel() == logging.DEBUG):
                log.debug("Compute subract " + safe_str_convert(self.arg))
            return reduce(
                lambda x, y: x - y,
                vba_conversion.coerce_args(evaluated_args,
                                           preferred_type="int"))
        except (TypeError, ValueError):
            # Try converting strings to ints.
            # TODO: Need to handle floats in strings.
            try:
                return reduce(
                    lambda x, y: vba_conversion.coerce_to_int(x) -
                    vba_conversion.coerce_to_int(y), evaluated_args)
            except Exception as e:

                # Are we doing math on character ordinals?
                l1 = []
                orig = evaluated_args
                for v in orig:
                    if (isinstance(v, int)):
                        l1.append(v)
                        continue
                    if (isinstance(v, str) and (len(v) == 1)):
                        l1.append(ord(v))
                        continue

                # Do we have something that we can do math on?
                if (len(orig) != len(l1)):
                    log.error(
                        'Impossible to subtract arguments of different types. '
                        + safe_str_convert(e))
                    return 0

                # Try subtracting based on character ordinals.
                return reduce(lambda x, y: int(x) - int(y), l1)
Ejemplo n.º 28
0
def _pull_cells_sheet_internal(sheet, strip_empty):
    """Pull all the cells from an ExcelSheet object defined internally in
    excel.py.

    @param sheet (ExcelSheet object) The ExcelSheet sheet from which
    to pull cells.

    @param strip_empty (boolean) If True do not report cells with
    empty values, if False return all cells.

    @return (list) A list of cells from the sheet represented as a
    dict. Each cell dict is of the form { "value" : cell value, "row"
    : row index, "col" : column index, "index" : AB123 form of cell
    index }

    """

    # We are going to use the internal cells field to build the list of all
    # cells, so this will only work with the ExcelSheet class defined in excel.py.
    if (not hasattr(sheet, "cells")):
        # This is not an internal sheet object.
        return None

    # Cycle row by row through the sheet, tracking all the cells.

    # Find the max row and column for the cells.
    max_row = -1
    max_col = -1
    for cell_index in sheet.cells.keys():
        curr_row = cell_index[0]
        curr_col = cell_index[1]
        if (curr_row > max_row):
            max_row = curr_row
        if (curr_col > max_col):
            max_col = curr_col

    # Cycle through all the cells in order.
    curr_cells = []
    for curr_row in range(0, max_row + 1):
        for curr_col in range(0, max_col + 1):
            try:
                curr_val = sheet.cell(curr_row, curr_col)
                if (strip_empty
                        and (len(safe_str_convert(curr_val).strip()) == 0)):
                    continue
                curr_cell = {
                    "value": curr_val,
                    "row": curr_row + 1,
                    "col": curr_col + 1,
                    "index": _get_alphanum_cell_index(curr_row, curr_col)
                }
                curr_cells.append(curr_cell)
            except KeyError:
                pass

    # Return the cells.
    return curr_cells
Ejemplo n.º 29
0
    def __repr__(self):
        """String value of sheet.

        """
        if (self.gloss is not None):
            return self.gloss
        log.info("Converting Excel sheet to str ...")
        r = ""
        if debug:
            r += "Sheet: '" + self.name + "'\n\n"
            for cell in self.cells.keys():
                r += safe_str_convert(cell) + "\t=\t'" + safe_str_convert(
                    self.cells[cell]) + "'\n"
        else:
            r += "Sheet: '" + self.name + "'\n"
            r += safe_str_convert(self.cells)
        self.gloss = r
        return self.gloss
Ejemplo n.º 30
0
    def __repr__(self):
        """String version of workbook.

        """
        log.info("Converting Excel workbook to str ...")
        r = ""
        for sheet in self.sheets:
            r += safe_str_convert(sheet) + "\n"
        return r