Added external logging package
parent
dbc2793946
commit
6924e9578a
|
@ -1,7 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/subfinder/pkg/runner"
|
||||
)
|
||||
|
||||
|
@ -11,11 +11,11 @@ func main() {
|
|||
|
||||
runner, err := runner.NewRunner(options)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not create runner: %s\n", err)
|
||||
gologger.Fatalf("Could not create runner: %s\n", err)
|
||||
}
|
||||
|
||||
err = runner.RunEnumeration()
|
||||
if err != nil {
|
||||
log.Fatalf("Could not run enumeration: %s\n", err)
|
||||
gologger.Fatalf("Could not run enumeration: %s\n", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
// Package log provides a simple layer for leveled logging in go.
|
||||
package log
|
173
pkg/log/log.go
173
pkg/log/log.go
|
@ -1,173 +0,0 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
// Level defines all the available levels we can log at
|
||||
type Level int
|
||||
|
||||
// Available logging levels
|
||||
const (
|
||||
Null Level = iota
|
||||
Fatal
|
||||
Silent
|
||||
Label
|
||||
Misc
|
||||
Error
|
||||
Info
|
||||
Warning
|
||||
Verbose
|
||||
)
|
||||
|
||||
var (
|
||||
// UseColors can be used to control coloring of the output
|
||||
UseColors = true
|
||||
// MaxLevel is the maximum level to log at. By default, logging
|
||||
// is done at Info level. Using verbose will display all the errors too,
|
||||
// Using silent will display only the most relevant information.
|
||||
MaxLevel = Info
|
||||
|
||||
labels = map[Level]string{
|
||||
Warning: "WRN",
|
||||
Error: "ERR",
|
||||
Label: "WRN",
|
||||
Fatal: "FTL",
|
||||
Info: "INF",
|
||||
}
|
||||
|
||||
// mutex protects the current logger
|
||||
mutex = &sync.Mutex{}
|
||||
)
|
||||
|
||||
var stringBuilderPool = &sync.Pool{New: func() interface{} {
|
||||
return new(strings.Builder)
|
||||
}}
|
||||
|
||||
// wrap wraps a given label for a message to a logg-able representation.
|
||||
// It checks if colors are specified and what level we are logging at.
|
||||
func wrap(label string, level Level) string {
|
||||
// Check if we are not using colors, if not, return
|
||||
if !UseColors {
|
||||
return label
|
||||
}
|
||||
|
||||
switch level {
|
||||
case Silent:
|
||||
return label
|
||||
case Info, Verbose:
|
||||
return aurora.Blue(label).String()
|
||||
case Fatal:
|
||||
return aurora.Bold(aurora.Red(label)).String()
|
||||
case Error:
|
||||
return aurora.Red(label).String()
|
||||
case Warning, Label:
|
||||
return aurora.Yellow(label).String()
|
||||
default:
|
||||
return label
|
||||
}
|
||||
}
|
||||
|
||||
// getLabel generates a label for a given message, depending on the level
|
||||
// and the label passed.
|
||||
func getLabel(level Level, label string, sb *strings.Builder) {
|
||||
switch level {
|
||||
case Silent, Misc:
|
||||
return
|
||||
case Error, Fatal, Info, Warning, Label:
|
||||
sb.WriteString("[")
|
||||
sb.WriteString(wrap(labels[level], level))
|
||||
sb.WriteString("]")
|
||||
sb.WriteString(" ")
|
||||
return
|
||||
case Verbose:
|
||||
sb.WriteString("[")
|
||||
sb.WriteString(wrap(label, level))
|
||||
sb.WriteString("]")
|
||||
sb.WriteString(" ")
|
||||
return
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// log logs the actual message to the screen
|
||||
func log(level Level, label string, format string, args ...interface{}) {
|
||||
// Don't log if the level is null
|
||||
if level == Null {
|
||||
return
|
||||
}
|
||||
|
||||
if level <= MaxLevel {
|
||||
// Build the log message using the string builder pool
|
||||
sb := stringBuilderPool.Get().(*strings.Builder)
|
||||
|
||||
// Get the label and append it to string builder
|
||||
getLabel(level, label, sb)
|
||||
|
||||
message := fmt.Sprintf(format, args...)
|
||||
sb.WriteString(message)
|
||||
|
||||
if strings.HasSuffix(message, "\n") == false {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
|
||||
mutex.Lock()
|
||||
switch level {
|
||||
case Silent:
|
||||
fmt.Fprintf(os.Stdout, sb.String())
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, sb.String())
|
||||
}
|
||||
mutex.Unlock()
|
||||
|
||||
sb.Reset()
|
||||
stringBuilderPool.Put(sb)
|
||||
}
|
||||
}
|
||||
|
||||
// Infof writes a info message on the screen with the default label
|
||||
func Infof(format string, args ...interface{}) {
|
||||
log(Info, "", format, args...)
|
||||
}
|
||||
|
||||
// Warningf writes a warning message on the screen with the default label
|
||||
func Warningf(format string, args ...interface{}) {
|
||||
log(Warning, "", format, args...)
|
||||
}
|
||||
|
||||
// Errorf writes an error message on the screen with the default label
|
||||
func Errorf(format string, args ...interface{}) {
|
||||
log(Error, "", format, args...)
|
||||
}
|
||||
|
||||
// Verbosef writes a verbose message on the screen with a tabel
|
||||
func Verbosef(format string, label string, args ...interface{}) {
|
||||
log(Verbose, label, format, args...)
|
||||
}
|
||||
|
||||
// Silentf writes a message on the stdout with no label
|
||||
func Silentf(format string, args ...interface{}) {
|
||||
log(Silent, "", format, args...)
|
||||
}
|
||||
|
||||
// Fatalf exits the program if we encounter a fatal error
|
||||
func Fatalf(format string, args ...interface{}) {
|
||||
log(Fatal, "", format, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Printf prints a string on screen without any extra stuff
|
||||
func Printf(format string, args ...interface{}) {
|
||||
log(Misc, "", format, args...)
|
||||
}
|
||||
|
||||
// Labelf prints a string on screen with a label interface
|
||||
func Labelf(format string, args ...interface{}) {
|
||||
log(Label, "", format, args...)
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
func TestGetLabel(t *testing.T) {
|
||||
tests := []struct {
|
||||
level Level
|
||||
label string
|
||||
expected string
|
||||
}{
|
||||
{Fatal, "", fmt.Sprintf("[%s] ", aurora.Bold(aurora.Red(labels[Fatal])).String())},
|
||||
{Silent, "hello", ""},
|
||||
{Error, "error", fmt.Sprintf("[%s] ", aurora.Red(labels[Error]).String())},
|
||||
{Info, "", fmt.Sprintf("[%s] ", aurora.Blue(labels[Info]).String())},
|
||||
{Warning, "", fmt.Sprintf("[%s] ", aurora.Yellow(labels[Warning]).String())},
|
||||
{Verbose, "dns", fmt.Sprintf("[%s] ", aurora.Blue("dns").String())},
|
||||
}
|
||||
|
||||
sb := &strings.Builder{}
|
||||
for _, test := range tests {
|
||||
sb.Reset()
|
||||
getLabel(test.level, test.label, sb)
|
||||
data := sb.String()
|
||||
|
||||
assert.Equal(t, data, test.expected, "Expected message and generate message don't match")
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/subfinder/pkg/subscraping"
|
||||
)
|
||||
|
||||
|
@ -47,7 +47,7 @@ func (a *Agent) EnumerateSubdomains(domain string, keys subscraping.Keys, timeou
|
|||
wg.Wait()
|
||||
|
||||
for source, data := range timeTaken {
|
||||
log.Verbosef(data, source)
|
||||
gologger.Verbosef(data, source)
|
||||
}
|
||||
|
||||
close(results)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package runner
|
||||
|
||||
import (
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/subfinder/pkg/passive"
|
||||
"github.com/projectdiscovery/subfinder/pkg/resolve"
|
||||
)
|
||||
|
@ -18,19 +18,19 @@ const Version = `2.3.2`
|
|||
|
||||
// showBanner is used to show the banner to the user
|
||||
func showBanner() {
|
||||
log.Printf("%s\n", banner)
|
||||
log.Printf("\t\tprojectdiscovery.io\n\n")
|
||||
gologger.Printf("%s\n", banner)
|
||||
gologger.Printf("\t\tprojectdiscovery.io\n\n")
|
||||
|
||||
log.Labelf("Use with caution. You are responsible for your actions\n")
|
||||
log.Labelf("Developers assume no liability and are not responsible for any misuse or damage.\n")
|
||||
log.Labelf("By using subfinder, you also agree to the terms of the APIs used.\n\n")
|
||||
gologger.Labelf("Use with caution. You are responsible for your actions\n")
|
||||
gologger.Labelf("Developers assume no liability and are not responsible for any misuse or damage.\n")
|
||||
gologger.Labelf("By using subfinder, you also agree to the terms of the APIs used.\n\n")
|
||||
}
|
||||
|
||||
// normalRunTasks runs the normal startup tasks
|
||||
func (options *Options) normalRunTasks() {
|
||||
configFile, err := UnmarshalRead(options.ConfigFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not read configuration file %s: %s\n", options.ConfigFile, err)
|
||||
gologger.Fatalf("Could not read configuration file %s: %s\n", options.ConfigFile, err)
|
||||
}
|
||||
options.YAMLConfig = configFile
|
||||
}
|
||||
|
@ -49,9 +49,9 @@ func (options *Options) firstRunTasks() {
|
|||
|
||||
err := config.MarshalWrite(options.ConfigFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not write configuration file to %s: %s\n", options.ConfigFile, err)
|
||||
gologger.Fatalf("Could not write configuration file to %s: %s\n", options.ConfigFile, err)
|
||||
}
|
||||
options.YAMLConfig = config
|
||||
|
||||
log.Infof("Configuration file saved to %s\n", options.ConfigFile)
|
||||
gologger.Infof("Configuration file saved to %s\n", options.ConfigFile)
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
"github.com/projectdiscovery/subfinder/pkg/resolve"
|
||||
"github.com/projectdiscovery/subfinder/pkg/subscraping"
|
||||
)
|
||||
|
||||
// EnumerateSingleDomain performs subdomain enumeration against a single domain
|
||||
func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error {
|
||||
log.Infof("Enumerating subdomains for %s\n", domain)
|
||||
gologger.Infof("Enumerating subdomains for %s\n", domain)
|
||||
|
||||
// Get the API keys for sources from the configuration
|
||||
// and also create the active resolving engine for the domain.
|
||||
|
@ -27,7 +27,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
err := resolutionPool.InitWildcards(domain)
|
||||
if err != nil {
|
||||
// Log the error but don't quit.
|
||||
log.Warningf("Could not get wildcards for domain %s: %s\n", domain, err)
|
||||
gologger.Warningf("Could not get wildcards for domain %s: %s\n", domain, err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -43,7 +43,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
for result := range passiveResults {
|
||||
switch result.Type {
|
||||
case subscraping.Error:
|
||||
log.Warningf("Could not run source %s: %s\n", result.Source, result.Error)
|
||||
gologger.Warningf("Could not run source %s: %s\n", result.Source, result.Error)
|
||||
case subscraping.Subdomain:
|
||||
// Validate the subdomain found and remove wildcards from
|
||||
if !strings.HasSuffix(result.Value, "."+domain) {
|
||||
|
@ -60,7 +60,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
|
||||
// Log the verbose message about the found subdomain and send the
|
||||
// host for resolution to the resolution pool
|
||||
log.Verbosef("%s\n", result.Source, subdomain)
|
||||
gologger.Verbosef("%s\n", result.Source, subdomain)
|
||||
|
||||
// If the user asked to remove wildcard then send on the resolve
|
||||
// queue. Otherwise, if mode is not verbose print the results on
|
||||
|
@ -70,7 +70,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
}
|
||||
|
||||
if !r.options.Verbose {
|
||||
log.Silentf("%s\n", subdomain)
|
||||
gologger.Silentf("%s\n", subdomain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
for result := range resolutionPool.Results {
|
||||
switch result.Type {
|
||||
case resolve.Error:
|
||||
log.Warningf("Could not resolve host: %s\n", result.Error)
|
||||
gologger.Warningf("Could not resolve host: %s\n", result.Error)
|
||||
case resolve.Subdomain:
|
||||
// Add the found subdomain to a map.
|
||||
if _, ok := foundResults[result.Host]; !ok {
|
||||
|
@ -105,11 +105,11 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
if r.options.Verbose {
|
||||
if r.options.RemoveWildcard {
|
||||
for result := range foundResults {
|
||||
log.Silentf("%s\n", result)
|
||||
gologger.Silentf("%s\n", result)
|
||||
}
|
||||
} else {
|
||||
for result := range uniqueMap {
|
||||
log.Silentf("%s\n", result)
|
||||
gologger.Silentf("%s\n", result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
file, err = os.Create(output)
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Could not create file %s for %s: %s\n", output, domain, err)
|
||||
gologger.Errorf("Could not create file %s for %s: %s\n", output, domain, err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ func (r *Runner) EnumerateSingleDomain(domain, output string, append bool) error
|
|||
}
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Could not write results to file %s for %s: %s\n", output, domain, err)
|
||||
gologger.Errorf("Could not write results to file %s for %s: %s\n", output, domain, err)
|
||||
}
|
||||
file.Close()
|
||||
return err
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
)
|
||||
|
||||
// Options contains the configuration options for tuning
|
||||
|
@ -42,7 +42,7 @@ func ParseOptions() *Options {
|
|||
config, err := GetConfigDirectory()
|
||||
if err != nil {
|
||||
// This should never be reached
|
||||
log.Fatalf("Could not get user home: %s\n", err)
|
||||
gologger.Fatalf("Could not get user home: %s\n", err)
|
||||
}
|
||||
|
||||
flag.BoolVar(&options.Verbose, "v", false, "Show Verbose output")
|
||||
|
@ -76,7 +76,7 @@ func ParseOptions() *Options {
|
|||
showBanner()
|
||||
|
||||
if options.Version {
|
||||
log.Infof("Current Version: %s\n", Version)
|
||||
gologger.Infof("Current Version: %s\n", Version)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ func ParseOptions() *Options {
|
|||
// invalid options have been used, exit.
|
||||
err = options.validateOptions()
|
||||
if err != nil {
|
||||
log.Fatalf("Program exiting: %s\n", err)
|
||||
gologger.Fatalf("Program exiting: %s\n", err)
|
||||
}
|
||||
|
||||
return options
|
||||
|
|
|
@ -3,7 +3,7 @@ package runner
|
|||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/projectdiscovery/subfinder/pkg/log"
|
||||
"github.com/projectdiscovery/gologger"
|
||||
)
|
||||
|
||||
// validateOptions validates the configuration options passed
|
||||
|
@ -47,12 +47,12 @@ func (options *Options) validateOptions() error {
|
|||
func (options *Options) configureOutput() {
|
||||
// If the user desires verbose output, show verbose output
|
||||
if options.Verbose {
|
||||
log.MaxLevel = log.Verbose
|
||||
gologger.MaxLevel = gologger.Verbose
|
||||
}
|
||||
if options.NoColor {
|
||||
log.UseColors = false
|
||||
gologger.UseColors = false
|
||||
}
|
||||
if options.Silent {
|
||||
log.MaxLevel = log.Silent
|
||||
gologger.MaxLevel = gologger.Silent
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue