all repos — nirvash @ 59954b94d806d3e343b0fa6a17c70066b9d8fcda

modular CMS using the quartzgun library

fix style and implement basic static file tree browsing
Iris Lightshard nilix@nilfm.cc
PGP Signature
-----BEGIN PGP SIGNATURE-----

iQIzBAABCAAdFiEEkFh6dA+k/6CXFXU4O3+8IhROY5gFAmKi5uUACgkQO3+8IhRO
Y5jyNw/9F9IHZky8Ky3zfAffhY0Bq+y9Tt3zq+ox7ckYFetHwalyK2PV/w5074JG
FSfso8pIwFH/tWY2zxcatXN4T9qWcaPukkcUTvthbfH4o1XE+HRj/lQ6PnxiWAId
UUMLQ3I2Wp1hR78cwu9AzzS2EXlOpvEs5alDPXMshRKxgPIigYa4E8kLwE9BhGUT
jzCQwIY2tNm8rg3/grNZVm3F41O5T/EkP7pzTuBJj0Uu453klbcVoLlOdP1TOJpA
LCX/hqo2PtPhh2LAJfKJDpXijGCn5Oos2z1o+gDWXH1XJdyup4A5Z7lV2NME3FS+
cUIBFUkVT2fJXHqq1XQiDw2w1w70feZU3Q9Ms8PdGqjNp7eoFD63avBy9zIHMXmY
BpgimGUMMYS7z+dVgwzkk8k4ZsFEncwMA29CQ29G/gWaWWTHVExlz3YtIqyEWBbT
auRgolaThTiLjpZV/9gxP0QLr6SNkBYSirwFw58Dku3l8idwiApghsIH7zmJ3sxn
+NEnz89zGuq3LZbDG+hDvYue6VDlfpOgEhsp+2gVoq17hehyj3byfChiDV6d7tXw
08P+6YNI8qRj1kBAfNjeFGbipZZg/lpX31qcEPVQqopS5Gm/ouS5i8VTSGfFLOzS
nSw9YsIj19shaGAgCRQP4wtxbvHglPuzzXDexxY5sGxad5Ls2Ys=
=UIgG
-----END PGP SIGNATURE-----
commit

59954b94d806d3e343b0fa6a17c70066b9d8fcda

parent

034d325ae36cd0f3978721ef7c0370809e2a918f

M archetype/config.goarchetype/config.go

@@ -9,11 +9,13 @@ "strings"

) type Config struct { - Adapter Adapter // adapter for this instance - Root string // root of the site data - StaticRoot string // root of static files for StaticFileManager - AssetRoot string // root of Nirvash dist files (CSS, images) - Plugins map[string]interface{} + Adapter Adapter // adapter for this instance + Root string // root of the site data + StaticRoot string // root of static files for StaticFileManager + StaticShowHidden bool // whether to show hidden files in the StaticFileManager + StaticShowHtml bool // whether to show html files in the StaticFileManager + AssetRoot string // root of Nirvash dist files (CSS, images) + Plugins map[string]interface{} } func GetConfigLocation() string {
M archetype/eureka.goarchetype/eureka.go

@@ -25,7 +25,7 @@ }

self.Root = cfg.Root self.Config = make(map[ConfigOption]string) - // TODO: read config.h and build self.Config + err = self.readCfg() if err != nil { panic("config.h is malformed!")
A archetype/fileManager.go

@@ -0,0 +1,88 @@

+package archetype + +import ( + "io/ioutil" + "path/filepath" + "strings" +) + +type SimpleFileManager struct { + Root string + ShowHtml bool + ShowHidden bool +} + +type FileListing struct { + Error string + Root string + Up string + SubDirs []string + Files []string +} + +type FileManager interface { + Init(cfg *Config) error + // ListTree() FileListing + ListSubTree(root string) FileListing + // AddFile(path string, file multipart.FileHeader) error + // MkDir(path string) error + // Remove(path string) error + // Rename(old, new string) error +} + +func (self *SimpleFileManager) Init(cfg *Config) error { + self.Root = cfg.StaticRoot + self.ShowHtml = cfg.StaticShowHtml + self.ShowHidden = cfg.StaticShowHidden + return nil +} + +func (self *SimpleFileManager) ListSubTree(root string) FileListing { + list := FileListing{} + + if strings.Contains(root, "../") || strings.Contains(root, "..\\") { + list.Error = "You cannot escape!" + return list + } + + fullPath := filepath.Join(self.Root, root) + + files, err := ioutil.ReadDir(fullPath) + + if err != nil { + list.Error = err.Error() + return list + } + + list.Root = root + if !strings.HasSuffix(list.Root, "/") { + list.Root += "/" + } + if !strings.HasPrefix(list.Root, "/") { + list.Root = "/" + list.Root + } + + levels := strings.Split(root, "/") + if list.Root != "/" { + list.Up = "/" + } + if len(levels) >= 2 { + list.Up = "/" + strings.Join(levels[:len(levels)-1], "/") + } + + for _, file := range files { + if !self.ShowHidden && strings.HasPrefix(file.Name(), ".") { + continue + } + if file.IsDir() { + list.SubDirs = append(list.SubDirs, file.Name()) + } else { + if !self.ShowHtml && strings.HasSuffix(file.Name(), ".html") { + continue + } + list.Files = append(list.Files, file.Name()) + } + } + + return list +}
D archetype/staticFileManager.go

@@ -1,16 +0,0 @@

-package archetype - -type StaticFileManager struct { - Root string - ShowHtml bool - ShowHidden bool -} - -type FileManager interface { - Init(cfg Config) error - ListTree() []string - ListSubTree(root string) []string - AddFile(path string, file interface{}) error - MkDir(path string) error - Remove(path string) error -}
M lfo/middleware.golfo/middleware.go

@@ -16,6 +16,15 @@

return http.HandlerFunc(handlerFunc) } +func WithFileManager(next http.Handler, fileManager core.FileManager) http.Handler { + handlerFunc := func(w http.ResponseWriter, req *http.Request) { + *req = *req.WithContext(context.WithValue(req.Context(), "file-manager", fileManager)) + next.ServeHTTP(w, req) + } + + return http.HandlerFunc(handlerFunc) +} + func EnsurePageData(next http.Handler, adapter core.Adapter) http.Handler { handlerFunc := func(w http.ResponseWriter, req *http.Request) { pageTitle := req.FormValue("title")
M nirvash.gonirvash.go

@@ -27,11 +27,15 @@ }

cfg.Adapter.Init(cfg) + fileManager := &core.SimpleFileManager{} + fileManager.Init(cfg) + pathConcat := filepath.Join rtr := &router.Router{ StaticPaths: map[string]string{ - "/static": filepath.Join(cfg.AssetRoot, "static"), + "/static/": filepath.Join(cfg.AssetRoot, "static"), + "/files/": cfg.StaticRoot, }, }

@@ -200,6 +204,20 @@ udb,

"/login"), udb, "/")) + + rtr.Get( + `/static-mgr/(?P<Slug>.*)`, + Fortify( + Protected( + WithFileManager( + renderer.Template( + pathConcat(templateRoot, "file_list.html"), + pathConcat(templateRoot, "header.html"), + pathConcat(templateRoot, "footer.html")), + fileManager), + http.MethodGet, + udb, + "/login"))) http.ListenAndServe(":8080", rtr) }
A static/delete.svg

@@ -0,0 +1,23 @@

+<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.0" + width="100" + height="100" + id="svg8978"> + <defs + id="defs8980" /> + <g + id="layer1"> + <path + d="M 6.3895625,6.4195626 C 93.580437,93.610437 93.580437,93.610437 93.580437,93.610437" + style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:18.05195999;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path8986" /> + <path + d="M 6.3894001,93.6106 C 93.830213,6.4194003 93.830213,6.4194003 93.830213,6.4194003" + style="fill:none;fill-rule:evenodd;stroke:#ff0000;stroke-width:17.80202103;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path8988" /> + </g> +</svg>
A static/move.svg

@@ -0,0 +1,6 @@

+<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500"> +<path stroke="#000" stroke-width="55" fill="none" +stroke-linecap="round" stroke-linejoin="round" +d="m249,30a220,220 0 1,0 2,0zm-10,75 140,145-140,145M110,250H350"/> +</svg>
M static/style.cssstatic/style.css

@@ -291,4 +291,9 @@ }

form input[readonly] { border: none; +} + +.edit-error { + display: block; + border-bottom: solid 2px crimson; }
A templates/file_list.html

@@ -0,0 +1,34 @@

+{{ $slug := ((.Context).Value "params").Slug }} +{{ $fileList := ((.Context).Value "file-manager").ListSubTree $slug }} + +{{ template "header" .}} + + +{{ if ($fileList).Error }} +<h2>File Listing Error</h2> + +<span class="adapter-error">{{($fileList).Error}}</span> +{{ else }} +<h2>Files: {{($fileList).Root}}</h2> + +<div class="new-page-button-wrapper"> + <a class="new-page-button" href="/upload{{($fileList).Root}}">Upload File</a> +</div> + +<div class="page-list"> + <ul> + {{ if ($fileList).Up }} + <li><a href="/static-mgr{{$fileList.Up}}">..</a></li> + {{ end }} + {{ range $dir := ($fileList).SubDirs }} + <li><a href="/static-mgr{{($fileList).Root}}{{$dir}}">{{$dir}}/</a></li> + {{ end }} + {{ range $file := ($fileList).Files }} + <li><a href="/files{{($fileList).Root}}{{$file}}">{{$file}}</a></li> + {{ end }} + </ul> +</div> + +{{ end }} + +{{ template "footer" .}}
M templates/header.htmltemplates/header.html

@@ -13,7 +13,7 @@ <header><h1>Nirvash CMS</h1></header>

<nav> <ul> <li><a href="/">Pages</a></li> - <li><a href="/static-mgr">Static Files</a></li> + <li><a href="/static-mgr/">Static Files</a></li> <li><a href="/build">Build</a></li> <li><a href="/config">Configuration</a></li> <li><a href="/logout">Logout</a></li>