#!/usr/bin/env python

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

# 导入所需的模块
import re

from lib.core.common import Backend  # 导入后端处理模块
from lib.core.common import Format   # 导入格式化处理模块
from lib.core.common import hashDBWrite  # 导入哈希数据库写入函数
from lib.core.data import kb  # 导入知识库模块
from lib.core.data import logger  # 导入日志记录模块
from lib.core.enums import HASHDB_KEYS  # 导入哈希数据库键值枚举
from lib.core.enums import OS  # 导入操作系统枚举
from lib.core.settings import SUPPORTED_DBMS  # 导入支持的数据库管理系统列表

def setDbms(dbms):
    """
    设置数据库管理系统的指纹信息到知识库中
    @param dbms: 要设置的数据库管理系统名称
    @type dbms: C{str} 字符串类型
    """

    # 将数据库类型写入哈希数据库,用于后续查询和缓存
    hashDBWrite(HASHDB_KEYS.DBMS, dbms)

    # 构造一个正则表达式模式,用所有支持的数据库类型组成
    # 例如: (MySQL|Oracle|PostgreSQL|Microsoft SQL Server)
    _ = "(%s)" % ('|'.join(SUPPORTED_DBMS))
    # 使用正则表达式匹配输入的数据库类型,不区分大小写
    # \A表示字符串开头,( |\Z)表示后面跟空格或字符串结尾
    _ = re.search(r"\A%s( |\Z)" % _, dbms, re.I)

    if _:
        # 如果匹配成功,提取匹配的数据库类型名称
        dbms = _.group(1)

    # 设置后端数据库类型,用于后续的数据库操作
    Backend.setDbms(dbms)
    if kb.resolutionDbms:
        # 如果存在解析后的数据库类型(可能是更精确的版本),则更新到哈希数据库
        hashDBWrite(HASHDB_KEYS.DBMS, kb.resolutionDbms)

    # 记录日志,输出识别到的数据库类型,方便用户查看
    logger.info("the back-end DBMS is %s" % Backend.getDbms())

def setOs():
    """
    设置目标系统的操作系统信息
    这个函数会解析banner中的操作系统指纹信息,并设置相关参数
    kb.bannerFp字典示例:
    {
      'sp': set(['Service Pack 4']),     # 系统补丁包信息
      'dbmsVersion': '8.00.194',         # 数据库版本
      'dbmsServicePack': '0',            # 数据库补丁包版本
      'distrib': set(['2000']),          # 系统发行版本
      'dbmsRelease': '2000',             # 数据库发行版本
      'type': set(['Windows'])           # 操作系统类型
    }
    """

    # 用于存储要输出的系统信息描述
    infoMsg = ""

    # 如果没有banner指纹信息,说明无法获取系统信息,直接返回
    if not kb.bannerFp:
        return

    # 如果banner中包含操作系统类型信息
    if "type" in kb.bannerFp:
        # 设置操作系统类型(如Windows、Linux等)
        Backend.setOs(Format.humanize(kb.bannerFp["type"]))
        infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs()

    # 如果包含系统发行版本信息(如Windows 2000、Windows XP等)
    if "distrib" in kb.bannerFp:
        kb.osVersion = Format.humanize(kb.bannerFp["distrib"])
        infoMsg += " %s" % kb.osVersion

    # 如果包含系统补丁包信息(Service Pack)
    if "sp" in kb.bannerFp:
        # 提取补丁包版本号,去掉"Service Pack "前缀,只保留数字
        kb.osSP = int(Format.humanize(kb.bannerFp["sp"]).replace("Service Pack ", ""))

    # 如果是Windows系统但没有补丁包信息,则默认设置为SP0
    elif "sp" not in kb.bannerFp and Backend.isOs(OS.WINDOWS):
        kb.osSP = 0

    # 如果有完整的系统信息(系统类型、版本和补丁包),则在输出中添加补丁包信息
    if Backend.getOs() and kb.osVersion and kb.osSP:
        infoMsg += " Service Pack %d" % kb.osSP

    # 如果收集到了系统信息,则记录到日志中
    if infoMsg:
        logger.info(infoMsg)

    # 将确定的操作系统类型写入哈希数据库,用于后续查询
    hashDBWrite(HASHDB_KEYS.OS, Backend.getOs())
