mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 16:00:51 +00:00
fix: prevent reading of binary preview files and improve file type handling (#12984)
This commit is contained in:
@@ -720,6 +720,9 @@ func (f *FileService) GetPreviewContent(op request.FileContentReq) (response.Fil
|
||||
return response.FileInfo{}, err
|
||||
}
|
||||
|
||||
if files.IsBinaryPreviewFile(info.MimeType, info.Extension) {
|
||||
return response.FileInfo{}, buserr.New("ErrFileCanNotRead")
|
||||
}
|
||||
if files.IsBlockDevice(info.FileMode) {
|
||||
return response.FileInfo{FileInfo: *info}, nil
|
||||
}
|
||||
@@ -932,6 +935,9 @@ func readEditableFileHistoryContent(filePath string) ([]byte, os.FileMode, bool)
|
||||
if mode.IsDir() || mode&os.ModeSymlink != 0 || !mode.IsRegular() || files.IsBlockDevice(mode) || info.Size() > fileHistorySnapshotMaxSize {
|
||||
return nil, mode, false
|
||||
}
|
||||
if files.IsBinaryPreviewFile(files.GetMimeType(filePath), filepath.Ext(info.Name())) {
|
||||
return nil, mode, false
|
||||
}
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return nil, mode, false
|
||||
|
||||
@@ -21,6 +21,76 @@ import (
|
||||
"github.com/spf13/afero"
|
||||
)
|
||||
|
||||
var binaryPreviewMimeTypes = map[string]struct{}{
|
||||
"application/pdf": {},
|
||||
"application/zip": {},
|
||||
"application/gzip": {},
|
||||
"application/x-gzip": {},
|
||||
"application/x-7z-compressed": {},
|
||||
"application/x-rar-compressed": {},
|
||||
"application/x-bzip2": {},
|
||||
"application/x-xz": {},
|
||||
"application/x-tar": {},
|
||||
"application/java-archive": {},
|
||||
"application/msword": {},
|
||||
"application/vnd.ms-excel": {},
|
||||
"application/vnd.ms-powerpoint": {},
|
||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": {},
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": {},
|
||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation": {},
|
||||
}
|
||||
|
||||
var binaryPreviewMimePrefixes = []string{
|
||||
"image/",
|
||||
"audio/",
|
||||
"video/",
|
||||
"application/vnd.ms-",
|
||||
"application/vnd.openxmlformats-officedocument.",
|
||||
"application/vnd.oasis.opendocument.",
|
||||
}
|
||||
|
||||
var binaryPreviewExtensions = map[string]struct{}{
|
||||
".pdf": {},
|
||||
".zip": {},
|
||||
".gz": {},
|
||||
".bz2": {},
|
||||
".xz": {},
|
||||
".tar": {},
|
||||
".tgz": {},
|
||||
".rar": {},
|
||||
".7z": {},
|
||||
".war": {},
|
||||
".doc": {},
|
||||
".docx": {},
|
||||
".xls": {},
|
||||
".xlsx": {},
|
||||
".ppt": {},
|
||||
".pptx": {},
|
||||
".jpg": {},
|
||||
".jpeg": {},
|
||||
".png": {},
|
||||
".bmp": {},
|
||||
".gif": {},
|
||||
".tiff": {},
|
||||
".ico": {},
|
||||
".webp": {},
|
||||
".svg": {},
|
||||
".mp3": {},
|
||||
".wav": {},
|
||||
".wma": {},
|
||||
".ape": {},
|
||||
".acc": {},
|
||||
".ogg": {},
|
||||
".flac": {},
|
||||
".mp4": {},
|
||||
".webm": {},
|
||||
".mov": {},
|
||||
".wmv": {},
|
||||
".mkv": {},
|
||||
".avi": {},
|
||||
".flv": {},
|
||||
}
|
||||
|
||||
type FileInfo struct {
|
||||
Fs afero.Fs `json:"-"`
|
||||
Path string `json:"path"`
|
||||
@@ -418,6 +488,9 @@ func (f *FileInfo) getContent() error {
|
||||
if f.Size > 10*1024*1024 {
|
||||
return buserr.New("ErrFileToLarge")
|
||||
}
|
||||
if IsBinaryPreviewFile(f.MimeType, f.Extension) {
|
||||
return buserr.New("ErrFileCanNotRead")
|
||||
}
|
||||
afs := &afero.Afero{Fs: f.Fs}
|
||||
cByte, err := afs.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
@@ -430,8 +503,39 @@ func (f *FileInfo) getContent() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsBinaryPreviewFile(mimeType, extension string) bool {
|
||||
mimeType = strings.ToLower(strings.TrimSpace(mimeType))
|
||||
extension = strings.ToLower(strings.TrimSpace(extension))
|
||||
|
||||
if mimeType == "" || mimeType == "application/octet-stream" {
|
||||
_, ok := binaryPreviewExtensions[extension]
|
||||
return ok
|
||||
}
|
||||
|
||||
if strings.HasPrefix(mimeType, "text/") {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, prefix := range binaryPreviewMimePrefixes {
|
||||
if strings.HasPrefix(mimeType, prefix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
_, ok := binaryPreviewMimeTypes[mimeType]
|
||||
if ok {
|
||||
return true
|
||||
}
|
||||
|
||||
_, ok = binaryPreviewExtensions[extension]
|
||||
return ok
|
||||
}
|
||||
|
||||
func DetectBinary(buf []byte) bool {
|
||||
mimeType := http.DetectContentType(buf)
|
||||
if IsBinaryPreviewFile(mimeType, "") {
|
||||
return true
|
||||
}
|
||||
if !strings.HasPrefix(mimeType, "text/") {
|
||||
whiteByte := 0
|
||||
n := min(1024, len(buf))
|
||||
@@ -445,7 +549,6 @@ func DetectBinary(buf []byte) bool {
|
||||
return whiteByte < 1
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
class="monaco-editor sm:w-48 w-1/3 monaco-editor-background border-0 tree-container"
|
||||
v-if="isShow"
|
||||
>
|
||||
<div class="flex items-center justify-between pl-1 pr-1 py-0.5 h-6">
|
||||
<div class="flex items-center justify-between px-1 h-7">
|
||||
<el-text size="small" @click="getUpData()" class="cursor-pointer">
|
||||
<el-icon>
|
||||
<Top />
|
||||
@@ -245,22 +245,24 @@
|
||||
:on-remove-other-tab="removeOtherTab"
|
||||
></CodeTabs>
|
||||
<div ref="codeBox" class="relative" :style="{ height: codeHeight }">
|
||||
<el-icon
|
||||
v-if="isShow"
|
||||
class="cursor-pointer absolute bg-gray-100 py-2 rounded-l-sm block top-1/3 -left-[9px]"
|
||||
size="9"
|
||||
@click="toggleShow"
|
||||
>
|
||||
<DArrowLeft />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-else
|
||||
class="cursor-pointer absolute bg-gray-100 py-2 rounded-r-sm block top-1/3 z-50"
|
||||
size="9"
|
||||
@click="toggleShow"
|
||||
>
|
||||
<DArrowRight />
|
||||
</el-icon>
|
||||
<div class="absolute top-1/3">
|
||||
<el-icon
|
||||
v-if="isShow"
|
||||
class="cursor-pointer bg-gray-100 py-2 rounded-l-sm block -left-[9px]"
|
||||
size="9"
|
||||
@click="toggleShow"
|
||||
>
|
||||
<DArrowLeft />
|
||||
</el-icon>
|
||||
<el-icon
|
||||
v-else
|
||||
class="cursor-pointer bg-gray-100 py-2 rounded-r-sm block z-50"
|
||||
size="9"
|
||||
@click="toggleShow"
|
||||
>
|
||||
<DArrowRight />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div class="flex justify-center items-center h-full" v-if="fileTabs.length === 0">
|
||||
<el-empty :image="noUpdateImage" />
|
||||
</div>
|
||||
@@ -268,7 +270,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="hidden code-footer pl-4 h-6 sm:flex justify-end items-center gap-4 rounded-b"
|
||||
class="hidden code-footer pl-4 h-7 sm:flex justify-end items-center gap-4 rounded-b"
|
||||
ref="dialogFooter"
|
||||
>
|
||||
<el-divider direction="vertical" class="!h-6" v-if="config.theme" />
|
||||
@@ -305,8 +307,7 @@
|
||||
</el-dropdown>
|
||||
<el-divider direction="vertical" class="!h-6" />
|
||||
<el-text class="cursor-pointer inline-flex items-center gap-1" @click="openHistoryDrawer">
|
||||
<span>{{ $t('file.history') }}</span>
|
||||
<span class="text-xs text-gray-500">({{ historyVersionCount }})</span>
|
||||
<span class="el-dropdown-link">{{ $t('file.history') }} ({{ historyVersionCount }})</span>
|
||||
</el-text>
|
||||
<el-divider direction="vertical" class="!h-6" />
|
||||
<el-dropdown trigger="click" max-height="300" placement="top" @command="changeLanguage">
|
||||
|
||||
@@ -1548,6 +1548,10 @@ const getFileExtension = (name: string, extension?: string): string => {
|
||||
|
||||
const openView = (item: File.File) => {
|
||||
const fileType = getFileType(item.extension);
|
||||
if (fileType == 'pdf') {
|
||||
MsgWarning(i18n.global.t('file.fileCanNotRead'));
|
||||
return;
|
||||
}
|
||||
if (fileType === 'image') {
|
||||
imageFiles.value = data.value
|
||||
.filter((item) => !item.isDir)
|
||||
|
||||
Reference in New Issue
Block a user