2023-09-11 16:25:39 +00:00
|
|
|
/*
|
|
|
|
Copyright © 2023 Seednode <seednode@seedno.de>
|
|
|
|
*/
|
|
|
|
|
2023-09-12 21:32:19 +00:00
|
|
|
package types
|
2023-09-11 16:25:39 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2023-09-11 21:05:38 +00:00
|
|
|
"net/http"
|
2023-09-11 16:25:39 +00:00
|
|
|
"os"
|
2023-09-12 18:06:45 +00:00
|
|
|
"path/filepath"
|
2023-09-13 04:35:17 +00:00
|
|
|
"slices"
|
|
|
|
"strings"
|
2023-09-11 16:25:39 +00:00
|
|
|
)
|
|
|
|
|
2023-09-13 04:35:17 +00:00
|
|
|
var SupportedFormats = &Types{
|
|
|
|
Extensions: make(map[string]string),
|
|
|
|
MimeTypes: make(map[string]Type),
|
|
|
|
}
|
|
|
|
|
2023-09-13 01:56:39 +00:00
|
|
|
type Type interface {
|
|
|
|
Css() string
|
|
|
|
Title(queryParams, fileUri, filePath, fileName, mime string) string
|
|
|
|
Body(queryParams, fileUri, filePath, fileName, mime string) string
|
|
|
|
Extensions() map[string]string
|
|
|
|
MimeTypes() []string
|
|
|
|
Validate(filePath string) bool
|
2023-09-11 16:25:39 +00:00
|
|
|
}
|
|
|
|
|
2023-09-12 21:32:19 +00:00
|
|
|
type Types struct {
|
2023-09-13 00:46:27 +00:00
|
|
|
Extensions map[string]string
|
2023-09-13 01:56:39 +00:00
|
|
|
MimeTypes map[string]Type
|
2023-09-11 16:25:39 +00:00
|
|
|
}
|
|
|
|
|
2023-09-13 01:56:39 +00:00
|
|
|
func (s *Types) Add(t Type) {
|
|
|
|
for k, v := range t.Extensions() {
|
2023-09-13 00:46:27 +00:00
|
|
|
_, exists := s.Extensions[k]
|
2023-09-12 18:06:45 +00:00
|
|
|
if !exists {
|
2023-09-13 00:46:27 +00:00
|
|
|
s.Extensions[k] = v
|
2023-09-12 18:06:45 +00:00
|
|
|
}
|
2023-09-11 16:25:39 +00:00
|
|
|
}
|
|
|
|
|
2023-09-13 01:56:39 +00:00
|
|
|
for _, v := range t.MimeTypes() {
|
2023-09-12 18:06:45 +00:00
|
|
|
_, exists := s.Extensions[v]
|
|
|
|
if !exists {
|
|
|
|
s.MimeTypes[v] = t
|
2023-09-11 16:25:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-13 01:56:39 +00:00
|
|
|
func FileType(path string, registeredFormats *Types) (bool, Type, string, error) {
|
2023-09-11 16:25:39 +00:00
|
|
|
file, err := os.Open(path)
|
|
|
|
switch {
|
|
|
|
case errors.Is(err, os.ErrNotExist):
|
|
|
|
return false, nil, "", nil
|
|
|
|
case err != nil:
|
|
|
|
return false, nil, "", err
|
|
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
|
2023-09-11 21:05:38 +00:00
|
|
|
head := make([]byte, 512)
|
2023-09-11 16:25:39 +00:00
|
|
|
file.Read(head)
|
|
|
|
|
2023-09-11 21:05:38 +00:00
|
|
|
mimeType := http.DetectContentType(head)
|
2023-09-11 16:25:39 +00:00
|
|
|
|
2023-09-12 18:06:45 +00:00
|
|
|
// try identifying files by mime types first
|
|
|
|
fileType, exists := registeredFormats.MimeTypes[mimeType]
|
|
|
|
if exists {
|
|
|
|
return fileType.Validate(path), fileType, mimeType, nil
|
|
|
|
}
|
2023-09-11 16:25:39 +00:00
|
|
|
|
2023-09-12 18:06:45 +00:00
|
|
|
// if mime type detection fails, use the file extension
|
2023-09-13 00:46:27 +00:00
|
|
|
mimeType, exists = registeredFormats.Extensions[filepath.Ext(path)]
|
2023-09-12 18:06:45 +00:00
|
|
|
if exists {
|
2023-09-13 00:46:27 +00:00
|
|
|
fileType, exists := registeredFormats.MimeTypes[mimeType]
|
|
|
|
|
|
|
|
if exists {
|
|
|
|
return fileType.Validate(path), fileType, mimeType, nil
|
|
|
|
}
|
2023-09-11 16:25:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil, "", nil
|
|
|
|
}
|
2023-09-13 04:35:17 +00:00
|
|
|
|
|
|
|
func Register(t Type) {
|
|
|
|
SupportedFormats.Add(t)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Types) GetExtensions() string {
|
|
|
|
var output strings.Builder
|
|
|
|
|
|
|
|
extensions := make([]string, len(t.Extensions))
|
|
|
|
|
|
|
|
i := 0
|
|
|
|
|
|
|
|
for k := range t.Extensions {
|
|
|
|
extensions[i] = k
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
|
|
|
slices.Sort(extensions)
|
|
|
|
|
|
|
|
for _, v := range extensions {
|
|
|
|
output.WriteString(v + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
return output.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t Types) GetMimeTypes() string {
|
|
|
|
var output strings.Builder
|
|
|
|
|
|
|
|
mimeTypes := make([]string, len(t.MimeTypes))
|
|
|
|
|
|
|
|
i := 0
|
|
|
|
|
|
|
|
for k := range t.MimeTypes {
|
|
|
|
mimeTypes[i] = k
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
|
|
|
|
slices.Sort(mimeTypes)
|
|
|
|
|
|
|
|
for _, v := range mimeTypes {
|
|
|
|
output.WriteString(v + "\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
return output.String()
|
|
|
|
}
|