gateway_indexPage.go 3.01 KB
Newer Older
Henry's avatar
Henry committed
1 2 3 4
package corehttp

import (
	"html/template"
5
	"net/url"
Henry's avatar
Henry committed
6
	"path"
7
	"strings"
rht's avatar
rht committed
8

tavit ohanian's avatar
tavit ohanian committed
9 10
	"gitlab.dms3.io/dms3/go-dms3/assets"
	dms3path "gitlab.dms3.io/dms3/go-path"
Henry's avatar
Henry committed
11 12 13 14
)

// structs for directory listing
type listingTemplateData struct {
15
	GatewayURL  string
16
	DNSLink     bool
17 18 19 20 21 22
	Listing     []directoryItem
	Size        string
	Path        string
	Breadcrumbs []breadcrumb
	BackLink    string
	Hash        string
Henry's avatar
Henry committed
23 24 25
}

type directoryItem struct {
26 27 28 29 30 31 32 33
	Size      string
	Name      string
	Path      string
	Hash      string
	ShortHash string
}

type breadcrumb struct {
Henry's avatar
Henry committed
34 35 36 37
	Name string
	Path string
}

38
func breadcrumbs(urlPath string, dnslinkOrigin bool) []breadcrumb {
39 40
	var ret []breadcrumb

tavit ohanian's avatar
tavit ohanian committed
41
	p, err := dms3path.ParsePath(urlPath)
42 43 44 45 46
	if err != nil {
		// No breadcrumbs, fallback to bare Path in template
		return ret
	}
	segs := p.Segments()
47
	contentRoot := segs[1]
48 49 50 51 52 53 54 55 56 57 58
	for i, seg := range segs {
		if i == 0 {
			ret = append(ret, breadcrumb{Name: seg})
		} else {
			ret = append(ret, breadcrumb{
				Name: seg,
				Path: "/" + strings.Join(segs[0:i+1], "/"),
			})
		}
	}

tavit ohanian's avatar
tavit ohanian committed
59
	// Drop the /dms3ns/<fqdn> prefix from breadcrumb Paths when directory
60 61 62 63
	// listing on a DNSLink website (loaded due to Host header in HTTP
	// request).  Necessary because the hostname most likely won't have a
	// public gateway mounted.
	if dnslinkOrigin {
tavit ohanian's avatar
tavit ohanian committed
64
		prefix := "/dms3ns/" + contentRoot
65 66 67 68 69 70 71 72 73
		for i, crumb := range ret {
			if strings.HasPrefix(crumb.Path, prefix) {
				ret[i].Path = strings.Replace(crumb.Path, prefix, "", 1)
			}
		}
		// Make contentRoot breadcrumb link to the website root
		ret[1].Path = "/"
	}

74 75 76 77 78 79 80
	return ret
}

func shortHash(hash string) string {
	return (hash[0:4] + "\u2026" + hash[len(hash)-4:])
}

81
// helper to detect DNSLink website context
tavit ohanian's avatar
tavit ohanian committed
82
// (when hostname from gwURL is matching /dms3ns/<fqdn> in path)
83 84
func hasDNSLinkOrigin(gwURL string, path string) bool {
	if gwURL != "" {
85
		fqdn := stripPort(strings.TrimPrefix(gwURL, "//"))
tavit ohanian's avatar
tavit ohanian committed
86
		return strings.HasPrefix(path, "/dms3ns/"+fqdn)
87 88 89 90
	}
	return false
}

91
var listingTemplate *template.Template
Henry's avatar
Henry committed
92

93
func init() {
94
	knownIconsBytes, err := assets.Asset("dir-index-html/knownIcons.txt")
95 96 97 98 99 100 101 102 103 104 105 106 107 108
	if err != nil {
		panic(err)
	}
	knownIcons := make(map[string]struct{})
	for _, ext := range strings.Split(strings.TrimSuffix(string(knownIconsBytes), "\n"), "\n") {
		knownIcons[ext] = struct{}{}
	}

	// helper to guess the type/icon for it by the extension name
	iconFromExt := func(name string) string {
		ext := path.Ext(name)
		_, ok := knownIcons[ext]
		if !ok {
			// default blank icon
tavit ohanian's avatar
tavit ohanian committed
109
			return "dms3-_blank"
110
		}
tavit ohanian's avatar
tavit ohanian committed
111
		return "dms3-" + ext[1:] // slice of the first dot
112 113
	}

114 115 116 117 118 119
	// custom template-escaping function to escape a full path, including '#' and '?'
	urlEscape := func(rawUrl string) string {
		pathUrl := url.URL{Path: rawUrl}
		return pathUrl.String()
	}

120
	// Directory listing template
121
	dirIndexBytes, err := assets.Asset("dir-index-html/dir-index.html")
122 123
	if err != nil {
		panic(err)
Henry's avatar
Henry committed
124 125
	}

126 127
	listingTemplate = template.Must(template.New("dir").Funcs(template.FuncMap{
		"iconFromExt": iconFromExt,
128
		"urlEscape":   urlEscape,
129
	}).Parse(string(dirIndexBytes)))
Henry's avatar
Henry committed
130
}