Files

152 lines
3.4 KiB
Go

//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
}
}