Files
ryan 699e95f12c perfsprint 18→0:strconv.Itoa/FormatInt/FormatUint/FormatBool 替代 fmt.Sprintf、无动词 fmt.Errorf→errors.New、纯字符串拼接。全部语义等价(已核对 diff)。修正 fixer 遗留的 import 问题(引入 goimports 统一整理)。
Result: {"status":"keep","total_issues":56,"golint_canonicalheader":8,"golint_errname":1,"golint_errorlint":12,"golint_forcetypeassert":3,"golint_gosec":0,"golint_intrange":3,"golint_modernize":5,"golint_nilnil":3,"golint_perfsprint":0,"golint_prealloc":3,"golint_recvcheck":7,"golint_usestdlibvars":3,"golint_wastedassign":7,"golint_total":55,"eslint_problems":1,"eslint_errors":0,"eslint_warnings":1,"tsc_errors":0,"measure_s":47}
2026-08-16 17:34:44 +08:00

192 lines
5.2 KiB
Go

// Copyright 2026 Arctel.net
// SPDX-License-Identifier: Apache-2.0
// Package pagesarchive provides multi-format archive detection, inspection and
// extraction helpers for OpenFlare Pages deployment packages.
package pagesarchive
import (
"bytes"
"errors"
"path/filepath"
"strings"
)
// Format identifies a supported Pages deployment package archive format.
type Format string
const (
// FormatZip is a ZIP archive.
FormatZip Format = "zip"
// FormatTar is an uncompressed tar archive.
FormatTar Format = "tar"
// FormatTarGz is a gzip-compressed tar archive.
FormatTarGz Format = "tar.gz"
// FormatTarXz is an xz-compressed tar archive.
FormatTarXz Format = "tar.xz"
// FormatTarBz2 is a bzip2-compressed tar archive.
FormatTarBz2 Format = "tar.bz2"
// FormatSevenZip is a 7z archive.
FormatSevenZip Format = "7z"
ustarMagicOffset = 257
ustarMagicMinLen = 262
)
// DetectFormatFromName returns the archive format inferred from a file name.
// Returns an empty Format and false when the extension is unsupported.
func DetectFormatFromName(fileName string) (Format, bool) {
name := strings.ToLower(strings.TrimSpace(fileName))
switch {
case strings.HasSuffix(name, ".tar.gz"), strings.HasSuffix(name, ".tgz"):
return FormatTarGz, true
case strings.HasSuffix(name, ".tar.xz"), strings.HasSuffix(name, ".txz"):
return FormatTarXz, true
case strings.HasSuffix(name, ".tar.bz2"), strings.HasSuffix(name, ".tbz2"), strings.HasSuffix(name, ".tbz"):
return FormatTarBz2, true
case strings.HasSuffix(name, ".tar"):
return FormatTar, true
case strings.HasSuffix(name, ".7z"):
return FormatSevenZip, true
case strings.HasSuffix(name, ".zip"):
return FormatZip, true
default:
return "", false
}
}
// DetectFormatFromBytes returns the archive format inferred from magic bytes.
// Prefer DetectFormatFromName when a reliable file name is available.
func DetectFormatFromBytes(data []byte) (Format, bool) {
if isZipMagic(data) {
return FormatZip, true
}
if isSevenZipMagic(data) {
return FormatSevenZip, true
}
if isXZMagic(data) {
return FormatTarXz, true
}
if isGzipMagic(data) {
return FormatTarGz, true
}
if isBzip2Magic(data) {
return FormatTarBz2, true
}
if looksLikeTar(data) {
return FormatTar, true
}
return "", false
}
// DetectFormat prefers the file name when present, otherwise magic bytes.
func DetectFormat(fileName string, data []byte) (Format, error) {
if format, ok := DetectFormatFromName(fileName); ok {
return format, nil
}
if format, ok := DetectFormatFromBytes(data); ok {
return format, nil
}
return "", errors.New("unsupported pages package format")
}
// Extension returns the canonical file extension for a format (without leading dot).
func Extension(format Format) string {
switch format {
case FormatZip:
return "zip"
case FormatTar:
return "tar"
case FormatTarGz:
return "tar.gz"
case FormatTarXz:
return "tar.xz"
case FormatTarBz2:
return "tar.bz2"
case FormatSevenZip:
return "7z"
default:
return "bin"
}
}
// MIMEType returns a reasonable content type for the archive format.
func MIMEType(format Format) string {
switch format {
case FormatZip:
return "application/zip"
case FormatTar:
return "application/x-tar"
case FormatTarGz:
return "application/gzip"
case FormatTarXz:
return "application/x-xz"
case FormatTarBz2:
return "application/x-bzip2"
case FormatSevenZip:
return "application/x-7z-compressed"
default:
return "application/octet-stream"
}
}
// SupportedExtensions lists human-readable extensions for UI copy and accept attributes.
func SupportedExtensions() []string {
return []string{".zip", ".tar.gz", ".tgz", ".tar.xz", ".txz", ".tar.bz2", ".tbz2", ".tar", ".7z"}
}
// AcceptAttribute returns a comma-separated accept list for file inputs.
func AcceptAttribute() string {
return strings.Join(SupportedExtensions(), ",")
}
// NormalizeNameExtension returns a storage-safe extension for the given format/name.
func NormalizeNameExtension(fileName string, format Format) string {
if format != "" {
return Extension(format)
}
if formatFromName, ok := DetectFormatFromName(fileName); ok {
return Extension(formatFromName)
}
ext := strings.TrimPrefix(filepath.Ext(fileName), ".")
if ext == "" {
return "bin"
}
return strings.ToLower(ext)
}
func isZipMagic(data []byte) bool {
return len(data) >= 4 &&
data[0] == 0x50 && data[1] == 0x4b &&
(data[2] == 0x03 || data[2] == 0x05 || data[2] == 0x07) &&
(data[3] == 0x04 || data[3] == 0x06 || data[3] == 0x08)
}
func isSevenZipMagic(data []byte) bool {
return len(data) >= 6 &&
data[0] == 0x37 && data[1] == 0x7a && data[2] == 0xbc &&
data[3] == 0xaf && data[4] == 0x27 && data[5] == 0x1c
}
func isXZMagic(data []byte) bool {
return len(data) >= 6 &&
data[0] == 0xfd && data[1] == 0x37 && data[2] == 0x7a &&
data[3] == 0x58 && data[4] == 0x5a && data[5] == 0x00
}
func isGzipMagic(data []byte) bool {
return len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b
}
func isBzip2Magic(data []byte) bool {
return len(data) >= 3 && data[0] == 0x42 && data[1] == 0x5a && data[2] == 0x68
}
func looksLikeTar(data []byte) bool {
// POSIX ustar magic at offset 257 ("ustar\0" or "ustar ").
if len(data) < ustarMagicMinLen {
return false
}
return bytes.Equal(data[ustarMagicOffset:ustarMagicOffset+5], []byte("ustar"))
}