fscan/Common/Output.go
ZacharyZcR e095f376f9 refactor: 重构日志和输出系统,优化日志级别和时间显示
主要更改:
- 重构Log.go和Output.go为模块化架构
- 创建独立的logging和output模块
- 新增LevelBaseInfoSuccess默认日志级别(显示BASE、INFO、SUCCESS)
- 添加运行时间显示到每条日志前面
- 保持完全向后兼容的API接口
- 支持多种输出格式(TXT、JSON、CSV)
- 优化日志格式化和颜色显示

技术改进:
- 模块化设计便于扩展和维护
- 智能时间格式化(毫秒→秒→分钟→小时)
- 支持缓冲和批量输出
- 线程安全的并发处理
2025-08-05 02:14:25 +08:00

289 lines
7.1 KiB
Go

package Common
import (
"fmt"
"time"
"github.com/shadow1ng/fscan/Common/output"
)
// 全局输出管理器(保持向后兼容)
var ResultOutput *OutputManager
// OutputManager 输出管理器结构体(向后兼容)
type OutputManager struct {
manager *output.Manager
}
// ResultType 定义结果类型(向后兼容)
type ResultType = output.ResultType
const (
HOST ResultType = output.TypeHost // 主机存活
PORT ResultType = output.TypePort // 端口开放
SERVICE ResultType = output.TypeService // 服务识别
VULN ResultType = output.TypeVuln // 漏洞发现
)
// ScanResult 扫描结果结构(向后兼容)
type ScanResult = output.ScanResult
// createOutputManager 创建输出管理器的内部包装
func createOutputManager(outputPath, outputFormat string) (*OutputManager, error) {
var format output.OutputFormat
switch outputFormat {
case "txt":
format = output.FormatTXT
case "json":
format = output.FormatJSON
case "csv":
format = output.FormatCSV
default:
return nil, fmt.Errorf(GetText("output_format_invalid"), outputFormat)
}
config := output.DefaultManagerConfig(outputPath, format)
manager, err := output.NewManager(config)
if err != nil {
return nil, err
}
return &OutputManager{
manager: manager,
}, nil
}
// InitOutput 初始化输出系统(保持原接口)
func InitOutput() error {
LogDebug(GetText("output_init_start"))
// 验证输出格式
switch OutputFormat {
case "txt", "json", "csv":
// 有效的格式
default:
return fmt.Errorf(GetText("output_format_invalid"), OutputFormat)
}
// 验证输出路径
if Outputfile == "" {
return fmt.Errorf(GetText("output_path_empty"))
}
manager, err := createOutputManager(Outputfile, OutputFormat)
if err != nil {
LogDebug(GetText("output_init_failed", err))
return fmt.Errorf(GetText("output_init_failed", err))
}
ResultOutput = manager
// 设置全局输出管理器
output.SetGlobalManager(manager.manager)
LogDebug(GetText("output_init_success"))
return nil
}
// saveResult 内部方法,使用新的输出管理器保存结果
func (om *OutputManager) saveResult(result *ScanResult) error {
if om.manager == nil {
return fmt.Errorf(GetText("output_not_init"))
}
LogDebug(GetText("output_saving_result", result.Type, result.Target))
return om.manager.SaveResult(result)
}
// getResult 内部方法,获取结果
func (om *OutputManager) getResult() ([]*ScanResult, error) {
if om.manager == nil {
return nil, fmt.Errorf(GetText("output_not_init"))
}
return om.manager.GetResults()
}
// SaveResult 保存扫描结果(保持原接口)
func SaveResult(result *ScanResult) error {
if ResultOutput == nil {
LogDebug(GetText("output_not_init"))
return fmt.Errorf(GetText("output_not_init"))
}
LogDebug(GetText("output_saving_result", result.Type, result.Target))
return ResultOutput.saveResult(result)
}
// GetResults 获取扫描结果(保持原接口)
func GetResults() ([]*ScanResult, error) {
if ResultOutput == nil {
return nil, fmt.Errorf(GetText("output_not_init"))
}
return ResultOutput.getResult()
}
// CloseOutput 关闭输出系统(保持原接口)
func CloseOutput() error {
if ResultOutput == nil {
LogDebug(GetText("output_no_need_close"))
return nil
}
LogDebug(GetText("output_closing"))
err := ResultOutput.manager.Close()
if err != nil {
LogDebug(GetText("output_close_failed", err))
return fmt.Errorf(GetText("output_close_failed", err))
}
LogDebug(GetText("output_closed"))
return nil
}
// 新增功能接口
// SaveResultWithDetails 保存带详细信息的扫描结果
func SaveResultWithDetails(resultType ResultType, target, status string, details map[string]interface{}) error {
result := &ScanResult{
Time: time.Now(),
Type: resultType,
Target: target,
Status: status,
Details: details,
}
return SaveResult(result)
}
// GetResultsWithFilter 获取过滤后的扫描结果
func GetResultsWithFilter(filter *output.ResultFilter) ([]*ScanResult, error) {
if ResultOutput == nil {
return nil, fmt.Errorf(GetText("output_not_init"))
}
return ResultOutput.manager.GetResultsWithFilter(filter)
}
// GetOutputStatistics 获取输出统计信息
func GetOutputStatistics() *output.Statistics {
if ResultOutput == nil {
return nil
}
return ResultOutput.manager.GetStatistics()
}
// FlushOutput 刷新输出缓冲区
func FlushOutput() error {
if ResultOutput == nil {
return nil
}
return ResultOutput.manager.Flush()
}
// UpdateOutputConfig 更新输出配置
func UpdateOutputConfig(updates map[string]interface{}) error {
if ResultOutput == nil {
return fmt.Errorf(GetText("output_not_init"))
}
return ResultOutput.manager.UpdateConfig(updates)
}
// 便利函数用于快速保存不同类型的结果
// SaveHostResult 保存主机存活结果
func SaveHostResult(target string, isAlive bool, details map[string]interface{}) error {
status := "离线"
if isAlive {
status = "存活"
}
return SaveResultWithDetails(HOST, target, status, details)
}
// SavePortResult 保存端口扫描结果
func SavePortResult(target string, port int, isOpen bool, service string, details map[string]interface{}) error {
status := "关闭"
if isOpen {
status = "开放"
}
if details == nil {
details = make(map[string]interface{})
}
details["port"] = port
if service != "" {
details["service"] = service
}
targetWithPort := fmt.Sprintf("%s:%d", target, port)
return SaveResultWithDetails(PORT, targetWithPort, status, details)
}
// SaveServiceResult 保存服务识别结果
func SaveServiceResult(target string, service, version string, details map[string]interface{}) error {
status := service
if version != "" {
status = fmt.Sprintf("%s %s", service, version)
}
if details == nil {
details = make(map[string]interface{})
}
details["service"] = service
if version != "" {
details["version"] = version
}
return SaveResultWithDetails(SERVICE, target, status, details)
}
// SaveVulnResult 保存漏洞发现结果
func SaveVulnResult(target, vulnName, severity string, details map[string]interface{}) error {
status := vulnName
if severity != "" {
status = fmt.Sprintf("%s [%s]", vulnName, severity)
}
if details == nil {
details = make(map[string]interface{})
}
details["vulnerability"] = vulnName
if severity != "" {
details["severity"] = severity
}
return SaveResultWithDetails(VULN, target, status, details)
}
// 导出新的类型和接口供高级用户使用
type (
OutputFormatType = output.OutputFormat
ResultFilter = output.ResultFilter
TimeRange = output.TimeRange
Statistics = output.Statistics
ManagerConfig = output.ManagerConfig
)
// 导出新的常量
const (
FormatTXT = output.FormatTXT
FormatJSON = output.FormatJSON
FormatCSV = output.FormatCSV
TypeInfo = output.TypeInfo
TypeBrute = output.TypeBrute
)
// CreateOutputManager 创建新的输出管理器(高级接口)
func CreateOutputManager(config *ManagerConfig) (*output.Manager, error) {
return output.NewManager(config)
}
// DefaultOutputConfig 获取默认输出配置
func DefaultOutputConfig(outputPath string, format OutputFormatType) *ManagerConfig {
return output.DefaultManagerConfig(outputPath, format)
}