#!/usr/bin/env python

"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""

# 导入所需的标准库
import binascii  # 用于二进制和ASCII转换
import re        # 用于正则表达式操作
import string    # 提供字符串常量和工具
import sys      # 提供系统相关的功能

# 判断Python版本是否为Python 3及以上
PY3 = sys.version_info >= (3, 0)

# 根据Python版本设置不同的类型别名
if PY3:
    xrange = range              # Python 3中range替代了xrange
    text_type = str            # Python 3中str即为文本类型
    string_types = (str,)      # Python 3中字符串类型只有str
    unichr = chr               # Python 3中chr替代了unichr
else:
    text_type = unicode        # Python 2中使用unicode作为文本类型
    string_types = (basestring,) # Python 2中的字符串基类

# 用于识别十六进制编码字符的正则表达式
HEX_ENCODED_CHAR_REGEX = r"(?P<result>\\x[0-9A-Fa-f]{2})"

# 需要被安全编码为反斜杠表示的原始字符(如换行符编码为\n)
SAFE_ENCODE_SLASH_REPLACEMENTS = "\t\n\r\x0b\x0c"

# 不需要安全编码的字符集合
# 包含所有可打印字符，但不包含反斜杠和上面定义的需要特殊处理的字符
SAFE_CHARS = "".join([_ for _ in string.printable.replace('\\', '') if _ not in SAFE_ENCODE_SLASH_REPLACEMENTS])

# 十六进制编码值的前缀
HEX_ENCODED_PREFIX = r"\x"

# 用于临时标记十六进制编码前缀的字符串(防止重复编码)
HEX_ENCODED_PREFIX_MARKER = "__HEX_ENCODED_PREFIX__"

# 用于临时标记反斜杠字符的字符串
SLASH_MARKER = "__SLASH__"

def safecharencode(value):
    """
    将给定的字符串值转换为安全的表示形式
    
    参数:
        value: 需要编码的值，可以是字符串或列表
        
    返回:
        编码后的安全字符串或处理后的列表
    
    示例:
    >>> safecharencode(u'test123') == u'test123'
    True
    >>> safecharencode(u'test\x01\x02\xaf') == u'test\\\\x01\\\\x02\\xaf'
    True
    """

    retVal = value

    if isinstance(value, string_types):  # 如果输入是字符串类型
        if any(_ not in SAFE_CHARS for _ in value):  # 检查是否包含不安全字符
            # 临时替换已有的十六进制编码前缀和反斜杠
            retVal = retVal.replace(HEX_ENCODED_PREFIX, HEX_ENCODED_PREFIX_MARKER)
            retVal = retVal.replace('\\', SLASH_MARKER)

            # 处理特殊字符(如\n, \t等)
            for char in SAFE_ENCODE_SLASH_REPLACEMENTS:
                retVal = retVal.replace(char, repr(char).strip('\''))

            # 将不可打印字符转换为十六进制表示
            for char in set(retVal):
                if not (char in string.printable or isinstance(value, text_type) and ord(char) >= 160):
                    retVal = retVal.replace(char, '\\x%02x' % ord(char))

            # 恢复临时替换的标记
            retVal = retVal.replace(SLASH_MARKER, "\\\\")
            retVal = retVal.replace(HEX_ENCODED_PREFIX_MARKER, HEX_ENCODED_PREFIX)
    elif isinstance(value, list):  # 如果输入是列表
        for i in xrange(len(value)):
            retVal[i] = safecharencode(value[i])  # 递归处理列表中的每个元素

    return retVal

def safechardecode(value, binary=False):
    """
    safecharencode的反向函数，将安全编码的字符串解码回原始形式
    
    参数:
        value: 需要解码的值，可以是字符串或列表
        binary: 是否返回二进制格式，默认为False
        
    返回:
        解码后的原始字符串或处理后的列表
    """

    retVal = value
    if isinstance(value, string_types):  # 如果输入是字符串类型
        # 临时替换反斜杠
        retVal = retVal.replace('\\\\', SLASH_MARKER)

        # 解码所有十六进制编码的字符
        while True:
            match = re.search(HEX_ENCODED_CHAR_REGEX, retVal)
            if match:
                retVal = retVal.replace(match.group("result"), unichr(ord(binascii.unhexlify(match.group("result").lstrip("\\x")))))
            else:
                break

        # 还原特殊字符
        for char in SAFE_ENCODE_SLASH_REPLACEMENTS[::-1]:
            retVal = retVal.replace(repr(char).strip('\''), char)

        # 恢复反斜杠
        retVal = retVal.replace(SLASH_MARKER, '\\')

        # 如果需要二进制格式
        if binary:
            if isinstance(retVal, text_type):
                retVal = retVal.encode("utf8", errors="surrogatepass" if PY3 else "strict")

    elif isinstance(value, (list, tuple)):  # 如果输入是列表或元组
        for i in xrange(len(value)):
            retVal[i] = safechardecode(value[i])  # 递归处理每个元素

    return retVal
