152 lines
3.4 KiB
Go
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
|
||
|
|
}
|
||
|
|
}
|