Help us shape the future of Go! Take the 2026 Go Developer Survey

archivecli

package
v0.44.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 25, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package archivecli runs operator-provided archive tools behind a small, fixed interface. It never evaluates a shell command: provider arguments are assembled here and the executable path comes only from process config.

Index

Constants

View Source
const (
	SettingEnabled          = "archive.enabled"
	SettingDefaultFormat    = "archive.default_format"
	SettingAllowedFormats   = "archive.allowed_formats"
	SettingMaxEntries       = "archive.max_entries"
	SettingMaxExpandedBytes = "archive.max_expanded_bytes"
	SettingTimeoutSeconds   = "archive.timeout_seconds"

	DefaultMaxEntries       = 20_000
	DefaultMaxExpandedBytes = int64(20 << 30)
	DefaultTimeout          = 30 * time.Minute
)

Variables

View Source
var (
	ErrUnavailable      = errors.New("archive provider unavailable")
	ErrPasswordRequired = errors.New("archive password required")
	ErrBadPassword      = errors.New("incorrect archive password")
	ErrUnsupported      = errors.New("unsupported archive format")
	ErrLimits           = errors.New("archive exceeds configured limits")
	// ErrPasswordCharset: a password 7-Zip cannot take. It reads one LINE from
	// stdin, so a line break cannot be part of one, and it refuses to encrypt
	// a ZIP with anything but printable ASCII (E_INVALIDARG) — said up front
	// instead of as "archive provider failed" after the files were staged.
	ErrPasswordCharset = errors.New("archive password contains characters this format cannot use")
)

Functions

func CanonicalFormat

func CanonicalFormat(v string) string

func CanonicalFormats

func CanonicalFormats(in []string) []string

func CheckPassword

func CheckPassword(password, format string) error

CheckPassword refuses what 7-Zip cannot be given: a line break ends the one line it reads, and ZIP encryption takes printable ASCII only.

func CleanMemberPath

func CleanMemberPath(name string) (string, error)

CleanMemberPath turns an archive member name into a safe relative path, or refuses it. One rule for every reader (archive/zip in the handlers, TAR here): backslashes are separators, leading slashes and "./" are dropped, a drive letter or any ".." component is refused.

func FormatFromPath

func FormatFromPath(name string) string

func IsCreateFormat

func IsCreateFormat(format string) bool

func Preflight

func Preflight(entries []Entry, policy Policy) error

Preflight judges a listing before anything is extracted, the same way for every reader: each member must have a clean relative path, be a file or a folder (never a link or a special file) and say how large it is; the declared sizes and the number of entries must fit the policy.

func ReadsItself

func ReadsItself(logicalName string) bool

ReadsItself reports whether filex reads this archive without 7-Zip (xz layers aside): ZIP through archive/zip, the TAR family and gzip/bzip2 here.

func ValidDictionarySizeMiB

func ValidDictionarySizeMiB(size int) bool

ValidDictionarySizeMiB bounds 7z's memory use to explicit, predictable powers of two. Zero means let 7-Zip choose its format/level default.

Types

type Config

type Config struct {
	SevenZipBin string
	WorkDir     string
}

Config contains the operator-owned settings. Binary is never writable over HTTP because changing it is equivalent to allowing arbitrary code execution.

type CreateOptions

type CreateOptions struct {
	Format            string
	Password          string
	EncryptNames      bool
	Compression       int
	Solid             *bool
	DictionarySizeMiB int
	Progress          func(percent int)
}

CreateOptions is the fixed, validated set of switches filex may pass to an archive provider. Keeping this typed prevents a browser from smuggling raw command-line arguments into the process invocation.

type Entry

type Entry struct {
	Name      string    `json:"name"`
	Size      int64     `json:"size"`
	Mtime     time.Time `json:"mtime"`
	IsDir     bool      `json:"is_dir"`
	Encrypted bool      `json:"encrypted,omitempty"`
	IsLink    bool      `json:"is_link,omitempty"`
	// Special: a FIFO, a device or a socket — neither a file nor a folder.
	Special bool `json:"special,omitempty"`
	// SizeUnknown: the archive does not say how large this member is (a RAR5
	// stream written by `rar -si` sets that flag; 7-Zip lists `Size = ` empty).
	// 7-Zip then decodes it to the end of its data, so nothing before the
	// extraction can hold it to the limit: Preflight refuses it.
	SizeUnknown bool `json:"-"`
}

Entry is one archive member as reported by the provider.

func (Entry) Refused

func (e Entry) Refused() bool

Refused reports a member filex never extracts: a link or a special file.

type Policy

type Policy struct {
	Enabled          bool     `json:"enabled"`
	DefaultFormat    string   `json:"default_format"`
	AllowedFormats   []string `json:"allowed_formats"`
	MaxEntries       int      `json:"max_entries"`
	MaxExpandedBytes int64    `json:"max_expanded_bytes"`
	TimeoutSeconds   int      `json:"timeout_seconds"`
}

Policy is the live, admin-writable archive policy.

type ProviderStatus

type ProviderStatus struct {
	Name           string   `json:"name"`
	Available      bool     `json:"available"`
	Version        string   `json:"version,omitempty"`
	CreateFormats  []string `json:"create_formats"`
	ExtractFormats []string `json:"extract_formats"`
	Encrypted      bool     `json:"encrypted"`
	Error          string   `json:"error,omitempty"`
	// RequiredVersion: the oldest version filex accepts, so the admin page can
	// say what to install in its own language.
	RequiredVersion string `json:"required_version,omitempty"`
}

ProviderStatus describes an archive provider without exposing host paths.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service resolves and invokes supported archive providers.

func New

func New(store SettingsStore, cfg Config) *Service

func (*Service) Create

func (s *Service) Create(ctx context.Context, sourceDir, destPath string, opts CreateOptions) error

Create builds an archive from the entire contents of sourceDir. Compressed TAR formats stream the TAR producer directly into gzip, bzip2 or xz, avoiding a potentially large intermediate file. sourceDir is an isolated workspace prepared by filex, so no user-controlled path becomes an option and no host path can be archived accidentally.

func (*Service) Extract

func (s *Service) Extract(ctx context.Context, archivePath, destDir, password string, members []string) error

Extract expands archivePath, taking its format from its own name.

func (*Service) ExtractAs

func (s *Service) ExtractAs(ctx context.Context, archivePath, logicalName, destDir, password string, members []string) error

ExtractAs expands an archive the user calls logicalName into destDir, an empty private workspace, while enforcing the live archive policy. The caller still validates paths and file types before copying anything into a storage driver.

The TAR family and bare gzip/bzip2/xz are read by filex (stream.go): exact limits, links refused from the header. 7z, RAR and ZIP go through 7-Zip, whose decoders stop at each member's declared size — the preflight checks those — with the workspace monitor as the backstop for a format that does not declare one.

func (*Service) List

func (s *Service) List(ctx context.Context, archivePath, password string) ([]Entry, error)

List lists archivePath, taking its format from its own name.

func (*Service) ListAs

func (s *Service) ListAs(ctx context.Context, archivePath, logicalName, password string) ([]Entry, error)

ListAs lists archivePath as the format logicalName names. The TAR family and bare gzip/bzip2/xz are read here (stream.go); 7z, RAR and ZIP through 7-Zip, which prints stable Path/Size/Modified/Attributes blocks.

func (*Service) Policy

func (s *Service) Policy(ctx context.Context) Policy

Policy returns validated defaults when a setting is absent or malformed.

func (*Service) Providers

func (s *Service) Providers(ctx context.Context) []ProviderStatus

func (*Service) SevenZipAvailable

func (s *Service) SevenZipAvailable(ctx context.Context) bool

SevenZipAvailable reports whether a supported 7-Zip is usable right now: installed, new enough, and not switched off in the archive policy.

func (*Service) Test

func (s *Service) Test(ctx context.Context, archivePath, password string) error

Test validates that every member can be decrypted without materialising it. Listing alone is insufficient for ZIP and non-header-encrypted 7z archives: 7-Zip can reveal their names without ever checking the content password.

func (*Service) TestAs

func (s *Service) TestAs(ctx context.Context, archivePath, logicalName, password string) error

TestAs is Test for an archive the user calls logicalName.

func (*Service) WorkDir

func (s *Service) WorkDir() string

type SettingsStore

type SettingsStore interface {
	GetSetting(context.Context, string) (string, error)
	UpsertSetting(context.Context, string, string) error
}

SettingsStore is the deliberately tiny settings-table surface used here.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL