- StdinSource reads from an injectable io.Reader (INPUT-03) - URLSource fetches http/https with 30s timeout, 50MB cap, scheme whitelist, and Content-Type filter (INPUT-04) - ClipboardSource wraps atotto/clipboard with graceful fallback for missing tooling (INPUT-05) - emitByteChunks local helper mirrors file.go windowing to stay independent of sibling wave-1 plans - Tests cover happy path, cancellation, redirects, oversize bodies, binary content types, scheme rejection, and clipboard error paths
46 lines
1.3 KiB
Go
46 lines
1.3 KiB
Go
package sources
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"github.com/atotto/clipboard"
|
|
|
|
"github.com/salvacybersec/keyhunter/pkg/types"
|
|
)
|
|
|
|
// ClipboardSource reads the current OS clipboard contents and emits them
|
|
// as a single chunk stream with Source="clipboard". Requires xclip/xsel/
|
|
// wl-clipboard on Linux, pbpaste on macOS, or native API on Windows.
|
|
type ClipboardSource struct {
|
|
// Reader overrides the clipboard reader; when nil the real clipboard is used.
|
|
// Tests inject a func returning a fixture.
|
|
Reader func() (string, error)
|
|
ChunkSize int
|
|
}
|
|
|
|
// NewClipboardSource returns a ClipboardSource bound to the real OS clipboard.
|
|
func NewClipboardSource() *ClipboardSource {
|
|
return &ClipboardSource{Reader: clipboard.ReadAll, ChunkSize: defaultChunkSize}
|
|
}
|
|
|
|
// Chunks reads the clipboard and emits its contents.
|
|
func (c *ClipboardSource) Chunks(ctx context.Context, out chan<- types.Chunk) error {
|
|
if clipboard.Unsupported && c.Reader == nil {
|
|
return errors.New("ClipboardSource: clipboard tooling unavailable (install xclip/xsel/wl-clipboard on Linux)")
|
|
}
|
|
reader := c.Reader
|
|
if reader == nil {
|
|
reader = clipboard.ReadAll
|
|
}
|
|
text, err := reader()
|
|
if err != nil {
|
|
return fmt.Errorf("ClipboardSource: read: %w", err)
|
|
}
|
|
if text == "" {
|
|
return nil
|
|
}
|
|
return emitByteChunks(ctx, []byte(text), "clipboard", c.ChunkSize, out)
|
|
}
|