//go:build linux || freebsd // +build linux freebsd package protocol import ( "fmt" "net/url" "codeberg.org/petrbalvin/goget/internal/core" ) // ProtocolInfo contains metadata about a protocol type ProtocolInfo struct { // Protocol name Name string // URL scheme Scheme string // Protocol version Version string // Supported operations Operations []string // Supported features Features []string // Default port DefaultPort int } // BaseProtocol is the base implementation for all protocols type BaseProtocol struct { info ProtocolInfo } // NewBaseProtocol creates a new base protocol func NewBaseProtocol(info ProtocolInfo) *BaseProtocol { return &BaseProtocol{info: info} } // Scheme returns the protocol scheme func (bp *BaseProtocol) Scheme() string { return bp.info.Scheme } // Name returns the protocol name func (bp *BaseProtocol) Name() string { return bp.info.Name } // Capabilities returns the list of supported features func (bp *BaseProtocol) Capabilities() []string { return bp.info.Features } // SupportsResume returns whether the protocol supports resume func (bp *BaseProtocol) SupportsResume() bool { return contains(bp.info.Features, "resume") } // SupportsCompression returns whether the protocol supports compression func (bp *BaseProtocol) SupportsCompression() bool { return contains(bp.info.Features, "compression") } // SupportsUpload returns whether the protocol supports upload func (bp *BaseProtocol) SupportsUpload() bool { return contains(bp.info.Features, "upload") } // SupportsRange returns whether the protocol supports range requests func (bp *BaseProtocol) SupportsRange() bool { return contains(bp.info.Features, "range") } // CanHandle checks if this protocol can handle the given URL. func (bp *BaseProtocol) CanHandle(url *url.URL) bool { if url == nil { return false } return url.Scheme == bp.info.Scheme } // SupportsParallel returns whether the protocol supports parallel downloads. func (bp *BaseProtocol) SupportsParallel() bool { return contains(bp.info.Features, "parallel") } // SupportsRecursive returns whether the protocol supports recursive downloads. func (bp *BaseProtocol) SupportsRecursive() bool { return contains(bp.info.Features, "recursive") } // contains is a helper function func contains(slice []string, item string) bool { for _, s := range slice { if s == item { return true } } return false } // ValidateURL validates a URL for the given protocol func ValidateURL(u *url.URL, scheme string) error { if u == nil { return core.NewProtocolError("URL is nil", nil, "") } if u.Scheme != scheme { return core.NewProtocolError( fmt.Sprintf("expected scheme %s, got %s", scheme, u.Scheme), nil, u.String(), ) } if u.Host == "" { return core.NewProtocolError("missing host in URL", nil, u.String()) } return nil } // GetDefaultPort returns the default port for a scheme func GetDefaultPort(scheme string) int { switch scheme { case "http": return 80 case "https", "webdavs": return 443 case "webdav": // Plain WebDAV (no TLS) defaults to 80, matching HTTP. // Previously this returned 443 — a leftover from bundling // "webdav" with the TLS-bearing schemes — which made // non-TLS WebDAV connections fail against servers not // listening on 443. return 80 case "ftp": return 21 case "ftps": return 990 case "sftp": return 22 default: return 0 } }