package common /* common.go - 简化的统一入口 移除所有向后兼容层,提供清晰的模块化接口。 直接导出各子模块的核心功能,避免代码债务。 */ import ( "context" "crypto/tls" "fmt" "net" "sync" "time" "github.com/shadow1ng/fscan/common/base" "github.com/shadow1ng/fscan/common/logging" "github.com/shadow1ng/fscan/common/output" "github.com/shadow1ng/fscan/common/proxy" ) // ============================================================================= // 核心类型导出 - 直接从core模块导出 // ============================================================================= type HostInfo = base.HostInfo type ScanPlugin = base.ScanPlugin // 插件类型常量 const ( PluginTypeWeb = base.PluginTypeWeb PluginTypeLocal = base.PluginTypeLocal ) // 全局插件管理器 var PluginManager = base.LegacyPluginManager // ============================================================================= // 核心功能导出 - 直接调用对应模块 // ============================================================================= // 已移除未使用的 RegisterPlugin 方法 // GetGlobalPluginManager 函数已删除(死代码清理) // ============================================================================= // 日志系统简化接口 // ============================================================================= var globalLogger *logging.Logger var loggerMutex sync.Mutex func getGlobalLogger() *logging.Logger { loggerMutex.Lock() defer loggerMutex.Unlock() if globalLogger == nil { level := getLogLevelFromString(LogLevel) config := &logging.LoggerConfig{ Level: level, EnableColor: !NoColor, SlowOutput: false, ShowProgress: ShowProgress, StartTime: StartTime, } globalLogger = logging.NewLogger(config) if ProgressBar != nil { globalLogger.SetProgressBar(ProgressBar) } globalLogger.SetOutputMutex(&OutputMutex) // 设置协调输出函数,使用LogWithProgress globalLogger.SetCoordinatedOutput(LogWithProgress) } return globalLogger } func getLogLevelFromString(levelStr string) logging.LogLevel { switch levelStr { case "all", "ALL": return logging.LevelAll case "error", "ERROR": return logging.LevelError case "base", "BASE": return logging.LevelBase case "info", "INFO": return logging.LevelInfo case "success", "SUCCESS": return logging.LevelSuccess case "debug", "DEBUG": return logging.LevelDebug case "info,success": return logging.LevelInfoSuccess case "base,info,success", "BASE_INFO_SUCCESS": return logging.LevelBaseInfoSuccess default: return logging.LevelInfoSuccess } } // 日志函数 func InitLogger() { loggerMutex.Lock() globalLogger = nil loggerMutex.Unlock() getGlobalLogger().Initialize() } func LogDebug(msg string) { getGlobalLogger().Debug(msg) } func LogBase(msg string) { getGlobalLogger().Base(msg) } func LogInfo(msg string) { getGlobalLogger().Info(msg) } func LogSuccess(result string) { getGlobalLogger().Success(result) } func LogError(errMsg string) { getGlobalLogger().Error(errMsg) } // ============================================================================= // 输出系统简化接口 // ============================================================================= var ResultOutput *output.Manager func InitOutput() error { if Outputfile == "" { return fmt.Errorf("output file not specified") } var format output.OutputFormat switch OutputFormat { case "txt": format = output.FormatTXT case "json": format = output.FormatJSON case "csv": format = output.FormatCSV default: return fmt.Errorf("invalid output format: %s", OutputFormat) } config := output.DefaultManagerConfig(Outputfile, format) manager, err := output.NewManager(config) if err != nil { return err } ResultOutput = manager return nil } func CloseOutput() error { if ResultOutput == nil { return nil } return ResultOutput.Close() } func SaveResult(result *output.ScanResult) error { if ResultOutput == nil { return fmt.Errorf("output not initialized") } return ResultOutput.SaveResult(result) } // ============================================================================= // 网络连接辅助函数 // ============================================================================= // WrapperTcpWithTimeout TCP连接包装器,带超时 func WrapperTcpWithTimeout(network, address string, timeout time.Duration) (net.Conn, error) { return net.DialTimeout(network, address, timeout) } // WrapperTcpWithContext TCP连接包装器,带上下文和代理支持 func WrapperTcpWithContext(ctx context.Context, network, address string) (net.Conn, error) { // 检查是否配置了SOCKS5代理 if Socks5Proxy != "" { proxyConfig := &proxy.ProxyConfig{ Type: proxy.ProxyTypeSOCKS5, Address: Socks5Proxy, Timeout: time.Second * 10, } proxyManager := proxy.NewProxyManager(proxyConfig) dialer, err := proxyManager.GetDialer() if err != nil { LogDebug(fmt.Sprintf("SOCKS5代理连接失败,回退到直连: %v", err)) // 代理失败时回退到直连 var d net.Dialer return d.DialContext(ctx, network, address) } LogDebug(fmt.Sprintf("使用SOCKS5代理连接: %s -> %s", Socks5Proxy, address)) return dialer.DialContext(ctx, network, address) } // 没有配置代理,使用直连 var d net.Dialer return d.DialContext(ctx, network, address) } // WrapperTlsWithContext TLS连接包装器,带上下文和代理支持 func WrapperTlsWithContext(ctx context.Context, network, address string, config *tls.Config) (net.Conn, error) { // 检查是否配置了SOCKS5代理 if Socks5Proxy != "" { proxyConfig := &proxy.ProxyConfig{ Type: proxy.ProxyTypeSOCKS5, Address: Socks5Proxy, Timeout: time.Second * 10, } proxyManager := proxy.NewProxyManager(proxyConfig) tlsDialer, err := proxyManager.GetTLSDialer() if err != nil { LogDebug(fmt.Sprintf("SOCKS5代理TLS连接失败,回退到直连: %v", err)) // 代理失败时回退到直连 d := &tls.Dialer{Config: config} return d.DialContext(ctx, network, address) } LogDebug(fmt.Sprintf("使用SOCKS5代理TLS连接: %s -> %s", Socks5Proxy, address)) return tlsDialer.DialTLSContext(ctx, network, address, config) } // 没有配置代理,使用直连 d := &tls.Dialer{Config: config} return d.DialContext(ctx, network, address) } // ============================================================================= // 错误处理辅助函数 // ============================================================================= // CheckErrs 检查单个错误 - 简化版本 func CheckErrs(err error) error { return err }