diff --git a/app/templates/backend/rule/add_new_rule.html b/app/templates/backend/rule/add_new_rule.html index fa38c57a..ca63f836 100644 --- a/app/templates/backend/rule/add_new_rule.html +++ b/app/templates/backend/rule/add_new_rule.html @@ -39,6 +39,10 @@ Function Up + + + Location Rule Line + Function Down diff --git a/app/templates/backend/rule/edit_rule.html b/app/templates/backend/rule/edit_rule.html index 0dc5cabe..6ed026b9 100644 --- a/app/templates/backend/rule/edit_rule.html +++ b/app/templates/backend/rule/edit_rule.html @@ -26,12 +26,10 @@ Status - On + On - Off + Off @@ -40,6 +38,10 @@ Function Up + + + Location Rule Line + Function Down diff --git a/cobra.py b/cobra.py index de0f5df3..0f27144d 100644 --- a/cobra.py +++ b/cobra.py @@ -12,49 +12,12 @@ :license: MIT, see LICENSE for more details. :copyright: Copyright (c) 2016 Feei. All rights reserved """ -import os -import logging.config from app import web, manager -from utils import config +from utils import log, config def main(): - logs_directory = config.Config('cobra', 'logs_directory').value - logs_directory = os.path.join(config.Config().project_directory, logs_directory) - if os.path.isdir(logs_directory) is not True: - os.mkdir(logs_directory) - filename = os.path.join(logs_directory, 'cobra.log') - logging.config.dictConfig({ - 'version': 1, - 'disable_existing_loggers': True, - 'formatters': { - 'verbose': { - 'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", - 'datefmt': "%Y-%m-%d %H:%M:%S" - }, - 'simple': { - 'format': '%(levelname)s %(message)s' - }, - }, - 'handlers': { - 'file': { - 'level': 'DEBUG', - 'class': 'cloghandler.ConcurrentRotatingFileHandler', - 'maxBytes': 1024 * 1024 * 10, - 'backupCount': 50, - 'delay': True, - 'filename': filename, - 'formatter': 'verbose' - } - }, - 'loggers': { - '': { - 'handlers': ['file'], - 'level': 'INFO', - }, - } - }) - + log.Log() debug = config.Config('cobra', 'debug').value web.debug = bool(debug) manager.run() diff --git a/engine/parse.py b/engine/parse.py index 9993f210..dd1c9d9e 100644 --- a/engine/parse.py +++ b/engine/parse.py @@ -17,8 +17,10 @@ import re import subprocess import traceback +from utils import log import logging +log.Log() logging = logging.getLogger(__name__) @@ -34,6 +36,7 @@ def __init__(self, rule, file_path, line, code): logging.info(file_path) self.line = line self.code = code + self.param_name = None def functions(self): logging.info('---------------------- [-]. Functions --------------------------------------') @@ -97,45 +100,57 @@ def block_code(self, block_position): :param block_position: 0:up 1:down + 2:location_line :return: """ - functions = self.functions() logging.info('---------------------- [-]. Block code B:{0} --------------------------------------'.format(block_position)) - if functions: - block_start = 0 - block_end = 0 - for function_name, function_value in functions.items(): - in_this_function = '' - if int(function_value['start']) < int(self.line) < int(function_value['end']): - in_this_function = '<---- {0}'.format(self.line) - if block_position == 0: - block_start = function_value['start'] - block_end = int(self.line) - elif block_position == 1: - block_start = int(self.line) - block_end = function_value['end'] - logging.info("F: {0} ({1} - {2}) {3}".format(function_name, function_value['start'], function_value['end'], in_this_function)) - # get param block code - logging.info('C: {0} - {1}p'.format(block_start, block_end)) - param = ['sed', "-n", "{0},{1}p".format(block_start, block_end), self.file_path] - p = subprocess.Popen(param, stdout=subprocess.PIPE) - result = p.communicate() - if len(result[0]): - param_block_code = result[0] - if param_block_code == '': - param_block_code = False + if block_position == 2: + line_rule = '{0}p'.format(self.line) + code = self.get_code(line_rule) + logging.info("C: {0}".format(code)) + return code + else: + functions = self.functions() + if functions: + block_start = 0 + block_end = 0 + for function_name, function_value in functions.items(): + in_this_function = '' + if int(function_value['start']) < int(self.line) < int(function_value['end']): + in_this_function = '<---- {0}'.format(self.line) + if block_position == 0: + block_start = function_value['start'] + block_end = int(self.line) - 1 + elif block_position == 1: + block_start = int(self.line) + 1 + block_end = function_value['end'] + logging.info("F: {0} ({1} - {2}) {3}".format(function_name, function_value['start'], function_value['end'], in_this_function)) + # get param block code + logging.info('C: {0} - {1}p'.format(block_start, block_end)) + line_rule = "{0},{1}p".format(block_start, block_end) + return self.get_code(line_rule) else: + logging.info("Not found functions") + return False + + def get_code(self, line_rule): + param = ['sed', "-n", line_rule, self.file_path] + p = subprocess.Popen(param, stdout=subprocess.PIPE) + result = p.communicate() + if len(result[0]): + param_block_code = result[0] + if param_block_code == '': param_block_code = False - return param_block_code else: - logging.info("Not found functions") - return False + param_block_code = False + return param_block_code def is_controllable_param(self): logging.info('---------------------- [2]. Param is controllable --------------------------------------') param_name = re.findall(self.rule, self.code) + param_name = param_name[0].strip() + self.param_name = param_name if len(param_name) == 1: - param_name = param_name[0].strip() logging.info('P: {0}'.format(param_name)) # controllable param # exclude class const (maybe misuse) @@ -203,6 +218,8 @@ def is_controllable_param(self): else: logging.info("R: False (Not contained $)") return False + else: + logging.warning("Not Found Param") def is_repair(self, repair_rule, block_repair): logging.info('---------------------- [3]. Is repair B:{0} --------------------------------------'.format(block_repair)) @@ -210,6 +227,9 @@ def is_repair(self, repair_rule, block_repair): if code is False: logging.debug("R: Un Repair (repair code not match)") return False + # replace repair {{PARAM}} const + if '{{PARAM}' in repair_rule: + repair_rule = repair_rule.replace('{{PARAM}', self.param_name) repair_result = re.findall(repair_rule, code) logging.debug(code) logging.debug(repair_result) @@ -223,8 +243,10 @@ def is_repair(self, repair_rule, block_repair): if __name__ == '__main__': try: - parse = Parse('curl_setopt\s?\(.*,\s?CURLOPT_URL\s?,(.*)\)', '/path/to/your.php', '478', "curl_setopt($ch, CURLOPT_URL, $url);") + parse = Parse('curl_setopt\s?\(.*,\s?CURLOPT_URL\s?,(.*)\)', '/Volumes/Statics/Project/Company/mogujie/appbeta/classes/crond/trade/chenxitest.php', '60', "curl_setopt($curl, CURLOPT_URL, $file); #output") if parse.is_controllable_param(): - parse.is_repair(r'fff', 1) + parse.is_repair(r'fff', 2) + else: + print("UC") except Exception as e: print(traceback.print_exc()) diff --git a/utils/log.py b/utils/log.py index 4f96c035..d6d53597 100644 --- a/utils/log.py +++ b/utils/log.py @@ -1,171 +1,42 @@ -# -*- coding: utf-8 -*- - -""" - utils.log - ~~~~~~~~~ - - Implements logging - - :author: Feei - :homepage: https://github.com/wufeifei/cobra - :license: MIT, see LICENSE for more details. - :copyright: Copyright (c) 2016 Feei. All rights reserved -""" import os -import sys -import time -import logging -import logging.handlers +import logging.config from utils import config -__all__ = ['set_logger', 'debug', 'info', 'warning', 'error', - 'critical', 'exception'] - -# Color escape string -COLOR_RED = '\033[1;31m' -COLOR_GREEN = '\033[1;32m' -COLOR_YELLOW = '\033[1;33m' -COLOR_BLUE = '\033[1;34m' -COLOR_PURPLE = '\033[1;35m' -COLOR_CYAN = '\033[1;36m' -COLOR_GRAY = '\033[1;37m' -COLOR_WHITE = '\033[1;38m' -COLOR_RESET = '\033[1;0m' - -# Define log color -LOG_COLORS = { - 'DEBUG': '%s', - 'INFO': COLOR_GREEN + '%s' + COLOR_RESET, - 'WARNING': COLOR_YELLOW + '%s' + COLOR_RESET, - 'ERROR': COLOR_RED + '%s' + COLOR_RESET, - 'CRITICAL': COLOR_RED + '%s' + COLOR_RESET, - 'EXCEPTION': COLOR_RED + '%s' + COLOR_RESET, -} - -# Global logger -g_logger = None - - -class ColoredFormatter(logging.Formatter): - """A colorful formatter.""" - - def __init__(self, fmt=None, datefmt=None): - logging.Formatter.__init__(self, fmt, datefmt) - - def format(self, record): - level_name = record.levelname - msg = logging.Formatter.format(self, record) - - return LOG_COLORS.get(level_name, '%s') % msg - - -def add_handler(cls, level, fmt, colorful, **kwargs): - """Add a configured handler to the global logger.""" - global g_logger - - if isinstance(level, str): - level = getattr(logging, level.upper(), logging.DEBUG) - - handler = cls(**kwargs) - handler.setLevel(level) - - if colorful: - formatter = ColoredFormatter(fmt) - else: - formatter = logging.Formatter(fmt) - - handler.setFormatter(formatter) - g_logger.addHandler(handler) - - return handler - - -def add_stream_handler(level, fmt): - """Add a stream handler to the global logger.""" - return add_handler(logging.StreamHandler, level, fmt, True) - -def add_file_handler(level, fmt, filename, mode, backup_count, limit, when): - """Add a file handler to the global logger.""" - kwargs = {} - - # If the filename is not set, use the default filename - if filename is None: +class Log: + def __init__(self): logs_directory = config.Config('cobra', 'logs_directory').value logs_directory = os.path.join(config.Config().project_directory, logs_directory) if os.path.isdir(logs_directory) is not True: os.mkdir(logs_directory) - filename = logs_directory + os.sep + time.strftime("%Y-%m-%d") + '.log' - - kwargs['filename'] = filename - - # Choose the file_handler based on the passed arguments - if backup_count == 0: # Use FileHandler - cls = logging.FileHandler - kwargs['mode'] = mode - elif when is None: # Use RotatingFileHandler - cls = logging.handlers.RotatingFileHandler - kwargs['maxBytes'] = limit - kwargs['backupCount'] = backup_count - kwargs['mode'] = mode - else: # Use TimedRotatingFileHandler - cls = logging.handlers.TimedRotatingFileHandler - kwargs['when'] = when - kwargs['interval'] = limit - kwargs['backupCount'] = backup_count - - return add_handler(cls, level, fmt, False, **kwargs) - - -def init_logger(): - """Reload the global logger.""" - global g_logger - - if g_logger is None: - g_logger = logging.getLogger() - else: - logging.shutdown() - g_logger.handlers = [] - - g_logger.setLevel(logging.DEBUG) - - -def set_logger(filename=None, mode='a', level='DEBUG:INFO', - fmt=None, - backup_count=5, limit=20480, when=None): - """Configure the global logger.""" - level = level.split(':') - - if len(level) == 1: # Both set to the same level - s_level = f_level = level[0] - else: - s_level = level[0] # StreamHandler log level - f_level = level[1] # FileHandler log level - if fmt is not None: - if s_level == 'ERROR' or f_level == 'ERROR': - fmt = '[%(levelname)s] %(asctime)s %(message)s in \'%(filename)s:%(lineno)s\'' - else: - fmt = '[%(levelname)s] %(asctime)s %(message)s' - init_logger() - add_stream_handler(s_level, fmt) - add_file_handler(f_level, fmt, filename, mode, backup_count, limit, when) - - # Import the common log functions for convenient - import_log_funcs() - - -def import_log_funcs(): - """Import the common log functions from the global logger to the module.""" - global g_logger - - curr_mod = sys.modules[__name__] - log_funcs = ['debug', 'info', 'warning', 'error', 'critical', - 'exception'] - - for func_name in log_funcs: - func = getattr(g_logger, func_name) - setattr(curr_mod, func_name, func) - - -# Set a default logger -set_logger() + filename = os.path.join(logs_directory, 'cobra.log') + logging.config.dictConfig({ + 'version': 1, + 'disable_existing_loggers': True, + 'formatters': { + 'verbose': { + 'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s", + 'datefmt': "%Y-%m-%d %H:%M:%S" + }, + 'simple': { + 'format': '%(levelname)s %(message)s' + }, + }, + 'handlers': { + 'file': { + 'level': 'DEBUG', + 'class': 'cloghandler.ConcurrentRotatingFileHandler', + 'maxBytes': 1024 * 1024 * 10, + 'backupCount': 50, + 'delay': True, + 'filename': filename, + 'formatter': 'verbose' + } + }, + 'loggers': { + '': { + 'handlers': ['file'], + 'level': 'INFO', + }, + } + })