fix(archive): decode filename when decompressing zips (#7998 close #7988)

This commit is contained in:
KirCute_ECT 2025-02-16 12:25:01 +08:00 committed by GitHub
parent 30d8c20756
commit c230f24ebe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 43 additions and 6 deletions

View File

@ -59,7 +59,7 @@ func _decompress(file *zip.File, targetPath, password string, up model.UpdatePro
return err return err
} }
defer rc.Close() defer rc.Close()
f, err := os.OpenFile(stdpath.Join(targetPath, file.FileInfo().Name()), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600) f, err := os.OpenFile(stdpath.Join(targetPath, decodeName(file.FileInfo().Name())), os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
if err != nil { if err != nil {
return err return err
} }
@ -87,12 +87,27 @@ func filterPassword(err error) error {
func decodeName(name string) string { func decodeName(name string) string {
b := []byte(name) b := []byte(name)
detector := chardet.NewTextDetector() detector := chardet.NewTextDetector()
result, err := detector.DetectBest(b) results, err := detector.DetectAll(b)
if err != nil { if err != nil {
return name return name
} }
enc := getEncoding(result.Charset) var ce, re, enc encoding.Encoding
if enc == nil { for _, r := range results {
if r.Confidence > 30 {
ce = getCommonEncoding(r.Charset)
if ce != nil {
break
}
}
if re == nil {
re = getEncoding(r.Charset)
}
}
if ce != nil {
enc = ce
} else if re != nil {
enc = re
} else {
return name return name
} }
i := bytes.NewReader(b) i := bytes.NewReader(b)
@ -101,8 +116,30 @@ func decodeName(name string) string {
return string(content) return string(content)
} }
func getCommonEncoding(name string) (enc encoding.Encoding) {
switch name {
case "UTF-8":
enc = unicode.UTF8
case "UTF-16LE":
enc = unicode.UTF16(unicode.LittleEndian, unicode.IgnoreBOM)
case "Shift_JIS":
enc = japanese.ShiftJIS
case "GB-18030":
enc = simplifiedchinese.GB18030
case "EUC-KR":
enc = korean.EUCKR
case "Big5":
enc = traditionalchinese.Big5
default:
enc = nil
}
return
}
func getEncoding(name string) (enc encoding.Encoding) { func getEncoding(name string) (enc encoding.Encoding) {
switch name { switch name {
case "UTF-8":
enc = unicode.UTF8
case "UTF-16BE": case "UTF-16BE":
enc = unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM) enc = unicode.UTF16(unicode.BigEndian, unicode.IgnoreBOM)
case "UTF-16LE": case "UTF-16LE":

View File

@ -35,7 +35,6 @@ func (*Zip) GetMeta(ss *stream.SeekableStream, args model.ArchiveArgs) (model.Ar
for _, file := range zipReader.File { for _, file := range zipReader.File {
if file.IsEncrypted() { if file.IsEncrypted() {
encrypted = true encrypted = true
break
} }
name := strings.TrimPrefix(decodeName(file.Name), "/") name := strings.TrimPrefix(decodeName(file.Name), "/")
@ -70,6 +69,7 @@ func (*Zip) GetMeta(ss *stream.SeekableStream, args model.ArchiveArgs) (model.Ar
dirObj.IsFolder = true dirObj.IsFolder = true
dirObj.Name = stdpath.Base(dir) dirObj.Name = stdpath.Base(dir)
dirObj.Modified = file.ModTime() dirObj.Modified = file.ModTime()
dirObj.Children = make([]model.ObjTree, 0)
} }
if isNewFolder { if isNewFolder {
// 将 文件夹 添加到 父文件夹 // 将 文件夹 添加到 父文件夹

View File

@ -39,7 +39,7 @@ type ArchiveMetaResp struct {
type ArchiveContentResp struct { type ArchiveContentResp struct {
ObjResp ObjResp
Children []ArchiveContentResp `json:"children,omitempty"` Children []ArchiveContentResp `json:"children"`
} }
func toObjsRespWithoutSignAndThumb(obj model.Obj) ObjResp { func toObjsRespWithoutSignAndThumb(obj model.Obj) ObjResp {