Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/scan/scan_context.go
2070 views
1
package scan
2
3
import (
4
"context"
5
"fmt"
6
"strings"
7
"sync"
8
9
"github.com/projectdiscovery/nuclei/v3/pkg/output"
10
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/contextargs"
11
"github.com/projectdiscovery/utils/errkit"
12
)
13
14
type ScanContextOption func(*ScanContext)
15
16
func WithEvents() ScanContextOption {
17
return func(sc *ScanContext) {
18
sc.withEvents = true
19
}
20
}
21
22
type ScanContext struct {
23
ctx context.Context
24
25
// exported / configurable fields
26
Input *contextargs.Context
27
28
// callbacks or hooks
29
OnError func(error)
30
OnResult func(e *output.InternalWrappedEvent)
31
OnWarning func(string)
32
33
// unexported state fields
34
error error
35
warnings []string
36
events []*output.InternalWrappedEvent
37
results []*output.ResultEvent
38
39
// what to log
40
withEvents bool
41
42
// might not be required but better to sync
43
m sync.Mutex
44
}
45
46
// NewScanContext creates a new scan context using input
47
func NewScanContext(ctx context.Context, input *contextargs.Context) *ScanContext {
48
return &ScanContext{ctx: ctx, Input: input}
49
}
50
51
// Context returns the context of the scan
52
func (s *ScanContext) Context() context.Context {
53
return s.ctx
54
}
55
56
func (s *ScanContext) GenerateErrorMessage() error {
57
return s.error
58
}
59
60
// GenerateResult returns final results slice from all events
61
func (s *ScanContext) GenerateResult() []*output.ResultEvent {
62
s.m.Lock()
63
defer s.m.Unlock()
64
65
return s.results
66
}
67
68
// LogEvent logs events to all events and triggeres any callbacks
69
func (s *ScanContext) LogEvent(e *output.InternalWrappedEvent) {
70
s.m.Lock()
71
defer s.m.Unlock()
72
if e == nil {
73
// do not log nil events
74
return
75
}
76
77
if s.OnResult != nil {
78
s.OnResult(e)
79
}
80
81
if s.withEvents {
82
s.events = append(s.events, e)
83
}
84
85
e.RLock()
86
defer e.RUnlock()
87
88
s.results = append(s.results, e.Results...)
89
}
90
91
// LogError logs error to all events and triggeres any callbacks
92
func (s *ScanContext) LogError(err error) {
93
s.m.Lock()
94
defer s.m.Unlock()
95
if err == nil {
96
return
97
}
98
if s.OnError != nil {
99
s.OnError(err)
100
}
101
if s.error == nil {
102
s.error = err
103
} else {
104
s.error = errkit.Append(s.error, err)
105
}
106
107
errorMessage := s.GenerateErrorMessage().Error()
108
109
for _, result := range s.results {
110
result.Error = errorMessage
111
}
112
113
for _, e := range s.events {
114
e.InternalEvent["error"] = errorMessage
115
}
116
}
117
118
// LogWarning logs warning to all events
119
func (s *ScanContext) LogWarning(format string, args ...any) {
120
s.m.Lock()
121
defer s.m.Unlock()
122
val := fmt.Sprintf(format, args...)
123
124
if s.OnWarning != nil {
125
s.OnWarning(val)
126
}
127
128
s.warnings = append(s.warnings, val)
129
130
for _, e := range s.events {
131
if e.InternalEvent != nil {
132
e.InternalEvent["warning"] = strings.Join(s.warnings, "; ")
133
}
134
}
135
}
136
137