package output import ( "fmt" "io" "os" "github.com/hits/ExploreDNS/internal/traverse" ) type Format int const ( FormatText Format = iota FormatJSON ) type Config struct { Format Format Domain string QueryType string ShowProgress bool ShowResolves bool ShowServers bool ShowVersions bool ShowAllStats bool ShowResults bool ShowSummaryResults bool Verbose bool Quiet bool Color bool Debug int // Fingerprints maps server IP strings to their version.bind version strings. // Populated by RunTraversal when ShowVersions and ShowServers are both true. Fingerprints map[string]string } func DefaultConfig() *Config { return &Config{ Format: FormatText, ShowProgress: true, ShowResolves: true, ShowServers: true, ShowVersions: true, ShowAllStats: true, ShowResults: true, ShowSummaryResults: true, Color: os.Getenv("NO_COLOR") == "", } } type Formatter interface { WriteProgress(event traverse.TraversalEvent) error WriteResolve(event traverse.TraversalEvent) error WriteResult(result traverse.TraversalResult) error WriteSummary(results []traverse.TraversalResult) error Flush() error } func NewFormatter(cfg *Config, w io.Writer) Formatter { if cfg == nil { cfg = DefaultConfig() } if w == nil { w = os.Stdout } if cfg.Format == FormatJSON { return newJSONFormatter(cfg, w) } return newTextFormatter(cfg, w) } func AttachHooks(cfg *Config, formatter Formatter) *traverse.TraverserHooks { if cfg == nil || formatter == nil { return nil } logErr := func(context string, err error) { if err != nil && cfg.Debug > 0 { fmt.Fprintf(os.Stderr, "Debug: formatter %s: %v\n", context, err) } } return &traverse.TraverserHooks{ OnEvent: func(event traverse.TraversalEvent) { switch { case event.IsResolve && cfg.ShowResolves: logErr("WriteResolve", formatter.WriteResolve(event)) case !event.IsResolve && cfg.ShowProgress: logErr("WriteProgress", formatter.WriteProgress(event)) } if event.Stage == traverse.EventComplete && cfg.ShowAllStats { logErr("WriteResult", formatter.WriteResult(event.Result)) } }, } }