#! /usr/bin/env python
# -*- coding: utf-8 -*-

"""
Copyright (c) 2013-2014 tangscan developers (http://www.wooyun.org/)
See the file 'docs/COPYING' for copying permission
author: fate0 <fate0@wooyun.org>
"""

import os
import sys
sys.path.append(os.path.join(os.path.dirname(__file__), '../thirdparty'))

import json
import colorama
from dotted import DottedDict
from abc import ABCMeta, abstractmethod

colorama.init()


class TSLogLevel(object):
    """
    日志级别
    """
    debug = 1
    info = 2
    warning = 3
    error = 4


class TSRef(object):
    """
    引用相关
    """
    url = "相关链接"  # url
    wooyun = "乌云案例"  # wooyun id: 2014-077274
    ssvid = 3  # sebug id


class TSConvert(object):
    """
    参数转换
    """
    @staticmethod
    def int_field(string):
        assert isinstance(string, (basestring, int))
        return int(string)

    @staticmethod
    def str_field(string):
        assert isinstance(string, basestring)
        return str(string)

    @staticmethod
    def bool_field(string):
        assert isinstance(string, (basestring, int))
        if string.lower() == 'false' or string == '0':
            return False
        return bool(string)

    @staticmethod
    def json_field(string):
        assert isinstance(string, basestring)
        return json.loads(string)

    @staticmethod
    def url_field(string):
        assert isinstance(string, basestring)
        domain = string if string.startswith('http') else "http://{domain}".format(domain=string)
        print domain
        return str(domain)

    @staticmethod
    def email_field(string):
        # TODO: there is no need to implement this in here
        assert isinstance(string, basestring)
        return string


class TSLicense(object):
    """
    相关版权信息
    """
    TS = 1
    MIT = 2
    BSD = 3
    GPL = 4
    LGPL = 5
    APACHE = 6


class TSSeverity(object):
    """
    危害等级
    """
    high = '高'
    medium = '中'
    low = '低'


class TSType(object):
    injection = '注入'
    xss = 'xss跨站脚本攻击'
    xxe = 'xml外部实体攻击'
    file_upload = '任意文件上传'
    file_operation = '任意文件操作'
    file_traversal = '目录遍历'
    rce = '远程命令/代码执行'
    lfi = '本地文件包含'
    rfi = '远程文件包含'
    info_leak = '信息泄漏'
    misconfiguration = '错误配置'
    other = '其他'


class TSExploit(object):
    __metaclass__ = ABCMeta

    ref = TSRef()
    type = TSType()
    convert = TSConvert()
    license = TSLicense()
    severity = TSSeverity()

    def __init__(self):
        super(TSExploit, self).__init__()
        self.option = {}
        self.result = {}
        self.log_level = TSLogLevel.info

    def register_option(self, dict_option):
        assert isinstance(dict_option, dict)
        self.option = DottedDict(dict_option)

    def register_result(self, dict_result):
        assert isinstance(dict_result, dict)
        self.result = DottedDict(dict_result)

    @staticmethod
    def is_sanbox():
        import os
        if os.environ.get('APP_NAME', None):
            return True

    @abstractmethod
    def verify(self):
        pass

    @abstractmethod
    def exploit(self):
        pass

    def print_debug(self, content):
        if self.log_level <= TSLogLevel.debug:
            if self.is_sanbox():
                print("{content}".format(content=content))
            else:
                print("{debug_color}[debug]: {content} {color_reset}".format(
                    debug_color=colorama.Fore.CYAN, content=content, color_reset=colorama.Fore.RESET))

    def print_info(self, content):
        if self.log_level <= TSLogLevel.info:
            if self.is_sanbox():
                print("{content}".format(content=content))
            else:
                print("{info_color}[info]: {content} {color_reset}".format(
                    info_color=colorama.Fore.GREEN, content=content, color_reset=colorama.Fore.RESET))

    def print_warning(self, content):
        if self.log_level <= TSLogLevel.warning:
            if self.is_sanbox():
                print("{content}".format(content=content))
            else:
                print("{warning_color}[warning]: {content} {color_reset}".format(
                    warning_color=colorama.Fore.YELLOW, content=content, color_reset=colorama.Fore.RESET))

    def print_error(self, content):
        if self.log_level <= TSLogLevel.error:
            if self.is_sanbox():
                print("{content}".format(content=content))
            else:
                print("{error_color}[error]: {content} {color_reset}".format(
                    error_color=colorama.Fore.RED, content=content, color_reset=colorama.Fore.RESET))

