subfinder/v2/pkg/runner/outputter.go

237 lines
5.3 KiB
Go
Raw Normal View History

2020-08-15 23:11:27 +00:00
package runner
import (
"bufio"
"errors"
"io"
"os"
"path/filepath"
2020-08-15 23:11:27 +00:00
"strings"
jsoniter "github.com/json-iterator/go"
2020-09-24 17:02:02 +00:00
"github.com/projectdiscovery/subfinder/v2/pkg/resolve"
2020-08-15 23:11:27 +00:00
)
2020-08-16 15:44:55 +00:00
// OutPutter outputs content to writers.
type OutPutter struct {
JSON bool
}
2022-03-24 20:43:58 +00:00
type jsonSourceResult struct {
Host string `json:"host"`
2022-03-24 20:47:54 +00:00
Input string `json:"input"`
2022-03-24 20:43:58 +00:00
Source string `json:"source"`
}
type jsonSourceIPResult struct {
2020-08-16 15:44:55 +00:00
Host string `json:"host"`
IP string `json:"ip"`
2022-03-24 20:47:54 +00:00
Input string `json:"input"`
2020-08-16 15:44:55 +00:00
Source string `json:"source"`
2020-08-15 23:11:27 +00:00
}
2022-03-24 20:43:58 +00:00
type jsonSourcesResult struct {
2020-10-14 19:34:07 +00:00
Host string `json:"host"`
2022-03-24 20:47:54 +00:00
Input string `json:"input"`
Sources []string `json:"sources"`
}
2020-08-16 15:44:55 +00:00
// NewOutputter creates a new Outputter
func NewOutputter(json bool) *OutPutter {
return &OutPutter{JSON: json}
}
2020-08-15 23:11:27 +00:00
func (o *OutPutter) createFile(filename string, appendtoFile bool) (*os.File, error) {
2020-08-15 23:11:27 +00:00
if filename == "" {
return nil, errors.New("empty filename")
}
dir := filepath.Dir(filename)
2020-08-15 23:11:27 +00:00
if dir != "" {
if _, err := os.Stat(dir); os.IsNotExist(err) {
err := os.MkdirAll(dir, os.ModePerm)
2020-08-15 23:11:27 +00:00
if err != nil {
return nil, err
}
}
}
var file *os.File
var err error
if appendtoFile {
file, err = os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
2020-08-15 23:11:27 +00:00
} else {
file, err = os.Create(filename)
2020-08-15 23:11:27 +00:00
}
if err != nil {
return nil, err
}
return file, nil
}
// WriteHostIP writes the output list of subdomain to an io.Writer
2022-03-24 20:47:54 +00:00
func (o *OutPutter) WriteHostIP(input string, results map[string]resolve.Result, writer io.Writer) error {
2020-08-16 15:44:55 +00:00
var err error
if o.JSON {
2022-03-24 20:47:54 +00:00
err = writeJSONHostIP(input, results, writer)
2020-08-16 15:44:55 +00:00
} else {
2022-03-24 20:47:54 +00:00
err = writePlainHostIP(input, results, writer)
2020-08-16 15:44:55 +00:00
}
return err
}
2022-03-24 20:47:54 +00:00
func writePlainHostIP(_ string, results map[string]resolve.Result, writer io.Writer) error {
2020-08-15 23:11:27 +00:00
bufwriter := bufio.NewWriter(writer)
sb := &strings.Builder{}
2020-08-16 15:44:55 +00:00
for _, result := range results {
sb.WriteString(result.Host)
sb.WriteString(",")
sb.WriteString(result.IP)
2020-08-15 23:11:27 +00:00
sb.WriteString(",")
2020-08-16 15:44:55 +00:00
sb.WriteString(result.Source)
2020-08-15 23:11:27 +00:00
sb.WriteString("\n")
_, err := bufwriter.WriteString(sb.String())
if err != nil {
bufwriter.Flush()
return err
}
sb.Reset()
}
return bufwriter.Flush()
}
2022-03-24 20:47:54 +00:00
func writeJSONHostIP(input string, results map[string]resolve.Result, writer io.Writer) error {
2020-08-15 23:11:27 +00:00
encoder := jsoniter.NewEncoder(writer)
2022-03-24 20:43:58 +00:00
var data jsonSourceIPResult
2020-08-15 23:11:27 +00:00
2020-08-16 15:44:55 +00:00
for _, result := range results {
data.Host = result.Host
data.IP = result.IP
2022-03-24 20:47:54 +00:00
data.Input = input
2020-08-16 15:44:55 +00:00
data.Source = result.Source
2020-08-15 23:11:27 +00:00
err := encoder.Encode(&data)
if err != nil {
return err
}
}
return nil
}
// WriteHostNoWildcard writes the output list of subdomain with nW flag to an io.Writer
2022-03-24 20:47:54 +00:00
func (o *OutPutter) WriteHostNoWildcard(input string, results map[string]resolve.Result, writer io.Writer) error {
2020-08-16 15:44:55 +00:00
hosts := make(map[string]resolve.HostEntry)
for host, result := range results {
hosts[host] = resolve.HostEntry{Host: result.Host, Source: result.Source}
}
2022-03-24 20:47:54 +00:00
return o.WriteHost(input, hosts, writer)
2020-08-16 15:44:55 +00:00
}
// WriteHost writes the output list of subdomain to an io.Writer
2022-03-24 20:47:54 +00:00
func (o *OutPutter) WriteHost(input string, results map[string]resolve.HostEntry, writer io.Writer) error {
2020-08-16 15:44:55 +00:00
var err error
if o.JSON {
2022-03-24 20:47:54 +00:00
err = writeJSONHost(input, results, writer)
2020-08-16 15:44:55 +00:00
} else {
2022-03-24 20:47:54 +00:00
err = writePlainHost(input, results, writer)
2020-08-16 15:44:55 +00:00
}
return err
}
2022-03-24 20:47:54 +00:00
func writePlainHost(_ string, results map[string]resolve.HostEntry, writer io.Writer) error {
2020-08-15 23:11:27 +00:00
bufwriter := bufio.NewWriter(writer)
sb := &strings.Builder{}
2020-08-16 15:44:55 +00:00
for _, result := range results {
sb.WriteString(result.Host)
2020-08-15 23:11:27 +00:00
sb.WriteString("\n")
_, err := bufwriter.WriteString(sb.String())
if err != nil {
bufwriter.Flush()
return err
}
sb.Reset()
}
return bufwriter.Flush()
}
2022-03-24 20:47:54 +00:00
func writeJSONHost(input string, results map[string]resolve.HostEntry, writer io.Writer) error {
2020-08-16 15:44:55 +00:00
encoder := jsoniter.NewEncoder(writer)
2020-08-15 23:11:27 +00:00
2022-03-24 20:43:58 +00:00
var data jsonSourceResult
2020-08-16 15:44:55 +00:00
for _, result := range results {
2022-03-24 20:43:58 +00:00
data.Host = result.Host
2022-03-24 20:47:54 +00:00
data.Input = input
2022-03-24 20:43:58 +00:00
data.Source = result.Source
err := encoder.Encode(data)
2020-08-15 23:11:27 +00:00
if err != nil {
return err
}
}
2020-08-16 15:44:55 +00:00
return nil
2020-08-15 23:11:27 +00:00
}
2021-02-20 17:46:12 +00:00
// WriteSourceHost writes the output list of subdomain to an io.Writer
2022-03-24 20:47:54 +00:00
func (o *OutPutter) WriteSourceHost(input string, sourceMap map[string]map[string]struct{}, writer io.Writer) error {
var err error
if o.JSON {
2022-03-24 20:47:54 +00:00
err = writeSourceJSONHost(input, sourceMap, writer)
} else {
2022-03-24 20:47:54 +00:00
err = writeSourcePlainHost(input, sourceMap, writer)
}
return err
}
2022-03-24 20:47:54 +00:00
func writeSourceJSONHost(input string, sourceMap map[string]map[string]struct{}, writer io.Writer) error {
encoder := jsoniter.NewEncoder(writer)
2022-03-24 20:43:58 +00:00
var data jsonSourcesResult
for host, sources := range sourceMap {
data.Host = host
2022-03-24 20:47:54 +00:00
data.Input = input
keys := make([]string, 0, len(sources))
for source := range sources {
keys = append(keys, source)
}
data.Sources = keys
err := encoder.Encode(&data)
if err != nil {
return err
}
}
return nil
}
2022-03-24 20:47:54 +00:00
func writeSourcePlainHost(_ string, sourceMap map[string]map[string]struct{}, writer io.Writer) error {
bufwriter := bufio.NewWriter(writer)
sb := &strings.Builder{}
for host, sources := range sourceMap {
sb.WriteString(host)
sb.WriteString(",[")
sourcesString := ""
for source := range sources {
sourcesString += source + ","
}
sb.WriteString(strings.Trim(sourcesString, ", "))
sb.WriteString("]\n")
_, err := bufwriter.WriteString(sb.String())
if err != nil {
bufwriter.Flush()
return err
}
sb.Reset()
}
return bufwriter.Flush()
2020-10-14 19:34:07 +00:00
}