mirror of
https://github.com/shadow1ng/fscan.git
synced 2025-09-14 14:06:44 +08:00

主要修复: 1. 修复时间显示Bug - StartTime初始化问题 2. 修复Web智能探测错误检测预定义端口而非用户指定端口 3. 修复本地插件被错误调用到端口扫描中的问题 4. 修复host:port格式双重处理导致的多余端口扫描 5. 统一插件过滤逻辑,消除接口不一致性 6. 优化Web检测缓存机制,减少重复HTTP请求 技术改进: - 重构插件适用性检查逻辑,确保策略过滤器正确工作 - 区分Web检测的自动发现模式和用户指定端口模式 - 在解析阶段正确处理host:port格式,避免与默认端口冲突 - 完善缓存机制,提升性能 测试验证: - ./fscan -h 127.0.0.1:3306 现在只检测3306端口 - 本地插件不再参与端口扫描 - Web检测只对指定端口进行协议检测 - 时间显示正确
316 lines
7.6 KiB
Go
316 lines
7.6 KiB
Go
package logging
|
||
|
||
import (
|
||
"fmt"
|
||
"io"
|
||
"log"
|
||
"path/filepath"
|
||
"runtime"
|
||
"sync"
|
||
"time"
|
||
|
||
"github.com/fatih/color"
|
||
)
|
||
|
||
// Logger 日志管理器
|
||
type Logger struct {
|
||
mu sync.RWMutex
|
||
config *LoggerConfig
|
||
formatter LogFormatter
|
||
handlers []LogHandler
|
||
scanStatus *ScanStatus
|
||
progressBar ProgressDisplay
|
||
outputMutex *sync.Mutex
|
||
initialized bool
|
||
}
|
||
|
||
// NewLogger 创建新的日志管理器
|
||
func NewLogger(config *LoggerConfig) *Logger {
|
||
if config == nil {
|
||
config = DefaultLoggerConfig()
|
||
}
|
||
|
||
logger := &Logger{
|
||
config: config,
|
||
formatter: NewStandardFormatter(),
|
||
handlers: make([]LogHandler, 0),
|
||
scanStatus: NewScanStatus(),
|
||
outputMutex: &sync.Mutex{},
|
||
initialized: true,
|
||
}
|
||
|
||
// 设置格式化器的开始时间
|
||
logger.formatter.SetStartTime(config.StartTime)
|
||
|
||
// 添加默认的控制台处理器
|
||
consoleHandler := NewConsoleHandler(config)
|
||
logger.AddHandler(consoleHandler)
|
||
|
||
return logger
|
||
}
|
||
|
||
// =============================================================================================
|
||
// 已删除的死代码(未使用):SetFormatter 方法
|
||
// =============================================================================================
|
||
|
||
// AddHandler 添加日志处理器
|
||
func (l *Logger) AddHandler(handler LogHandler) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
l.handlers = append(l.handlers, handler)
|
||
}
|
||
|
||
// SetProgressBar 设置进度条显示
|
||
func (l *Logger) SetProgressBar(progressBar ProgressDisplay) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
l.progressBar = progressBar
|
||
}
|
||
|
||
// SetOutputMutex 设置输出互斥锁
|
||
func (l *Logger) SetOutputMutex(mutex *sync.Mutex) {
|
||
l.mu.Lock()
|
||
defer l.mu.Unlock()
|
||
l.outputMutex = mutex
|
||
}
|
||
|
||
// SetCoordinatedOutput 设置协调输出函数(用于进度条协调)
|
||
func (l *Logger) SetCoordinatedOutput(fn func(string)) {
|
||
l.mu.RLock()
|
||
defer l.mu.RUnlock()
|
||
|
||
for _, handler := range l.handlers {
|
||
if consoleHandler, ok := handler.(*ConsoleHandler); ok {
|
||
consoleHandler.SetCoordinatedOutput(fn)
|
||
}
|
||
}
|
||
}
|
||
|
||
// Log 记录日志
|
||
func (l *Logger) Log(level LogLevel, content string, metadata ...map[string]interface{}) {
|
||
if !l.shouldLog(level) {
|
||
return
|
||
}
|
||
|
||
entry := &LogEntry{
|
||
Level: level,
|
||
Time: time.Now(),
|
||
Content: content,
|
||
}
|
||
|
||
// 添加元数据
|
||
if len(metadata) > 0 {
|
||
entry.Metadata = metadata[0]
|
||
}
|
||
|
||
// 对于错误级别,自动添加调用者信息
|
||
if level == LevelError {
|
||
if _, file, line, ok := runtime.Caller(2); ok {
|
||
entry.Source = fmt.Sprintf("%s:%d", filepath.Base(file), line)
|
||
entry.Content = fmt.Sprintf("%s:%d - %s", filepath.Base(file), line, content)
|
||
}
|
||
}
|
||
|
||
l.handleLogEntry(entry)
|
||
|
||
// 更新扫描状态
|
||
if level == LevelSuccess {
|
||
l.scanStatus.UpdateSuccess()
|
||
} else if level == LevelError {
|
||
l.scanStatus.UpdateError()
|
||
}
|
||
}
|
||
|
||
// shouldLog 检查是否应该记录该级别的日志
|
||
func (l *Logger) shouldLog(level LogLevel) bool {
|
||
switch l.config.Level {
|
||
case LevelAll:
|
||
return true
|
||
case LevelBaseInfoSuccess:
|
||
return level == LevelBase || level == LevelInfo || level == LevelSuccess
|
||
case LevelInfoSuccess:
|
||
return level == LevelInfo || level == LevelSuccess
|
||
case LevelError:
|
||
return level == LevelError
|
||
case LevelBase:
|
||
return level == LevelBase
|
||
case LevelInfo:
|
||
return level == LevelInfo
|
||
case LevelSuccess:
|
||
return level == LevelSuccess
|
||
case LevelDebug:
|
||
return level == LevelDebug
|
||
default:
|
||
// 向后兼容:如果是字符串 "debug",显示所有
|
||
if l.config.Level == "debug" {
|
||
return true
|
||
}
|
||
// 默认显示base、info和success
|
||
return level == LevelBase || level == LevelInfo || level == LevelSuccess
|
||
}
|
||
}
|
||
|
||
// handleLogEntry 处理日志条目
|
||
func (l *Logger) handleLogEntry(entry *LogEntry) {
|
||
l.outputMutex.Lock()
|
||
defer l.outputMutex.Unlock()
|
||
|
||
// 清除进度条
|
||
l.clearProgress()
|
||
|
||
// 使用所有处理器处理日志
|
||
l.mu.RLock()
|
||
for _, handler := range l.handlers {
|
||
if handler.IsEnabled() {
|
||
handler.Handle(entry)
|
||
}
|
||
}
|
||
l.mu.RUnlock()
|
||
|
||
// 恢复进度条
|
||
l.restoreProgress()
|
||
}
|
||
|
||
// clearProgress 清除进度条
|
||
func (l *Logger) clearProgress() {
|
||
if l.progressBar != nil {
|
||
l.progressBar.Clear() // 忽略错误
|
||
time.Sleep(ProgressClearDelay)
|
||
}
|
||
}
|
||
|
||
// restoreProgress 恢复进度条
|
||
func (l *Logger) restoreProgress() {
|
||
if l.progressBar != nil {
|
||
l.progressBar.RenderBlank() // 忽略错误
|
||
}
|
||
}
|
||
|
||
// 便利方法
|
||
func (l *Logger) Debug(content string, metadata ...map[string]interface{}) {
|
||
l.Log(LevelDebug, content, metadata...)
|
||
}
|
||
|
||
func (l *Logger) Base(content string, metadata ...map[string]interface{}) {
|
||
l.Log(LevelBase, content, metadata...)
|
||
}
|
||
|
||
func (l *Logger) Info(content string, metadata ...map[string]interface{}) {
|
||
l.Log(LevelInfo, content, metadata...)
|
||
}
|
||
|
||
func (l *Logger) Success(content string, metadata ...map[string]interface{}) {
|
||
l.Log(LevelSuccess, content, metadata...)
|
||
}
|
||
|
||
func (l *Logger) Error(content string, metadata ...map[string]interface{}) {
|
||
l.Log(LevelError, content, metadata...)
|
||
}
|
||
|
||
// =============================================================================================
|
||
// 已删除的死代码(未使用):GetScanStatus 获取扫描状态管理器
|
||
// =============================================================================================
|
||
|
||
// Initialize 初始化日志系统(兼容原接口)
|
||
func (l *Logger) Initialize() {
|
||
// 禁用标准日志输出
|
||
log.SetOutput(io.Discard)
|
||
}
|
||
|
||
// ConsoleHandler 控制台日志处理器
|
||
type ConsoleHandler struct {
|
||
config *LoggerConfig
|
||
formatter LogFormatter
|
||
enabled bool
|
||
coordinatedOutput func(string) // 协调输出函数
|
||
mu sync.RWMutex
|
||
}
|
||
|
||
// NewConsoleHandler 创建控制台处理器
|
||
func NewConsoleHandler(config *LoggerConfig) *ConsoleHandler {
|
||
formatter := NewStandardFormatter()
|
||
formatter.SetStartTime(config.StartTime)
|
||
|
||
return &ConsoleHandler{
|
||
config: config,
|
||
formatter: formatter,
|
||
enabled: true,
|
||
}
|
||
}
|
||
|
||
// Handle 处理日志条目
|
||
func (h *ConsoleHandler) Handle(entry *LogEntry) {
|
||
h.mu.RLock()
|
||
defer h.mu.RUnlock()
|
||
|
||
if !h.enabled {
|
||
return
|
||
}
|
||
|
||
// 使用自己的格式化器格式化消息
|
||
logMsg := h.formatter.Format(entry)
|
||
|
||
// 使用协调输出函数,如果设置了的话
|
||
if h.coordinatedOutput != nil {
|
||
if h.config.EnableColor {
|
||
if colorAttr, ok := h.config.LevelColors[entry.Level]; ok {
|
||
if attr, ok := colorAttr.(color.Attribute); ok {
|
||
coloredMsg := color.New(attr).Sprint(logMsg)
|
||
h.coordinatedOutput(coloredMsg)
|
||
} else {
|
||
h.coordinatedOutput(logMsg)
|
||
}
|
||
} else {
|
||
h.coordinatedOutput(logMsg)
|
||
}
|
||
} else {
|
||
h.coordinatedOutput(logMsg)
|
||
}
|
||
} else {
|
||
// 回到原来的直接输出方式
|
||
if h.config.EnableColor {
|
||
if colorAttr, ok := h.config.LevelColors[entry.Level]; ok {
|
||
if attr, ok := colorAttr.(color.Attribute); ok {
|
||
color.New(attr).Println(logMsg)
|
||
} else {
|
||
fmt.Println(logMsg)
|
||
}
|
||
} else {
|
||
fmt.Println(logMsg)
|
||
}
|
||
} else {
|
||
fmt.Println(logMsg)
|
||
}
|
||
}
|
||
|
||
// 根据慢速输出设置决定是否添加延迟
|
||
if h.config.SlowOutput {
|
||
time.Sleep(SlowOutputDelay)
|
||
}
|
||
}
|
||
|
||
// SetEnabled 设置处理器启用状态
|
||
func (h *ConsoleHandler) SetEnabled(enabled bool) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
h.enabled = enabled
|
||
}
|
||
|
||
// SetCoordinatedOutput 设置协调输出函数
|
||
func (h *ConsoleHandler) SetCoordinatedOutput(fn func(string)) {
|
||
h.mu.Lock()
|
||
defer h.mu.Unlock()
|
||
h.coordinatedOutput = fn
|
||
}
|
||
|
||
// IsEnabled 检查处理器是否启用
|
||
func (h *ConsoleHandler) IsEnabled() bool {
|
||
h.mu.RLock()
|
||
defer h.mu.RUnlock()
|
||
return h.enabled
|
||
}
|
||
|
||
// =============================================================================================
|
||
// 已删除的死代码(未使用):CheckErrs 错误检查函数
|
||
// =============================================================================================
|