mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 05:56:46 +08:00

主要改进: - 模块化设计:将549行Parse.go拆分为6个专用解析器 - 性能优化:添加文件缓存、并发处理和去重机制 - 增强验证:实现配置冲突检测和参数验证 - 改善体验:清理冗余警告,添加解析结果摘要显示 - 向后兼容:保持所有原有API接口不变 新增模块: - FileReader: 高性能文件读取和缓存 - CredentialParser: 用户名密码解析 - TargetParser: 主机目标解析 - NetworkParser: 网络配置解析 - ValidationParser: 参数验证和冲突检测 - Types: 统一的数据结构定义 修复问题: - 消除重复的"Web超时时间大于普通超时时间"警告 - 添加目标主机、端口、代理等配置信息显示 - 删除说教性安全警告,保留技术性提示
684 lines
18 KiB
Go
684 lines
18 KiB
Go
package Common
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/fatih/color"
|
|
"github.com/shadow1ng/fscan/Common/logging"
|
|
"github.com/shadow1ng/fscan/Common/parsers"
|
|
)
|
|
|
|
// ParsedConfiguration 解析后的完整配置(兼容旧代码)
|
|
type ParsedConfiguration struct {
|
|
*parsers.ParsedConfig
|
|
}
|
|
|
|
// Parser 主解析器
|
|
type Parser struct {
|
|
mu sync.RWMutex
|
|
fileReader *parsers.FileReader
|
|
credentialParser *parsers.CredentialParser
|
|
targetParser *parsers.TargetParser
|
|
networkParser *parsers.NetworkParser
|
|
validationParser *parsers.ValidationParser
|
|
options *parsers.ParserOptions
|
|
initialized bool
|
|
}
|
|
|
|
// NewParser 创建新的解析器实例
|
|
func NewParser(options *parsers.ParserOptions) *Parser {
|
|
if options == nil {
|
|
options = parsers.DefaultParserOptions()
|
|
}
|
|
|
|
// 创建文件读取器
|
|
fileReader := parsers.NewFileReader(nil)
|
|
|
|
// 创建各个子解析器
|
|
credentialParser := parsers.NewCredentialParser(fileReader, nil)
|
|
targetParser := parsers.NewTargetParser(fileReader, nil)
|
|
networkParser := parsers.NewNetworkParser(nil)
|
|
validationParser := parsers.NewValidationParser(nil)
|
|
|
|
return &Parser{
|
|
fileReader: fileReader,
|
|
credentialParser: credentialParser,
|
|
targetParser: targetParser,
|
|
networkParser: networkParser,
|
|
validationParser: validationParser,
|
|
options: options,
|
|
initialized: true,
|
|
}
|
|
}
|
|
|
|
// 全局解析器实例
|
|
var globalParser *Parser
|
|
var initOnce sync.Once
|
|
|
|
// getGlobalParser 获取全局解析器实例
|
|
func getGlobalParser() *Parser {
|
|
initOnce.Do(func() {
|
|
globalParser = NewParser(nil)
|
|
})
|
|
return globalParser
|
|
}
|
|
|
|
// Parse 主解析函数 - 保持与原版本兼容的接口
|
|
func Parse(Info *HostInfo) error {
|
|
// 首先应用LogLevel配置到日志系统
|
|
applyLogLevel()
|
|
|
|
parser := getGlobalParser()
|
|
|
|
// 构建输入参数
|
|
input := &AllInputs{
|
|
Credential: &parsers.CredentialInput{
|
|
Username: Username,
|
|
Password: Password,
|
|
AddUsers: AddUsers,
|
|
AddPasswords: AddPasswords,
|
|
HashValue: HashValue,
|
|
SshKeyPath: SshKeyPath,
|
|
Domain: Domain,
|
|
UsersFile: UsersFile,
|
|
PasswordsFile: PasswordsFile,
|
|
HashFile: HashFile,
|
|
},
|
|
Target: &parsers.TargetInput{
|
|
Host: Info.Host,
|
|
HostsFile: HostsFile,
|
|
ExcludeHosts: ExcludeHosts,
|
|
Ports: Ports,
|
|
PortsFile: PortsFile,
|
|
AddPorts: AddPorts,
|
|
ExcludePorts: ExcludePorts,
|
|
TargetURL: TargetURL,
|
|
URLsFile: URLsFile,
|
|
HostPort: HostPort,
|
|
LocalMode: LocalMode,
|
|
},
|
|
Network: &parsers.NetworkInput{
|
|
HttpProxy: HttpProxy,
|
|
Socks5Proxy: Socks5Proxy,
|
|
Timeout: Timeout,
|
|
WebTimeout: WebTimeout,
|
|
DisablePing: DisablePing,
|
|
DnsLog: DnsLog,
|
|
UserAgent: UserAgent,
|
|
Cookie: Cookie,
|
|
},
|
|
}
|
|
|
|
// 执行解析
|
|
result, err := parser.ParseAll(input)
|
|
if err != nil {
|
|
return fmt.Errorf("解析配置失败: %v", err)
|
|
}
|
|
|
|
// 更新全局变量以保持兼容性
|
|
if err := updateGlobalVariables(result.Config, Info); err != nil {
|
|
return fmt.Errorf("更新全局变量失败: %v", err)
|
|
}
|
|
|
|
// 报告警告
|
|
for _, warning := range result.Warnings {
|
|
LogBase(warning)
|
|
}
|
|
|
|
// 显示解析结果摘要
|
|
showParseSummary(result.Config)
|
|
|
|
return nil
|
|
}
|
|
|
|
// AllInputs 所有输入参数的集合
|
|
type AllInputs struct {
|
|
Credential *parsers.CredentialInput `json:"credential"`
|
|
Target *parsers.TargetInput `json:"target"`
|
|
Network *parsers.NetworkInput `json:"network"`
|
|
}
|
|
|
|
// ParseAll 解析所有配置
|
|
func (p *Parser) ParseAll(input *AllInputs) (*parsers.ParseResult, error) {
|
|
if input == nil {
|
|
return nil, fmt.Errorf("输入参数为空")
|
|
}
|
|
|
|
p.mu.Lock()
|
|
defer p.mu.Unlock()
|
|
|
|
if !p.initialized {
|
|
return nil, fmt.Errorf("解析器未初始化")
|
|
}
|
|
|
|
startTime := time.Now()
|
|
result := &parsers.ParseResult{
|
|
Config: &parsers.ParsedConfig{},
|
|
Success: true,
|
|
}
|
|
|
|
var allErrors []error
|
|
var allWarnings []string
|
|
|
|
// 解析凭据配置
|
|
if input.Credential != nil {
|
|
credResult, err := p.credentialParser.Parse(input.Credential, p.options)
|
|
if err != nil {
|
|
allErrors = append(allErrors, fmt.Errorf("凭据解析失败: %v", err))
|
|
} else {
|
|
result.Config.Credentials = credResult.Config.Credentials
|
|
allErrors = append(allErrors, credResult.Errors...)
|
|
allWarnings = append(allWarnings, credResult.Warnings...)
|
|
}
|
|
}
|
|
|
|
// 解析目标配置
|
|
if input.Target != nil {
|
|
targetResult, err := p.targetParser.Parse(input.Target, p.options)
|
|
if err != nil {
|
|
allErrors = append(allErrors, fmt.Errorf("目标解析失败: %v", err))
|
|
} else {
|
|
result.Config.Targets = targetResult.Config.Targets
|
|
allErrors = append(allErrors, targetResult.Errors...)
|
|
allWarnings = append(allWarnings, targetResult.Warnings...)
|
|
}
|
|
}
|
|
|
|
// 解析网络配置
|
|
if input.Network != nil {
|
|
networkResult, err := p.networkParser.Parse(input.Network, p.options)
|
|
if err != nil {
|
|
allErrors = append(allErrors, fmt.Errorf("网络解析失败: %v", err))
|
|
} else {
|
|
result.Config.Network = networkResult.Config.Network
|
|
allErrors = append(allErrors, networkResult.Errors...)
|
|
allWarnings = append(allWarnings, networkResult.Warnings...)
|
|
}
|
|
}
|
|
|
|
// 执行验证
|
|
validationInput := &parsers.ValidationInput{
|
|
ScanMode: ScanMode,
|
|
LocalMode: LocalMode,
|
|
HasHosts: input.Target != nil && (input.Target.Host != "" || input.Target.HostsFile != ""),
|
|
HasURLs: input.Target != nil && (input.Target.TargetURL != "" || input.Target.URLsFile != ""),
|
|
HasPorts: input.Target != nil && (input.Target.Ports != "" || input.Target.PortsFile != ""),
|
|
HasProxy: input.Network != nil && (input.Network.HttpProxy != "" || input.Network.Socks5Proxy != ""),
|
|
DisablePing: input.Network != nil && input.Network.DisablePing,
|
|
HasCredentials: input.Credential != nil && (input.Credential.Username != "" || input.Credential.UsersFile != ""),
|
|
}
|
|
|
|
validationResult, err := p.validationParser.Parse(validationInput, result.Config, p.options)
|
|
if err != nil {
|
|
allErrors = append(allErrors, fmt.Errorf("验证失败: %v", err))
|
|
} else {
|
|
result.Config.Validation = validationResult.Config.Validation
|
|
allErrors = append(allErrors, validationResult.Errors...)
|
|
allWarnings = append(allWarnings, validationResult.Warnings...)
|
|
}
|
|
|
|
// 汇总结果
|
|
result.Errors = allErrors
|
|
result.Warnings = allWarnings
|
|
result.ParseTime = time.Since(startTime)
|
|
result.Success = len(allErrors) == 0
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// updateGlobalVariables 更新全局变量以保持向后兼容性
|
|
func updateGlobalVariables(config *parsers.ParsedConfig, info *HostInfo) error {
|
|
if config == nil {
|
|
return nil
|
|
}
|
|
|
|
// 更新凭据相关全局变量
|
|
if config.Credentials != nil {
|
|
if len(config.Credentials.Usernames) > 0 {
|
|
// 更新全局用户字典
|
|
for serviceName := range Userdict {
|
|
Userdict[serviceName] = config.Credentials.Usernames
|
|
}
|
|
}
|
|
|
|
if len(config.Credentials.Passwords) > 0 {
|
|
Passwords = config.Credentials.Passwords
|
|
}
|
|
|
|
if len(config.Credentials.HashValues) > 0 {
|
|
HashValues = config.Credentials.HashValues
|
|
}
|
|
|
|
if len(config.Credentials.HashBytes) > 0 {
|
|
HashBytes = config.Credentials.HashBytes
|
|
}
|
|
}
|
|
|
|
// 更新目标相关全局变量
|
|
if config.Targets != nil {
|
|
if len(config.Targets.Hosts) > 0 {
|
|
if info.Host == "" {
|
|
info.Host = joinStrings(config.Targets.Hosts, ",")
|
|
} else {
|
|
info.Host += "," + joinStrings(config.Targets.Hosts, ",")
|
|
}
|
|
}
|
|
|
|
if len(config.Targets.URLs) > 0 {
|
|
URLs = config.Targets.URLs
|
|
}
|
|
|
|
if len(config.Targets.Ports) > 0 {
|
|
Ports = joinInts(config.Targets.Ports, ",")
|
|
}
|
|
|
|
if len(config.Targets.ExcludePorts) > 0 {
|
|
ExcludePorts = joinInts(config.Targets.ExcludePorts, ",")
|
|
}
|
|
|
|
if len(config.Targets.HostPorts) > 0 {
|
|
HostPort = config.Targets.HostPorts
|
|
}
|
|
}
|
|
|
|
// 更新网络相关全局变量
|
|
if config.Network != nil {
|
|
if config.Network.HttpProxy != "" {
|
|
HttpProxy = config.Network.HttpProxy
|
|
}
|
|
|
|
if config.Network.Socks5Proxy != "" {
|
|
Socks5Proxy = config.Network.Socks5Proxy
|
|
}
|
|
|
|
if config.Network.Timeout > 0 {
|
|
Timeout = int64(config.Network.Timeout.Seconds())
|
|
}
|
|
|
|
if config.Network.WebTimeout > 0 {
|
|
WebTimeout = int64(config.Network.WebTimeout.Seconds())
|
|
}
|
|
|
|
if config.Network.UserAgent != "" {
|
|
UserAgent = config.Network.UserAgent
|
|
}
|
|
|
|
if config.Network.Cookie != "" {
|
|
Cookie = config.Network.Cookie
|
|
}
|
|
|
|
DisablePing = config.Network.DisablePing
|
|
DnsLog = config.Network.EnableDNSLog
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 保持原有的独立解析函数以确保向后兼容性
|
|
|
|
// ParseUser 解析用户名配置 - 兼容接口
|
|
func ParseUser() error {
|
|
parser := getGlobalParser()
|
|
input := &parsers.CredentialInput{
|
|
Username: Username,
|
|
UsersFile: UsersFile,
|
|
AddUsers: AddUsers,
|
|
}
|
|
|
|
result, err := parser.credentialParser.Parse(input, parser.options)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 更新全局变量
|
|
if len(result.Config.Credentials.Usernames) > 0 {
|
|
for serviceName := range Userdict {
|
|
Userdict[serviceName] = result.Config.Credentials.Usernames
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ParsePass 解析密码配置 - 兼容接口
|
|
func ParsePass(Info *HostInfo) error {
|
|
parser := getGlobalParser()
|
|
|
|
// 处理密码
|
|
credInput := &parsers.CredentialInput{
|
|
Password: Password,
|
|
PasswordsFile: PasswordsFile,
|
|
AddPasswords: AddPasswords,
|
|
HashValue: HashValue,
|
|
HashFile: HashFile,
|
|
}
|
|
|
|
credResult, err := parser.credentialParser.Parse(credInput, parser.options)
|
|
if err != nil {
|
|
LogError(fmt.Sprintf("密码解析失败: %v", err))
|
|
} else if credResult.Config.Credentials != nil {
|
|
if len(credResult.Config.Credentials.Passwords) > 0 {
|
|
Passwords = credResult.Config.Credentials.Passwords
|
|
}
|
|
if len(credResult.Config.Credentials.HashValues) > 0 {
|
|
HashValues = credResult.Config.Credentials.HashValues
|
|
}
|
|
if len(credResult.Config.Credentials.HashBytes) > 0 {
|
|
HashBytes = credResult.Config.Credentials.HashBytes
|
|
}
|
|
}
|
|
|
|
// 处理URL和主机
|
|
targetInput := &parsers.TargetInput{
|
|
TargetURL: TargetURL,
|
|
URLsFile: URLsFile,
|
|
Host: Info.Host,
|
|
HostsFile: HostsFile,
|
|
Ports: Ports,
|
|
PortsFile: PortsFile,
|
|
AddPorts: AddPorts,
|
|
ExcludePorts: ExcludePorts,
|
|
}
|
|
|
|
targetResult, err := parser.targetParser.Parse(targetInput, parser.options)
|
|
if err != nil {
|
|
LogError(fmt.Sprintf("目标解析失败: %v", err))
|
|
} else if targetResult.Config.Targets != nil {
|
|
if len(targetResult.Config.Targets.URLs) > 0 {
|
|
URLs = targetResult.Config.Targets.URLs
|
|
}
|
|
if len(targetResult.Config.Targets.Hosts) > 0 {
|
|
Info.Host = joinStrings(targetResult.Config.Targets.Hosts, ",")
|
|
}
|
|
if len(targetResult.Config.Targets.Ports) > 0 {
|
|
Ports = joinInts(targetResult.Config.Targets.Ports, ",")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ParseInput 解析输入参数 - 兼容接口
|
|
func ParseInput(Info *HostInfo) error {
|
|
parser := getGlobalParser()
|
|
|
|
// 网络配置解析
|
|
networkInput := &parsers.NetworkInput{
|
|
HttpProxy: HttpProxy,
|
|
Socks5Proxy: Socks5Proxy,
|
|
Timeout: Timeout,
|
|
WebTimeout: WebTimeout,
|
|
DisablePing: DisablePing,
|
|
DnsLog: DnsLog,
|
|
UserAgent: UserAgent,
|
|
Cookie: Cookie,
|
|
}
|
|
|
|
networkResult, err := parser.networkParser.Parse(networkInput, parser.options)
|
|
if err != nil {
|
|
return fmt.Errorf("网络配置解析失败: %v", err)
|
|
}
|
|
|
|
// 更新全局变量
|
|
if networkResult.Config.Network != nil {
|
|
HttpProxy = networkResult.Config.Network.HttpProxy
|
|
Socks5Proxy = networkResult.Config.Network.Socks5Proxy
|
|
if networkResult.Config.Network.Timeout > 0 {
|
|
Timeout = int64(networkResult.Config.Network.Timeout.Seconds())
|
|
}
|
|
if networkResult.Config.Network.WebTimeout > 0 {
|
|
WebTimeout = int64(networkResult.Config.Network.WebTimeout.Seconds())
|
|
}
|
|
UserAgent = networkResult.Config.Network.UserAgent
|
|
Cookie = networkResult.Config.Network.Cookie
|
|
DisablePing = networkResult.Config.Network.DisablePing
|
|
DnsLog = networkResult.Config.Network.EnableDNSLog
|
|
}
|
|
|
|
// 验证配置
|
|
validationInput := &parsers.ValidationInput{
|
|
ScanMode: ScanMode,
|
|
LocalMode: LocalMode,
|
|
HasHosts: Info.Host != "" || HostsFile != "",
|
|
HasURLs: TargetURL != "" || URLsFile != "",
|
|
HasPorts: Ports != "" || PortsFile != "",
|
|
HasProxy: HttpProxy != "" || Socks5Proxy != "",
|
|
DisablePing: DisablePing,
|
|
}
|
|
|
|
validationResult, err := parser.validationParser.Parse(validationInput, nil, parser.options)
|
|
if err != nil {
|
|
return fmt.Errorf("参数验证失败: %v", err)
|
|
}
|
|
|
|
// 报告验证警告
|
|
for _, warning := range validationResult.Warnings {
|
|
LogBase(warning)
|
|
}
|
|
|
|
// 如果有严重错误,返回错误
|
|
for _, validationError := range validationResult.Errors {
|
|
LogError(validationError.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 保持原有的工具函数
|
|
|
|
// ReadFileLines 读取文件行 - 兼容接口
|
|
func ReadFileLines(filename string) ([]string, error) {
|
|
parser := getGlobalParser()
|
|
result, err := parser.fileReader.ReadFile(filename)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return result.Lines, nil
|
|
}
|
|
|
|
// RemoveDuplicate 去重函数 - 保持原有实现
|
|
func RemoveDuplicate(old []string) []string {
|
|
temp := make(map[string]struct{})
|
|
var result []string
|
|
|
|
for _, item := range old {
|
|
if _, exists := temp[item]; !exists {
|
|
temp[item] = struct{}{}
|
|
result = append(result, item)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// 辅助函数
|
|
|
|
// joinStrings 连接字符串切片
|
|
func joinStrings(slice []string, sep string) string {
|
|
if len(slice) == 0 {
|
|
return ""
|
|
}
|
|
result := slice[0]
|
|
for i := 1; i < len(slice); i++ {
|
|
result += sep + slice[i]
|
|
}
|
|
return result
|
|
}
|
|
|
|
// joinInts 连接整数切片
|
|
func joinInts(slice []int, sep string) string {
|
|
if len(slice) == 0 {
|
|
return ""
|
|
}
|
|
result := fmt.Sprintf("%d", slice[0])
|
|
for i := 1; i < len(slice); i++ {
|
|
result += sep + fmt.Sprintf("%d", slice[i])
|
|
}
|
|
return result
|
|
}
|
|
|
|
// GetParser 获取解析器实例 - 新增API
|
|
func GetParser() *Parser {
|
|
return getGlobalParser()
|
|
}
|
|
|
|
// SetParserOptions 设置解析器选项 - 新增API
|
|
func SetParserOptions(options *parsers.ParserOptions) {
|
|
globalParser = NewParser(options)
|
|
}
|
|
|
|
// ClearParserCache 清空解析器缓存 - 新增API
|
|
func ClearParserCache() {
|
|
if globalParser != nil && globalParser.fileReader != nil {
|
|
globalParser.fileReader.ClearCache()
|
|
}
|
|
}
|
|
|
|
// showParseSummary 显示解析结果摘要
|
|
func showParseSummary(config *parsers.ParsedConfig) {
|
|
if config == nil {
|
|
return
|
|
}
|
|
|
|
// 显示目标信息
|
|
if config.Targets != nil {
|
|
if len(config.Targets.Hosts) > 0 {
|
|
if len(config.Targets.Hosts) <= 5 {
|
|
LogBase(fmt.Sprintf("目标主机: %s", joinStrings(config.Targets.Hosts, ", ")))
|
|
} else {
|
|
LogBase(fmt.Sprintf("目标主机: %s ... (共%d个)", joinStrings(config.Targets.Hosts[:5], ", "), len(config.Targets.Hosts)))
|
|
}
|
|
}
|
|
|
|
if len(config.Targets.URLs) > 0 {
|
|
if len(config.Targets.URLs) <= 3 {
|
|
LogBase(fmt.Sprintf("目标URL: %s", joinStrings(config.Targets.URLs, ", ")))
|
|
} else {
|
|
LogBase(fmt.Sprintf("目标URL: %s ... (共%d个)", joinStrings(config.Targets.URLs[:3], ", "), len(config.Targets.URLs)))
|
|
}
|
|
}
|
|
|
|
if len(config.Targets.Ports) > 0 {
|
|
if len(config.Targets.Ports) <= 20 {
|
|
LogBase(fmt.Sprintf("扫描端口: %s", joinInts(config.Targets.Ports, ", ")))
|
|
} else {
|
|
LogBase(fmt.Sprintf("扫描端口: %s ... (共%d个)", joinInts(config.Targets.Ports[:20], ", "), len(config.Targets.Ports)))
|
|
}
|
|
}
|
|
|
|
if len(config.Targets.ExcludePorts) > 0 {
|
|
LogBase(fmt.Sprintf("排除端口: %s", joinInts(config.Targets.ExcludePorts, ", ")))
|
|
}
|
|
|
|
if config.Targets.LocalMode {
|
|
LogBase("本地扫描模式")
|
|
}
|
|
}
|
|
|
|
// 显示网络配置
|
|
if config.Network != nil {
|
|
if config.Network.HttpProxy != "" {
|
|
LogBase(fmt.Sprintf("HTTP代理: %s", config.Network.HttpProxy))
|
|
}
|
|
if config.Network.Socks5Proxy != "" {
|
|
LogBase(fmt.Sprintf("Socks5代理: %s", config.Network.Socks5Proxy))
|
|
}
|
|
if config.Network.Timeout > 0 {
|
|
LogBase(fmt.Sprintf("连接超时: %v", config.Network.Timeout))
|
|
}
|
|
if config.Network.WebTimeout > 0 {
|
|
LogBase(fmt.Sprintf("Web超时: %v", config.Network.WebTimeout))
|
|
}
|
|
}
|
|
|
|
// 显示凭据信息
|
|
if config.Credentials != nil {
|
|
if len(config.Credentials.Usernames) > 0 {
|
|
LogBase(fmt.Sprintf("用户名数量: %d", len(config.Credentials.Usernames)))
|
|
}
|
|
if len(config.Credentials.Passwords) > 0 {
|
|
LogBase(fmt.Sprintf("密码数量: %d", len(config.Credentials.Passwords)))
|
|
}
|
|
if len(config.Credentials.HashValues) > 0 {
|
|
LogBase(fmt.Sprintf("Hash数量: %d", len(config.Credentials.HashValues)))
|
|
}
|
|
}
|
|
}
|
|
|
|
// applyLogLevel 应用LogLevel配置到日志系统
|
|
func applyLogLevel() {
|
|
if LogLevel == "" {
|
|
return // 使用默认级别
|
|
}
|
|
|
|
// 根据LogLevel字符串获取对应的日志级别
|
|
var level logging.LogLevel
|
|
switch LogLevel {
|
|
case LogLevelAll:
|
|
level = logging.LevelAll
|
|
case LogLevelError:
|
|
level = logging.LevelError
|
|
case LogLevelBase:
|
|
level = logging.LevelBase
|
|
case LogLevelInfo:
|
|
level = logging.LevelInfo
|
|
case LogLevelSuccess:
|
|
level = logging.LevelSuccess
|
|
case LogLevelDebug:
|
|
level = logging.LevelDebug
|
|
case LogLevelInfoSuccess:
|
|
level = logging.LevelInfoSuccess
|
|
case LogLevelBaseInfoSuccess:
|
|
level = logging.LevelBaseInfoSuccess
|
|
default:
|
|
// 向后兼容:如果是老的字符串格式
|
|
switch LogLevel {
|
|
case "ALL":
|
|
level = logging.LevelAll
|
|
case "ERROR":
|
|
level = logging.LevelError
|
|
case "BASE":
|
|
level = logging.LevelBase
|
|
case "INFO":
|
|
level = logging.LevelInfo
|
|
case "SUCCESS":
|
|
level = logging.LevelSuccess
|
|
case "DEBUG":
|
|
level = logging.LevelDebug
|
|
case "debug":
|
|
level = logging.LevelAll // 兼容旧的debug行为
|
|
default:
|
|
return // 无效的级别,保持默认
|
|
}
|
|
}
|
|
|
|
// 更新全局日志管理器的级别
|
|
if globalLogger != nil {
|
|
config := &logging.LoggerConfig{
|
|
Level: level,
|
|
EnableColor: !NoColor,
|
|
SlowOutput: SlowLogOutput,
|
|
ShowProgress: true,
|
|
StartTime: StartTime,
|
|
LevelColors: map[logging.LogLevel]color.Attribute{
|
|
logging.LevelError: color.FgBlue,
|
|
logging.LevelBase: color.FgYellow,
|
|
logging.LevelInfo: color.FgGreen,
|
|
logging.LevelSuccess: color.FgRed,
|
|
logging.LevelDebug: color.FgWhite,
|
|
},
|
|
}
|
|
|
|
newLogger := logging.NewLogger(config)
|
|
if ProgressBar != nil {
|
|
newLogger.SetProgressBar(ProgressBar)
|
|
}
|
|
newLogger.SetOutputMutex(&OutputMutex)
|
|
|
|
// 更新全局日志管理器
|
|
globalLogger = newLogger
|
|
status = newLogger.GetScanStatus()
|
|
}
|
|
} |