1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-04 18:19:54 +00:00

Move mimetype stuff to a separate module

This commit is contained in:
bouncepaw 2021-01-29 00:07:21 +05:00
parent d25c953409
commit ae1c5db3b3
8 changed files with 131 additions and 128 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
mycorrhiza
hyphae/*.gog

View File

@ -11,6 +11,7 @@ import (
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/markup"
"github.com/bouncepaw/mycorrhiza/mimetype"
"github.com/bouncepaw/mycorrhiza/templates"
"github.com/bouncepaw/mycorrhiza/tree"
"github.com/bouncepaw/mycorrhiza/user"
@ -71,7 +72,7 @@ func handlerBinary(w http.ResponseWriter, rq *http.Request) {
hyphaName := HyphaNameFromRq(rq, "binary")
if data, ok := HyphaStorage[hyphaName]; ok {
log.Println("Serving", data.binaryPath)
w.Header().Set("Content-Type", ExtensionToMime(filepath.Ext(data.binaryPath)))
w.Header().Set("Content-Type", mimetype.FromExtension(filepath.Ext(data.binaryPath)))
http.ServeFile(w, rq, data.binaryPath)
}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/markup"
"github.com/bouncepaw/mycorrhiza/mimetype"
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
)
@ -114,7 +115,7 @@ func UploadBinary(hyphaName, mime string, file multipart.File, u *user.User) *hi
if err != nil {
return hop.WithError(err).Apply()
}
return uploadHelp(hop, hyphaName, MimeToExtension(mime), data, u)
return uploadHelp(hop, hyphaName, mimetype.ToExtension(mime), data, u)
}
// DeleteHypha deletes hypha and makes a history record about that.
@ -254,48 +255,6 @@ func binaryHtmlBlock(hyphaName string, hd *HyphaData) string {
}
}
// Index finds all hypha files in the full `path` and saves them to HyphaStorage. This function is recursive.
func Index(path string) {
nodes, err := ioutil.ReadDir(path)
if err != nil {
log.Fatal(err)
}
for _, node := range nodes {
// If this hypha looks like it can be a hypha path, go deeper. Do not touch the .git and static folders for they have an admnistrative importance!
if node.IsDir() && isCanonicalName(node.Name()) && node.Name() != ".git" && node.Name() != "static" {
Index(filepath.Join(path, node.Name()))
continue
}
var (
hyphaPartPath = filepath.Join(path, node.Name())
hyphaName, isText, skip = DataFromFilename(hyphaPartPath)
hyphaData *HyphaData
)
if !skip {
// Reuse the entry for existing hyphae, create a new one for those that do not exist yet.
if hd, ok := HyphaStorage[hyphaName]; ok {
hyphaData = hd
} else {
hyphaData = &HyphaData{}
HyphaStorage[hyphaName] = hyphaData
hyphae.IncrementCount()
}
if isText {
hyphaData.textPath = hyphaPartPath
} else {
// Notify the user about binary part collisions. It's a design decision to just use any of them, it's the user's fault that they have screwed up the folder structure, but the engine should at least let them know, right?
if hyphaData.binaryPath != "" {
log.Println("There is a file collision for binary part of a hypha:", hyphaData.binaryPath, "and", hyphaPartPath, "-- going on with the latter")
}
hyphaData.binaryPath = hyphaPartPath
}
}
}
}
// FetchTextPart tries to read text file in the `d`. If there is no file, empty string is returned.
func FetchTextPart(d *HyphaData) (string, error) {
if d.textPath == "" {
@ -327,3 +286,45 @@ func setHeaderLinks() {
}
}
}
// Index finds all hypha files in the full `path` and saves them to HyphaStorage. This function is recursive.
func Index(path string) {
nodes, err := ioutil.ReadDir(path)
if err != nil {
log.Fatal(err)
}
for _, node := range nodes {
// If this hypha looks like it can be a hypha path, go deeper. Do not touch the .git and static folders for they have an admnistrative importance!
if node.IsDir() && isCanonicalName(node.Name()) && node.Name() != ".git" && node.Name() != "static" {
Index(filepath.Join(path, node.Name()))
continue
}
var (
hyphaPartPath = filepath.Join(path, node.Name())
hyphaName, isText, skip = mimetype.DataFromFilename(hyphaPartPath)
hyphaData *HyphaData
)
if !skip {
// Reuse the entry for existing hyphae, create a new one for those that do not exist yet.
if hd, ok := HyphaStorage[hyphaName]; ok {
hyphaData = hd
} else {
hyphaData = &HyphaData{}
HyphaStorage[hyphaName] = hyphaData
hyphae.IncrementCount()
}
if isText {
hyphaData.textPath = hyphaPartPath
} else {
// Notify the user about binary part collisions. It's a design decision to just use any of them, it's the user's fault that they have screwed up the folder structure, but the engine should at least let them know, right?
if hyphaData.binaryPath != "" {
log.Println("There is a file collision for binary part of a hypha:", hyphaData.binaryPath, "and", hyphaPartPath, "-- going on with the latter")
}
hyphaData.binaryPath = hyphaPartPath
}
}
}
}

View File

@ -1,21 +0,0 @@
package hyphae
// TODO: do
import ()
type Hypha struct {
Name string
Exists bool
TextPath string
BinaryPath string
OutLinks []string
BackLinks []string
}
// AddHypha adds a hypha named `name` with such `textPath` and `binaryPath`. Both paths can be empty. Does //not// check for hypha's existence beforehand. Count is handled.
func AddHypha(name, textPath, binaryPath string) {
}
// DeleteHypha clears both paths and all out-links from the named hypha and marks it as non-existent. It does not actually delete it from the memdb. Count is handled.
func DeleteHypha(name string) {
}

View File

@ -15,6 +15,7 @@ import (
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/mimetype"
"github.com/bouncepaw/mycorrhiza/templates"
"github.com/bouncepaw/mycorrhiza/user"
"github.com/bouncepaw/mycorrhiza/util"
@ -64,7 +65,7 @@ func handlerList(w http.ResponseWriter, rq *http.Request) {
u = user.FromRequest(rq)
)
for hyphaName, data := range HyphaStorage {
tbody += templates.HyphaListRowHTML(hyphaName, ExtensionToMime(filepath.Ext(data.binaryPath)), data.binaryPath != "")
tbody += templates.HyphaListRowHTML(hyphaName, mimetype.FromExtension(filepath.Ext(data.binaryPath)), data.binaryPath != "")
}
util.HTTP200Page(w, base("List of pages", templates.HyphaListHTML(tbody, pageCount), u))
}

62
mime.go
View File

@ -1,62 +0,0 @@
package main
import (
"path/filepath"
"strings"
)
func MimeToExtension(mime string) string {
mm := map[string]string{
"application/octet-stream": "bin",
"image/jpeg": "jpg",
"image/gif": "gif",
"image/png": "png",
"image/webp": "webp",
"image/svg+xml": "svg",
"image/x-icon": "ico",
"application/ogg": "ogg",
"video/webm": "webm",
"audio/mp3": "mp3",
"video/mp4": "mp4",
}
if ext, ok := mm[mime]; ok {
return "." + ext
}
return ".bin"
}
func ExtensionToMime(ext string) string {
mm := map[string]string{
".bin": "application/octet-stream",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".png": "image/png",
".webp": "image/webp",
".svg": "image/svg+xml",
".ico": "image/x-icon",
".ogg": "application/ogg",
".webm": "video/webm",
".mp3": "audio/mp3",
".mp4": "video/mp4",
}
if mime, ok := mm[ext]; ok {
return mime
}
return "application/octet-stream"
}
// DataFromFilename fetches all meta information from hypha content file with path `fullPath`. If it is not a content file, `skip` is true, and you are expected to ignore this file when indexing hyphae. `name` is name of the hypha to which this file relates. `isText` is true when the content file is text, false when is binary. `mimeId` is an integer representation of content type. Cast it to TextType if `isText == true`, cast it to BinaryType if `isText == false`.
func DataFromFilename(fullPath string) (name string, isText bool, skip bool) {
shortPath := strings.TrimPrefix(fullPath, WikiDir)[1:]
ext := filepath.Ext(shortPath)
name = CanonicalName(strings.TrimSuffix(shortPath, ext))
switch ext {
case ".myco":
isText = true
case "", shortPath:
skip = true
}
return
}

68
mimetype/mime.go Normal file
View File

@ -0,0 +1,68 @@
package mimetype
import (
"path/filepath"
"strings"
"github.com/bouncepaw/mycorrhiza/util"
)
// ToExtension returns dotted extension for given mime-type.
func ToExtension(mime string) string {
if ext, ok := mapMime2Ext[mime]; ok {
return "." + ext
}
return ".bin"
}
// FromExtension returns mime-type for given extension. The extension must start with a dot.
func FromExtension(ext string) string {
if mime, ok := mapExt2Mime[ext]; ok {
return mime
}
return "application/octet-stream"
}
// DataFromFilename fetches all meta information from hypha content file with path `fullPath`. If it is not a content file, `skip` is true, and you are expected to ignore this file when indexing hyphae. `name` is name of the hypha to which this file relates. `isText` is true when the content file is text, false when is binary.
func DataFromFilename(fullPath string) (name string, isText bool, skip bool) {
shortPath := util.ShorterPath(fullPath)
ext := filepath.Ext(shortPath)
name = util.CanonicalName(strings.TrimSuffix(shortPath, ext))
switch ext {
case ".myco":
isText = true
case "", shortPath:
skip = true
}
return
}
var mapMime2Ext = map[string]string{
"application/octet-stream": "bin",
"image/jpeg": "jpg",
"image/gif": "gif",
"image/png": "png",
"image/webp": "webp",
"image/svg+xml": "svg",
"image/x-icon": "ico",
"application/ogg": "ogg",
"video/webm": "webm",
"audio/mp3": "mp3",
"video/mp4": "mp4",
}
var mapExt2Mime = map[string]string{
".bin": "application/octet-stream",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".png": "image/png",
".webp": "image/webp",
".svg": "image/svg+xml",
".ico": "image/x-icon",
".ogg": "application/ogg",
".webm": "video/webm",
".mp3": "audio/mp3",
".mp4": "video/mp4",
}

View File

@ -4,6 +4,7 @@ import (
"crypto/rand"
"encoding/hex"
"net/http"
"regexp"
"strings"
)
@ -65,3 +66,16 @@ func BeautifulName(uglyName string) string {
}
return strings.Title(strings.ReplaceAll(uglyName, "_", " "))
}
// CanonicalName makes sure the `name` is canonical. A name is canonical if it is lowercase and all spaces are replaced with underscores.
func CanonicalName(name string) string {
return strings.ToLower(strings.ReplaceAll(name, " ", "_"))
}
// HyphaPattern is a pattern which all hyphae must match.
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%{}]+`)
// IsCanonicalName checks if the `name` is canonical.
func IsCanonicalName(name string) bool {
return HyphaPattern.MatchString(name)
}