Added external logging package

master
Ice3man543 2020-02-26 16:12:19 +05:30
parent dbc2793946
commit 6924e9578a
9 changed files with 33 additions and 242 deletions

View File

@ -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)
}
}

View File

@ -1,2 +0,0 @@
// Package log provides a simple layer for leveled logging in go.
package log

View File

@ -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...)
}

View File

@ -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")
}
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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

View File

@ -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

View File

@ -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
}
}