fscan/Common/Parse.go
ZacharyZcR 2f9c213e80 refactor: 系统性清理common包中的死代码和未使用变量
主要清理内容:
- logging包:移除DetailedFormatter、JSONFormatter及相关方法
- output包:清理Manager和Statistics中的未使用方法
- parsers包:移除各Parser中的Validate()和GetStatistics()方法
- proxy包:清理Factory和Global中的所有未使用函数
- ProgressManager:移除未使用的进度条方法和字段
- globals:清理未使用的status变量

技术改进:
- 使用deadcode和golangci-lint工具系统性检测
- 保持代码结构清晰,添加清理注释
- 修复相关依赖引用问题
- 确保编译通过和功能正常

代码减少:移除约40个死代码函数和多个未使用字段
2025-08-06 08:14:00 +08:00

513 lines
14 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package common
import (
"fmt"
"sync"
"time"
"github.com/fatih/color"
"github.com/shadow1ng/fscan/common/i18n"
"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(i18n.GetText("parse_error_config_failed", err))
}
// 更新全局变量以保持兼容性
if err := updateGlobalVariables(result.Config, Info); err != nil {
return fmt.Errorf(i18n.GetText("parse_error_update_vars_failed", err))
}
// 报告警告
for _, warning := range result.Warnings {
LogBase(warning)
}
// 显示解析结果摘要
showParseSummary(result.Config)
// 同步变量到core包
syncToCore()
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(i18n.GetText("parse_error_empty_input"))
}
p.mu.Lock()
defer p.mu.Unlock()
if !p.initialized {
return nil, fmt.Errorf(i18n.GetText("parse_error_parser_not_init"))
}
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(i18n.GetText("parse_error_credential_failed", 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(i18n.GetText("parse_error_target_failed", 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(i18n.GetText("parse_error_network_failed", 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(i18n.GetText("parse_error_validation_failed", 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
}
// 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
}
// 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(i18n.GetText("target_hosts_found", joinStrings(config.Targets.Hosts, ", ")))
} else {
LogBase(i18n.GetText("target_hosts_count", joinStrings(config.Targets.Hosts[:5], ", "), len(config.Targets.Hosts)))
}
}
if len(config.Targets.URLs) > 0 {
if len(config.Targets.URLs) <= 3 {
LogBase(i18n.GetText("target_urls_found", joinStrings(config.Targets.URLs, ", ")))
} else {
LogBase(i18n.GetText("target_urls_count", joinStrings(config.Targets.URLs[:3], ", "), len(config.Targets.URLs)))
}
}
if len(config.Targets.Ports) > 0 {
if len(config.Targets.Ports) <= 20 {
LogBase(i18n.GetText("target_ports_found", joinInts(config.Targets.Ports, ", ")))
} else {
LogBase(i18n.GetText("target_ports_count", joinInts(config.Targets.Ports[:20], ", "), len(config.Targets.Ports)))
}
}
if len(config.Targets.ExcludePorts) > 0 {
LogBase(i18n.GetText("target_exclude_ports", joinInts(config.Targets.ExcludePorts, ", ")))
}
if config.Targets.LocalMode {
LogBase(i18n.GetText("target_local_mode"))
}
}
// 显示网络配置
if config.Network != nil {
if config.Network.HttpProxy != "" {
LogBase(i18n.GetText("network_http_proxy", config.Network.HttpProxy))
}
if config.Network.Socks5Proxy != "" {
LogBase(i18n.GetText("network_socks5_proxy", config.Network.Socks5Proxy))
}
if config.Network.Timeout > 0 {
LogBase(i18n.GetText("network_timeout", config.Network.Timeout))
}
if config.Network.WebTimeout > 0 {
LogBase(i18n.GetText("network_web_timeout", config.Network.WebTimeout))
}
}
// 显示凭据信息
if config.Credentials != nil {
if len(config.Credentials.Usernames) > 0 {
LogBase(i18n.GetText("credential_username_count", len(config.Credentials.Usernames)))
}
if len(config.Credentials.Passwords) > 0 {
LogBase(i18n.GetText("credential_password_count", len(config.Credentials.Passwords)))
}
if len(config.Credentials.HashValues) > 0 {
LogBase(i18n.GetText("credential_hash_count", 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)
// 设置协调输出函数使用LogWithProgress
newLogger.SetCoordinatedOutput(LogWithProgress)
// 更新全局日志管理器
globalLogger = newLogger
// status变量已移除如需获取状态请直接调用newLogger.GetScanStatus()
}
}