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

主要更改: - 重构Log.go和Output.go为模块化架构 - 创建独立的logging和output模块 - 新增LevelBaseInfoSuccess默认日志级别(显示BASE、INFO、SUCCESS) - 添加运行时间显示到每条日志前面 - 保持完全向后兼容的API接口 - 支持多种输出格式(TXT、JSON、CSV) - 优化日志格式化和颜色显示 技术改进: - 模块化设计便于扩展和维护 - 智能时间格式化(毫秒→秒→分钟→小时) - 支持缓冲和批量输出 - 线程安全的并发处理
289 lines
7.1 KiB
Go
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)
|
|
} |