package component
import (
"context"
"fmt"
"net/http"
"github.com/projectdiscovery/nuclei/v3/pkg/fuzz/dataformat"
"github.com/projectdiscovery/retryablehttp-go"
mapsutil "github.com/projectdiscovery/utils/maps"
)
type Cookie struct {
value *Value
req *retryablehttp.Request
}
var _ Component = &Cookie{}
func NewCookie() *Cookie {
return &Cookie{}
}
func (c *Cookie) Name() string {
return RequestCookieComponent
}
func (c *Cookie) Parse(req *retryablehttp.Request) (bool, error) {
if len(req.Cookies()) == 0 {
return false, nil
}
c.req = req
c.value = NewValue("")
parsedCookies := mapsutil.NewOrderedMap[string, any]()
for _, cookie := range req.Cookies() {
parsedCookies.Set(cookie.Name, cookie.Value)
}
if parsedCookies.Len() == 0 {
return false, nil
}
c.value.SetParsed(dataformat.KVOrderedMap(&parsedCookies), "")
return true, nil
}
func (c *Cookie) Iterate(callback func(key string, value interface{}) error) (err error) {
c.value.parsed.Iterate(func(key string, value any) bool {
if errx := callback(key, value); errx != nil {
err = errx
return false
}
return true
})
return
}
func (c *Cookie) SetValue(key string, value string) error {
if !c.value.SetParsedValue(key, value) {
return ErrSetValue
}
return nil
}
func (c *Cookie) Delete(key string) error {
if !c.value.Delete(key) {
return ErrKeyNotFound
}
return nil
}
func (c *Cookie) Rebuild() (*retryablehttp.Request, error) {
cloned := c.req.Clone(context.Background())
cloned.Header.Del("Cookie")
c.value.parsed.Iterate(func(key string, value any) bool {
cookie := &http.Cookie{
Name: key,
Value: fmt.Sprint(value),
}
cloned.AddCookie(cookie)
return true
})
return cloned, nil
}
func (c *Cookie) Clone() Component {
return &Cookie{
value: c.value.Clone(),
req: c.req.Clone(context.Background()),
}
}