repo.go

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
package repo

import (
	"fmt"
	"html/template"
	"net/http"
	"os"
	"path"
	"path/filepath"
	"senary/auth"
	"senary/common"
	"strings"
)

type Repository struct {
	config *common.Config
	repo   string
	ac     *auth.AuthClient
}

func NewRepository(config *common.Config, repo string, ac *auth.AuthClient) *Repository {
	fmt.Printf("serving %v\n", repo)

	return &Repository{config: config, repo: repo, ac: ac}
}

type KeyVal struct {
	Key string
	Val string
}

type StaticDir struct {
	RequestBase
	Table       template.HTML
	Title       string
	Filename    string
	Breadcrumbs []KeyVal
	DirName     string
}

func (repo *Repository) ServeTree(w http.ResponseWriter, r *http.Request) {
	localFile, found := strings.CutPrefix(r.URL.Path, "/repos/"+repo.repo)
	fmt.Printf("serving %v\n", localFile)
	if !found {
		http.Error(w, fmt.Errorf("file not found").Error(), http.StatusBadRequest)
		return
	}

	if info, err := os.Stat(filepath.Join(repo.config.RepoDir, repo.repo, localFile)); err == nil {
		if info.IsDir() {
			if !strings.HasSuffix(localFile, "/") {
				http.Redirect(w, r, r.URL.String()+"/", http.StatusMovedPermanently)
			}
			localFile += "/index.html"
		}
	} else {
		http.Error(w, fmt.Errorf("static file not found").Error(), http.StatusBadRequest)
		return
	}

	data, err := os.ReadFile(filepath.Join(repo.config.RepoDir, repo.repo, localFile))
	if err != nil {
		http.Error(w, fmt.Errorf("repo file not found").Error(), http.StatusBadRequest)
		return
	}

	user := repo.ac.GetAuthInfo(repo.config, r)
	title, _ := strings.CutSuffix(localFile, ".html")
	breadcrumbs := strings.Split(title, "/")
	var breadcrumbsMap []KeyVal
	filename := filepath.Base(title)
	if !strings.HasSuffix(localFile, "/index.html") {
		breadcrumbsMap = make([]KeyVal, len(breadcrumbs)-2)
		soafar := path.Join("/repos", repo.repo)
		for i, bc := range breadcrumbs[1 : len(breadcrumbs)-1] {
			soafar = path.Join(soafar, bc)
			breadcrumbsMap[i].Key = bc
			breadcrumbsMap[i].Val = soafar
		}
	} else {
		breadcrumbs := strings.Split(filepath.Dir(title), "/")
		if len(breadcrumbs) > 2 {
			breadcrumbsMap = make([]KeyVal, len(breadcrumbs)-2)
			soafar := path.Join("/repos", repo.repo)
			for i, bc := range breadcrumbs[1 : len(breadcrumbs)-1] {
				soafar = path.Join(soafar, bc)
				breadcrumbsMap[i].Key = bc
				breadcrumbsMap[i].Val = soafar
			}
		}

		filename = filepath.Base(filepath.Dir(title))
	}

	err = repo.config.Templates.ExecuteTemplate(w, "dir.tpl.html", StaticDir{Table: template.HTML(data), DirName: filepath.Dir(localFile),
		Title:       filename,
		Breadcrumbs: breadcrumbsMap,
		Filename:    filename,
		RequestBase: RequestBase{
			Repo: repo.repo, User: user, ClientID: repo.config.ClientID}})
	if err != nil {
		http.Error(w, fmt.Errorf("file not found").Error(), http.StatusBadRequest)
	}
}