From c68ee09559a9256e69297bde9e39a0a19956bdab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=97=E5=AD=90?= Date: Mon, 28 Oct 2024 02:56:53 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E5=8E=8B=E7=BC=A9?= =?UTF-8?q?=E8=A7=A3=E5=8E=8B=E9=94=99=E8=AF=AF=E8=BE=93=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/io/compress.go | 33 +++++++++++++--------------- pkg/shell/exec.go | 22 +++++++++++++++++++ web/src/utils/file/index.ts | 8 ++++--- web/src/views/file/CompressModal.vue | 7 +++--- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/pkg/io/compress.go b/pkg/io/compress.go index 75a83e6ad0..fcdc174758 100644 --- a/pkg/io/compress.go +++ b/pkg/io/compress.go @@ -2,7 +2,7 @@ package io import ( "errors" - "os/exec" + "github.com/TheTNB/panel/pkg/shell" "path/filepath" "strings" ) @@ -41,26 +41,24 @@ func Compress(dir string, src []string, dst string) error { return err } - cmd := new(exec.Cmd) switch format { case Zip: - cmd = exec.Command("zip", append([]string{"-qr", "-o", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "zip -qr -o %s %s", dst, strings.Join(src, " ")) case TGz: - cmd = exec.Command("tar", append([]string{"-czf", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "tar -czf %s %s", dst, strings.Join(src, " ")) case Bz2: - cmd = exec.Command("tar", append([]string{"-cjf", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "tar -cjf %s %s", dst, strings.Join(src, " ")) case Tar: - cmd = exec.Command("tar", append([]string{"-cf", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "tar -cf %s %s", dst, strings.Join(src, " ")) case Xz: - cmd = exec.Command("tar", append([]string{"-cJf", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "tar -cJf %s %s", dst, strings.Join(src, " ")) case SevenZip: - cmd = exec.Command("7z", append([]string{"a", "-y", dst}, src...)...) + _, err = shell.ExecfWithDir(dir, "7z a -y %s %s", dst, strings.Join(src, " ")) default: return errors.New("unsupported format") } - cmd.Dir = dir - return cmd.Run() + return err } // UnCompress 解压文件 @@ -79,25 +77,24 @@ func UnCompress(src string, dst string) error { return err } - var cmd *exec.Cmd switch format { case Zip: - cmd = exec.Command("unzip", "-qo", src, "-d", dst) + _, err = shell.Execf("unzip -qo '%s' -d '%s'", src, dst) case TGz: - cmd = exec.Command("tar", "-xzf", src, "-C", dst) + _, err = shell.Execf("tar -xzf '%s' -C '%s'", src, dst) case Bz2: - cmd = exec.Command("tar", "-xjf", src, "-C", dst) + _, err = shell.Execf("tar -xjf '%s' -C '%s'", src, dst) case Tar: - cmd = exec.Command("tar", "-xf", src, "-C", dst) + _, err = shell.Execf("tar -xf '%s' -C '%s'", src, dst) case Xz: - cmd = exec.Command("tar", "-xJf", src, "-C", dst) + _, err = shell.Execf("tar -xJf '%s' -C '%s'", src, dst) case SevenZip: - cmd = exec.Command("7z", "x", "-y", src, "-o"+dst) + _, err = shell.Execf("7z x -y '%s' -o'%s'", src, dst) default: return errors.New("unsupported format") } - return cmd.Run() + return err } // formatArchiveByPath 根据文件后缀获取压缩格式 diff --git a/pkg/shell/exec.go b/pkg/shell/exec.go index b4e9d910f4..cd75ef0f63 100644 --- a/pkg/shell/exec.go +++ b/pkg/shell/exec.go @@ -126,6 +126,28 @@ func ExecfWithPipe(ctx context.Context, shell string, args ...any) (out io.ReadC return } +// ExecfWithDir 在指定目录下执行 shell 命令 +func ExecfWithDir(dir, shell string, args ...any) (string, error) { + if !preCheckArg(args) { + return "", errors.New("command contains illegal characters") + } + + _ = os.Setenv("LC_ALL", "C") + cmd := exec.Command("bash", "-c", fmt.Sprintf(shell, args...)) + cmd.Dir = dir + + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + + err := cmd.Run() + if err != nil { + return strings.TrimSpace(stdout.String()), errors.New(strings.TrimSpace(stderr.String())) + } + + return strings.TrimSpace(stdout.String()), err +} + func preCheckArg(args []any) bool { illegals := []any{`&`, `|`, `;`, `$`, `'`, `"`, "`", `(`, `)`, "\n", "\r", `>`, `<`} for arg := range slices.Values(args) { diff --git a/web/src/utils/file/index.ts b/web/src/utils/file/index.ts index 835dd9663e..057b59339d 100644 --- a/web/src/utils/file/index.ts +++ b/web/src/utils/file/index.ts @@ -32,10 +32,12 @@ const getIconByExt = (ext: string) => { case 'ape': return 'bi:file-earmark-music' case 'zip': - case 'rar': - case '7z': + case 'bz2': case 'tar': case 'gz': + case 'tgz': + case 'xz': + case '7z': return 'bi:file-earmark-zip' case 'doc': case 'docx': @@ -288,7 +290,7 @@ const getFilename = (path: string) => { const isCompress = (name: string) => { const ext = getExt(name) - return ['zip', 'rar', '7z', 'tar', 'gz'].includes(ext) + return ['zip', 'bz2', 'tar', 'gz', 'tgz', 'xz', '7z'].includes(ext) } const formatPercent = (num: any) => { diff --git a/web/src/views/file/CompressModal.vue b/web/src/views/file/CompressModal.vue index 71c0732a98..6e27f4102a 100644 --- a/web/src/views/file/CompressModal.vue +++ b/web/src/views/file/CompressModal.vue @@ -79,12 +79,13 @@ onMounted(() => { v-model:value="format" :options="[ { label: '.zip', value: '.zip' }, - { label: '.gz', value: '.gz' }, - { label: '.xz', value: '.xz' }, { label: '.bz2', value: '.bz2' }, { label: '.tar', value: '.tar' }, + { label: '.gz', value: '.gz' }, { label: '.tar.gz', value: '.tar.gz' }, - { label: '.tar.bz2', value: '.tar.bz2' } + { label: '.tgz', value: '.tgz' }, + { label: '.xz', value: '.xz' }, + { label: '.7z', value: '.7z' } ]" @update:value="ensureExtension" />