refactor(file): refactor file format check function
This commit is contained in:
+62
-19
@@ -20,13 +20,18 @@
|
||||
package checker
|
||||
|
||||
import (
|
||||
"golang.org/x/image/webp"
|
||||
"fmt"
|
||||
"image"
|
||||
_ "image/gif" // use init to support decode jpeg,jpg,png,gif
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/segmentfault/pacman/log"
|
||||
"golang.org/x/image/webp"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -35,47 +40,85 @@ const (
|
||||
|
||||
// IsSupportedImageFile currently answers support image type is
|
||||
// `image/jpeg, image/jpg, image/png, image/gif, image/webp`
|
||||
func IsSupportedImageFile(file io.Reader, ext string) bool {
|
||||
ext = strings.ToLower(strings.TrimPrefix(ext, "."))
|
||||
var err error
|
||||
func IsSupportedImageFile(localFilePath string) bool {
|
||||
ext := strings.ToLower(strings.TrimPrefix(filepath.Ext(localFilePath), "."))
|
||||
switch ext {
|
||||
case "jpg", "jpeg", "png", "gif": // only allow for `image/jpeg,image/jpg,image/png, image/gif`
|
||||
if !checkImageSize(file) {
|
||||
if !decodeAndCheckImageFile(localFilePath, standardImageConfigCheck) {
|
||||
return false
|
||||
}
|
||||
if !decodeAndCheckImageFile(localFilePath, standardImageCheck) {
|
||||
return false
|
||||
}
|
||||
_, _, err = image.Decode(file)
|
||||
case "ico":
|
||||
// TODO: There is currently no good Golang library to parse whether the image is in ico format.
|
||||
return true
|
||||
case "webp":
|
||||
if !checkWebpSize(file) {
|
||||
if !decodeAndCheckImageFile(localFilePath, webpImageConfigCheck) {
|
||||
return false
|
||||
}
|
||||
if !decodeAndCheckImageFile(localFilePath, webpImageCheck) {
|
||||
return false
|
||||
}
|
||||
_, err = webp.Decode(file)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return err == nil
|
||||
return true
|
||||
}
|
||||
|
||||
func checkImageSize(file io.Reader) bool {
|
||||
func decodeAndCheckImageFile(localFilePath string, checker func(io.Reader) error) bool {
|
||||
file, err := os.Open(localFilePath)
|
||||
if err != nil {
|
||||
log.Errorf("open file error: %v", err)
|
||||
return false
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
if err = checker(file); err != nil {
|
||||
log.Errorf("check image format error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func standardImageConfigCheck(file io.Reader) error {
|
||||
config, _, err := image.DecodeConfig(file)
|
||||
if err != nil {
|
||||
return false
|
||||
return fmt.Errorf("decode image config error: %v", err)
|
||||
}
|
||||
if (config.Width * config.Height) > maxImageSize {
|
||||
return false
|
||||
if imageSizeTooLarge(config) {
|
||||
return fmt.Errorf("image size too large")
|
||||
}
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkWebpSize(file io.Reader) bool {
|
||||
func standardImageCheck(file io.Reader) error {
|
||||
_, _, err := image.Decode(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode image error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func webpImageConfigCheck(file io.Reader) error {
|
||||
config, err := webp.DecodeConfig(file)
|
||||
if err != nil {
|
||||
return false
|
||||
return fmt.Errorf("decode webp image config error: %v", err)
|
||||
}
|
||||
if (config.Width * config.Height) > maxImageSize {
|
||||
return false
|
||||
if imageSizeTooLarge(config) {
|
||||
return fmt.Errorf("image size too large")
|
||||
}
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
func webpImageCheck(file io.Reader) error {
|
||||
_, err := webp.Decode(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("decode webp image error: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func imageSizeTooLarge(config image.Config) bool {
|
||||
return config.Width*config.Height > maxImageSize
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user