solve some back end bugs
parent
193adea6bb
commit
2819ab24b8
|
@ -75,22 +75,6 @@ buttons.setDone = function (name, success = true) {
|
|||
* EVENTS *
|
||||
* *
|
||||
* * * * * * * * * * * * * * * */
|
||||
function closePrompt (event) {
|
||||
let prompt = document.querySelector('.prompt')
|
||||
|
||||
if (!prompt) return
|
||||
|
||||
if (typeof event !== 'undefined') {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
document.querySelector('.overlay').classList.remove('active')
|
||||
prompt.classList.remove('active')
|
||||
|
||||
setTimeout(() => {
|
||||
prompt.remove()
|
||||
}, 100)
|
||||
}
|
||||
|
||||
function notImplemented (event) {
|
||||
event.preventDefault()
|
||||
|
@ -194,26 +178,7 @@ function deleteEvent (event) {
|
|||
* * * * * * * * * * * * * * * */
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function (event) {
|
||||
overlay = document.querySelector('.overlay')
|
||||
clickOverlay = document.querySelector('#click-overlay')
|
||||
|
||||
buttons.logout = document.getElementById('logout')
|
||||
buttons.delete = document.getElementById('delete')
|
||||
buttons.previous = document.getElementById('previous')
|
||||
buttons.info = document.getElementById('info')
|
||||
|
||||
// Attach event listeners
|
||||
buttons.logout.addEventListener('click', logoutEvent)
|
||||
buttons.info.addEventListener('click', infoEvent)
|
||||
|
||||
templates.question = document.querySelector('#question-template')
|
||||
templates.info = document.querySelector('#info-template')
|
||||
templates.message = document.querySelector('#message-template')
|
||||
templates.move = document.querySelector('#move-template')
|
||||
|
||||
if (data.user.AllowEdit) {
|
||||
buttons.delete.addEventListener('click', deleteEvent)
|
||||
}
|
||||
|
||||
let dropdownButtons = document.querySelectorAll('.action[data-dropdown]')
|
||||
Array.from(dropdownButtons).forEach(button => {
|
||||
|
@ -228,15 +193,6 @@ document.addEventListener('DOMContentLoaded', function (event) {
|
|||
})
|
||||
})
|
||||
|
||||
overlay.addEventListener('click', event => {
|
||||
if (document.querySelector('.help.active')) {
|
||||
closeHelp(event)
|
||||
return
|
||||
}
|
||||
|
||||
closePrompt(event)
|
||||
})
|
||||
|
||||
let mainActions = document.getElementById('main-actions')
|
||||
|
||||
document.getElementById('more').addEventListener('click', event => {
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<info-prompt v-show="showInfo" :class="{ active: showInfo }"></info-prompt>
|
||||
<help v-show="showHelp" :class="{ active: showHelp }"></help>
|
||||
|
||||
<div v-show="showOverlay()" class="overlay" :class="{ active: showOverlay() }"></div>
|
||||
<div v-show="showOverlay()" @click="resetPrompts" class="overlay" :class="{ active: showOverlay() }"></div>
|
||||
|
||||
<footer>Served with <a rel="noopener noreferrer" href="https://github.com/hacdias/caddy-filemanager">File Manager</a>.</footer>
|
||||
</div>
|
||||
|
@ -78,14 +78,18 @@ function updateColumnSizes () {
|
|||
items.style.width = `calc(${100 / columns}% - 1em)`
|
||||
}
|
||||
|
||||
function resetPrompts () {
|
||||
window.info.showHelp = false
|
||||
window.info.showInfo = false
|
||||
window.info.showDelete = false
|
||||
window.info.showRename = false
|
||||
window.info.showMove = false
|
||||
}
|
||||
|
||||
window.addEventListener('keydown', (event) => {
|
||||
// Esc!
|
||||
if (event.keyCode === 27) {
|
||||
window.info.showHelp = false
|
||||
window.info.showInfo = false
|
||||
window.info.showDelete = false
|
||||
window.info.showRename = false
|
||||
window.info.showMove = false
|
||||
resetPrompts()
|
||||
|
||||
// Unselect all files and folders.
|
||||
if (window.info.req.kind === 'listing') {
|
||||
|
@ -166,7 +170,8 @@ export default {
|
|||
showUpload: function () {
|
||||
if (this.req.kind === 'editor') return false
|
||||
return this.user.allowNew
|
||||
}
|
||||
},
|
||||
resetPrompts: resetPrompts
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
121
editor.go
121
editor.go
|
@ -1,121 +0,0 @@
|
|||
package filemanager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/hacdias/filemanager/frontmatter"
|
||||
"github.com/spf13/hugo/parser"
|
||||
)
|
||||
|
||||
// editor contains the information to fill the editor template.
|
||||
type editor struct {
|
||||
*fileInfo
|
||||
Class string `json:"class"`
|
||||
Mode string `json:"mode"`
|
||||
Visual bool `json:"visual"`
|
||||
Content string `json:"content"`
|
||||
FrontMatter struct {
|
||||
Content *frontmatter.Content
|
||||
Rune rune
|
||||
} `json:"frontmatter"`
|
||||
}
|
||||
|
||||
// getEditor gets the editor based on a Info struct
|
||||
func getEditor(r *http.Request, i *fileInfo) (*editor, error) {
|
||||
var err error
|
||||
|
||||
// Create a new editor variable and set the mode
|
||||
e := &editor{fileInfo: i}
|
||||
e.Mode = editorMode(i.Name)
|
||||
e.Class = editorClass(e.Mode)
|
||||
|
||||
if e.Class == "frontmatter-only" || e.Class == "complete" {
|
||||
e.Visual = true
|
||||
}
|
||||
|
||||
if r.URL.Query().Get("visual") == "false" {
|
||||
e.Class = "content-only"
|
||||
}
|
||||
|
||||
hasRune := frontmatter.HasRune(i.content)
|
||||
|
||||
if e.Class == "frontmatter-only" && !hasRune {
|
||||
e.FrontMatter.Rune, err = frontmatter.StringFormatToRune(e.Mode)
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
i.content = frontmatter.AppendRune(i.content, e.FrontMatter.Rune)
|
||||
hasRune = true
|
||||
}
|
||||
|
||||
if e.Class == "frontmatter-only" && hasRune {
|
||||
e.FrontMatter.Content, _, err = frontmatter.Pretty(i.content)
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
}
|
||||
|
||||
if e.Class == "complete" && hasRune {
|
||||
var page parser.Page
|
||||
// Starts a new buffer and parses the file using Hugo's functions
|
||||
buffer := bytes.NewBuffer(i.content)
|
||||
page, err = parser.ReadFrom(buffer)
|
||||
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
|
||||
// Parses the page content and the frontmatter
|
||||
e.Content = strings.TrimSpace(string(page.Content()))
|
||||
e.FrontMatter.Rune = rune(i.content[0])
|
||||
e.FrontMatter.Content, _, err = frontmatter.Pretty(page.FrontMatter())
|
||||
}
|
||||
|
||||
if e.Class == "complete" && !hasRune {
|
||||
err = errors.New("Complete but without rune")
|
||||
}
|
||||
|
||||
Error:
|
||||
if e.Class == "content-only" || err != nil {
|
||||
e.Class = "content-only"
|
||||
e.Content = i.StringifyContent()
|
||||
}
|
||||
|
||||
return e, nil
|
||||
}
|
||||
|
||||
func editorClass(mode string) string {
|
||||
switch mode {
|
||||
case "json", "toml", "yaml":
|
||||
return "frontmatter-only"
|
||||
case "markdown", "asciidoc", "rst":
|
||||
return "complete"
|
||||
}
|
||||
|
||||
return "content-only"
|
||||
}
|
||||
|
||||
func editorMode(filename string) string {
|
||||
mode := strings.TrimPrefix(filepath.Ext(filename), ".")
|
||||
|
||||
switch mode {
|
||||
case "md", "markdown", "mdown", "mmark":
|
||||
mode = "markdown"
|
||||
case "asciidoc", "adoc", "ad":
|
||||
mode = "asciidoc"
|
||||
case "rst":
|
||||
mode = "rst"
|
||||
case "html", "htm":
|
||||
mode = "html"
|
||||
case "js":
|
||||
mode = "javascript"
|
||||
case "go":
|
||||
mode = "golang"
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
219
file.go
219
file.go
|
@ -1,6 +1,7 @@
|
|||
package filemanager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/md5"
|
||||
"crypto/sha1"
|
||||
|
@ -19,16 +20,17 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hacdias/filemanager/frontmatter"
|
||||
"github.com/spf13/hugo/parser"
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidOption = errors.New("Invalid option")
|
||||
)
|
||||
|
||||
// fileInfo contains the information about a particular file or directory.
|
||||
type fileInfo struct {
|
||||
// Used to store the file's content temporarily.
|
||||
content []byte
|
||||
// file contains the information about a particular file or directory.
|
||||
type file struct {
|
||||
// The name of the file.
|
||||
Name string `json:"name"`
|
||||
// The Size of the file.
|
||||
|
@ -50,14 +52,17 @@ type fileInfo struct {
|
|||
// Indicates the file content type: video, text, image, music or blob.
|
||||
Type string `json:"type"`
|
||||
// Stores the content of a text file.
|
||||
Content string `json:"content"`
|
||||
Content string `json:"content,omitempty"`
|
||||
|
||||
Editor *editor `json:"editor,omitempty"`
|
||||
|
||||
*listing `json:",omitempty"`
|
||||
}
|
||||
|
||||
// A listing is the context used to fill out a template.
|
||||
type listing struct {
|
||||
*fileInfo
|
||||
// The items (files and folders) in the path.
|
||||
Items []fileInfo `json:"items"`
|
||||
Items []file `json:"items"`
|
||||
// The number of directories in the listing.
|
||||
NumDirs int `json:"numDirs"`
|
||||
// The number of files (items that aren't directories) in the listing.
|
||||
|
@ -66,17 +71,30 @@ type listing struct {
|
|||
Sort string `json:"sort"`
|
||||
// And which order.
|
||||
Order string `json:"order"`
|
||||
// If ≠0 then Items have been limited to that many elements.
|
||||
ItemsLimitedTo int `json:"ItemsLimitedTo"`
|
||||
Display string `json:"display"`
|
||||
// Displays in mosaic or list.
|
||||
Display string `json:"display"`
|
||||
}
|
||||
|
||||
// editor contains the information to fill the editor template.
|
||||
type editor struct {
|
||||
// Indicates if the content has only frontmatter, only content, or both.
|
||||
Mode string `json:"type"`
|
||||
// File content language.
|
||||
Language string `json:"language"`
|
||||
// This indicates if the editor should be visual or not.
|
||||
Visual bool `json:"visual"`
|
||||
FrontMatter struct {
|
||||
Content *frontmatter.Content `json:"content"`
|
||||
Rune rune `json:"rune"`
|
||||
} `json:"frontmatter"`
|
||||
}
|
||||
|
||||
// getInfo gets the file information and, in case of error, returns the
|
||||
// respective HTTP error code
|
||||
func getInfo(url *url.URL, c *FileManager, u *User) (*fileInfo, error) {
|
||||
func getInfo(url *url.URL, c *FileManager, u *User) (*file, error) {
|
||||
var err error
|
||||
|
||||
i := &fileInfo{URL: c.RootURL() + url.Path}
|
||||
i := &file{URL: c.RootURL() + url.Path}
|
||||
i.VirtualPath = url.Path
|
||||
i.VirtualPath = strings.TrimPrefix(i.VirtualPath, "/")
|
||||
i.VirtualPath = "/" + i.VirtualPath
|
||||
|
@ -99,29 +117,31 @@ func getInfo(url *url.URL, c *FileManager, u *User) (*fileInfo, error) {
|
|||
}
|
||||
|
||||
// getListing gets the information about a specific directory and its files.
|
||||
func getListing(u *User, filePath string, baseURL string, i *fileInfo) (*listing, error) {
|
||||
func (i *file) getListing(c *requestContext, r *http.Request) error {
|
||||
baseURL := c.fm.RootURL() + r.URL.Path
|
||||
|
||||
// Gets the directory information using the Virtual File System of
|
||||
// the user configuration.
|
||||
file, err := u.fileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0)
|
||||
f, err := c.us.fileSystem.OpenFile(context.TODO(), c.fi.VirtualPath, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
defer f.Close()
|
||||
|
||||
// Reads the directory and gets the information about the files.
|
||||
files, err := file.Readdir(-1)
|
||||
files, err := f.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
var (
|
||||
fileinfos []fileInfo
|
||||
fileinfos []file
|
||||
dirCount, fileCount int
|
||||
)
|
||||
|
||||
for _, f := range files {
|
||||
name := f.Name()
|
||||
allowed := u.Allowed("/" + name)
|
||||
allowed := c.us.Allowed("/" + name)
|
||||
|
||||
if !allowed {
|
||||
continue
|
||||
|
@ -137,7 +157,7 @@ func getListing(u *User, filePath string, baseURL string, i *fileInfo) (*listing
|
|||
// Absolute URL
|
||||
url := url.URL{Path: baseURL + name}
|
||||
|
||||
i := fileInfo{
|
||||
i := file{
|
||||
Name: f.Name(),
|
||||
Size: f.Size(),
|
||||
ModTime: f.ModTime(),
|
||||
|
@ -150,29 +170,101 @@ func getListing(u *User, filePath string, baseURL string, i *fileInfo) (*listing
|
|||
fileinfos = append(fileinfos, i)
|
||||
}
|
||||
|
||||
return &listing{
|
||||
fileInfo: i,
|
||||
i.listing = &listing{
|
||||
Items: fileinfos,
|
||||
NumDirs: dirCount,
|
||||
NumFiles: fileCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getEditor gets the editor based on a Info struct
|
||||
func (i *file) getEditor(r *http.Request) error {
|
||||
var err error
|
||||
|
||||
// Create a new editor variable and set the mode
|
||||
e := &editor{
|
||||
Language: editorLanguage(i.Extension),
|
||||
}
|
||||
|
||||
e.Mode = editorMode(e.Language)
|
||||
|
||||
if e.Mode == "frontmatter-only" || e.Mode == "complete" {
|
||||
e.Visual = true
|
||||
}
|
||||
|
||||
if r.URL.Query().Get("visual") == "false" {
|
||||
e.Mode = "content-only"
|
||||
}
|
||||
|
||||
hasRune := frontmatter.HasRune(i.Content)
|
||||
|
||||
if e.Mode == "frontmatter-only" && !hasRune {
|
||||
e.FrontMatter.Rune, err = frontmatter.StringFormatToRune(e.Mode)
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
i.Content = frontmatter.AppendRune(i.Content, e.FrontMatter.Rune)
|
||||
hasRune = true
|
||||
}
|
||||
|
||||
if e.Mode == "frontmatter-only" && hasRune {
|
||||
e.FrontMatter.Content, _, err = frontmatter.Pretty([]byte(i.Content))
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
}
|
||||
|
||||
if e.Mode == "complete" && hasRune {
|
||||
var page parser.Page
|
||||
content := []byte(i.Content)
|
||||
// Starts a new buffer and parses the file using Hugo's functions
|
||||
|
||||
buffer := bytes.NewBuffer(content)
|
||||
page, err = parser.ReadFrom(buffer)
|
||||
|
||||
if err != nil {
|
||||
goto Error
|
||||
}
|
||||
|
||||
// Parses the page content and the frontmatter
|
||||
i.Content = strings.TrimSpace(string(page.Content()))
|
||||
e.FrontMatter.Rune = rune(content[0])
|
||||
e.FrontMatter.Content, _, err = frontmatter.Pretty(page.FrontMatter())
|
||||
}
|
||||
|
||||
if e.Mode == "complete" && !hasRune {
|
||||
err = errors.New("Complete but without rune")
|
||||
}
|
||||
|
||||
Error:
|
||||
if e.Mode == "content-only" || err != nil {
|
||||
e.Mode = "content-only"
|
||||
}
|
||||
|
||||
i.Editor = e
|
||||
return nil
|
||||
}
|
||||
|
||||
// RetrieveFileType obtains the mimetype and converts it to a simple
|
||||
// type nomenclature.
|
||||
func (i *fileInfo) RetrieveFileType() error {
|
||||
func (i *file) RetrieveFileType() error {
|
||||
var content []byte
|
||||
var err error
|
||||
|
||||
// Tries to get the file mimetype using its extension.
|
||||
mimetype := mime.TypeByExtension(i.Extension)
|
||||
|
||||
if mimetype == "" {
|
||||
err := i.Read()
|
||||
content, err = ioutil.ReadFile(i.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Tries to get the file mimetype using its first
|
||||
// 512 bytes.
|
||||
mimetype = http.DetectContentType(i.content)
|
||||
mimetype = http.DetectContentType(content)
|
||||
}
|
||||
|
||||
if strings.HasPrefix(mimetype, "video") {
|
||||
|
@ -192,12 +284,12 @@ func (i *fileInfo) RetrieveFileType() error {
|
|||
|
||||
if strings.HasPrefix(mimetype, "text") {
|
||||
i.Type = "text"
|
||||
return nil
|
||||
goto End
|
||||
}
|
||||
|
||||
if strings.HasPrefix(mimetype, "application/javascript") {
|
||||
i.Type = "text"
|
||||
return nil
|
||||
goto End
|
||||
}
|
||||
|
||||
// If the type isn't text (and is blob for example), it will check some
|
||||
|
@ -210,24 +302,24 @@ func (i *fileInfo) RetrieveFileType() error {
|
|||
}
|
||||
|
||||
i.Type = "blob"
|
||||
|
||||
End:
|
||||
// If the file type is text, save its content.
|
||||
if i.Type == "text" {
|
||||
if len(content) == 0 {
|
||||
content, err = ioutil.ReadFile(i.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
i.Content = string(content)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Reads the file.
|
||||
func (i *fileInfo) Read() error {
|
||||
if len(i.content) != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
i.content, err = ioutil.ReadFile(i.Path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i fileInfo) Checksum(kind string) (string, error) {
|
||||
func (i file) Checksum(kind string) (string, error) {
|
||||
file, err := os.Open(i.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -258,13 +350,8 @@ func (i fileInfo) Checksum(kind string) (string, error) {
|
|||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
|
||||
// StringifyContent returns a string with the file content.
|
||||
func (i fileInfo) StringifyContent() string {
|
||||
return string(i.content)
|
||||
}
|
||||
|
||||
// CanBeEdited checks if the extension of a file is supported by the editor
|
||||
func (i fileInfo) CanBeEdited() bool {
|
||||
func (i file) CanBeEdited() bool {
|
||||
return i.Type == "text"
|
||||
}
|
||||
|
||||
|
@ -373,3 +460,35 @@ var textExtensions = [...]string{
|
|||
".c", ".cc", ".h", ".hh", ".cpp", ".hpp", ".f90",
|
||||
".f", ".bas", ".d", ".ada", ".nim", ".cr", ".java", ".cs", ".vala", ".vapi",
|
||||
}
|
||||
|
||||
func editorMode(language string) string {
|
||||
switch language {
|
||||
case "json", "toml", "yaml":
|
||||
return "frontmatter-only"
|
||||
case "markdown", "asciidoc", "rst":
|
||||
return "complete"
|
||||
}
|
||||
|
||||
return "content-only"
|
||||
}
|
||||
|
||||
func editorLanguage(mode string) string {
|
||||
mode = strings.TrimPrefix(".", mode)
|
||||
|
||||
switch mode {
|
||||
case "md", "markdown", "mdown", "mmark":
|
||||
mode = "markdown"
|
||||
case "asciidoc", "adoc", "ad":
|
||||
mode = "asciidoc"
|
||||
case "rst":
|
||||
mode = "rst"
|
||||
case "html", "htm":
|
||||
mode = "html"
|
||||
case "js":
|
||||
mode = "javascript"
|
||||
case "go":
|
||||
mode = "golang"
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ type Block struct {
|
|||
Type string
|
||||
HTMLType string
|
||||
Content *Content
|
||||
Parent *Block
|
||||
Parent *Block `json:"-"`
|
||||
}
|
||||
|
||||
func rawToPretty(config interface{}, parent *Block) *Content {
|
||||
|
|
|
@ -1,29 +1,28 @@
|
|||
package frontmatter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HasRune checks if the file has the frontmatter rune
|
||||
func HasRune(file []byte) bool {
|
||||
return strings.HasPrefix(string(file), "---") ||
|
||||
strings.HasPrefix(string(file), "+++") ||
|
||||
strings.HasPrefix(string(file), "{")
|
||||
func HasRune(file string) bool {
|
||||
return strings.HasPrefix(file, "---") ||
|
||||
strings.HasPrefix(file, "+++") ||
|
||||
strings.HasPrefix(file, "{")
|
||||
}
|
||||
|
||||
// AppendRune appends the frontmatter rune to a file
|
||||
func AppendRune(frontmatter []byte, mark rune) []byte {
|
||||
frontmatter = bytes.TrimSpace(frontmatter)
|
||||
func AppendRune(frontmatter string, mark rune) string {
|
||||
frontmatter = strings.TrimSpace(frontmatter)
|
||||
|
||||
switch mark {
|
||||
case '-':
|
||||
return []byte("---\n" + string(frontmatter) + "\n---")
|
||||
return "---\n" + frontmatter + "\n---"
|
||||
case '+':
|
||||
return []byte("+++\n" + string(frontmatter) + "\n+++")
|
||||
return "+++\n" + frontmatter + "\n+++"
|
||||
case '{':
|
||||
return []byte("{\n" + string(frontmatter) + "\n}")
|
||||
return "{\n" + frontmatter + "\n}"
|
||||
}
|
||||
|
||||
return frontmatter
|
||||
|
|
4
http.go
4
http.go
|
@ -15,7 +15,7 @@ const assetsURL = "/_"
|
|||
type requestContext struct {
|
||||
us *User
|
||||
fm *FileManager
|
||||
fi *fileInfo
|
||||
fi *file
|
||||
pg *page
|
||||
}
|
||||
|
||||
|
@ -82,7 +82,7 @@ func serveHTTP(c *requestContext, w http.ResponseWriter, r *http.Request) (int,
|
|||
}
|
||||
|
||||
if r.Method == http.MethodGet {
|
||||
var f *fileInfo
|
||||
var f *file
|
||||
|
||||
// Obtains the information of the directory/file.
|
||||
f, err = getInfo(r.URL, c.fm, c.us)
|
||||
|
|
10
page.go
10
page.go
|
@ -26,13 +26,11 @@ type page struct {
|
|||
User *User `json:"-"`
|
||||
BaseURL string `json:"-"`
|
||||
WebDavURL string `json:"-"`
|
||||
|
||||
Name string `json:"name"`
|
||||
Path string `json:"path"`
|
||||
Kind string `json:"kind"` // listing, editor or preview
|
||||
Data interface{} `json:"data"`
|
||||
Kind string `json:"kind"`
|
||||
Data *file `json:"data"`
|
||||
}
|
||||
|
||||
/*
|
||||
// breadcrumbItem contains the Name and the URL of a breadcrumb piece.
|
||||
type breadcrumbItem struct {
|
||||
Name string
|
||||
|
@ -90,7 +88,7 @@ func (p page) PreviousLink() string {
|
|||
}
|
||||
|
||||
return path
|
||||
}
|
||||
} */
|
||||
|
||||
func (p page) Render(c *requestContext, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
if strings.Contains(r.Header.Get("Accept"), "application/json") {
|
||||
|
|
2
put.go
2
put.go
|
@ -128,7 +128,7 @@ func parseCompleteFile(data map[string]interface{}, filename string, mark rune)
|
|||
return []byte{}, err
|
||||
}
|
||||
|
||||
front = frontmatter.AppendRune(front, mark)
|
||||
front = []byte(frontmatter.AppendRune(string(front), mark))
|
||||
|
||||
// Generates the final file
|
||||
f := new(bytes.Buffer)
|
||||
|
|
49
serve.go
49
serve.go
|
@ -2,18 +2,17 @@ package filemanager
|
|||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func serveDefault(c *requestContext, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
var err error
|
||||
|
||||
// Starts building the page.
|
||||
c.pg = &page{
|
||||
Name: c.fi.Name,
|
||||
Path: c.fi.VirtualPath,
|
||||
User: c.us,
|
||||
BaseURL: c.fm.RootURL(),
|
||||
WebDavURL: c.fm.WebDavURL(),
|
||||
Data: c.fi,
|
||||
}
|
||||
|
||||
// If it is a dir, go and serve the listing.
|
||||
|
@ -26,27 +25,15 @@ func serveDefault(c *requestContext, w http.ResponseWriter, r *http.Request) (in
|
|||
return errorToHTTP(err, true), err
|
||||
}
|
||||
|
||||
// If it is a text file, reads its content.
|
||||
if c.fi.Type == "text" {
|
||||
if err = c.fi.Read(); err != nil {
|
||||
return errorToHTTP(err, true), err
|
||||
}
|
||||
}
|
||||
|
||||
// If it can't be edited or the user isn't allowed to,
|
||||
// serve it as a listing, with a preview of the file.
|
||||
if !c.fi.CanBeEdited() || !c.us.AllowEdit {
|
||||
if c.fi.Type == "text" {
|
||||
c.fi.Content = string(c.fi.content)
|
||||
}
|
||||
|
||||
c.pg.Kind = "preview"
|
||||
c.pg.Data = c.fi
|
||||
} else {
|
||||
// Otherwise, we just bring the editor in!
|
||||
c.pg.Kind = "editor"
|
||||
|
||||
c.pg.Data, err = getEditor(r, c.fi)
|
||||
err = c.fi.getEditor(r)
|
||||
if err != nil {
|
||||
return http.StatusInternalServerError, err
|
||||
}
|
||||
|
@ -57,40 +44,31 @@ func serveDefault(c *requestContext, w http.ResponseWriter, r *http.Request) (in
|
|||
|
||||
// serveListing presents the user with a listage of a directory folder.
|
||||
func serveListing(c *requestContext, w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
var (
|
||||
err error
|
||||
listing *listing
|
||||
)
|
||||
var err error
|
||||
|
||||
c.pg.Kind = "listing"
|
||||
|
||||
listing, err = getListing(c.us, c.fi.VirtualPath, c.fm.RootURL()+r.URL.Path, c.fi)
|
||||
err = c.fi.getListing(c, r)
|
||||
if err != nil {
|
||||
return errorToHTTP(err, true), err
|
||||
}
|
||||
|
||||
listing := c.fi.listing
|
||||
|
||||
cookieScope := c.fm.RootURL()
|
||||
if cookieScope == "" {
|
||||
cookieScope = "/"
|
||||
}
|
||||
|
||||
// Copy the query values into the Listing struct
|
||||
var limit int
|
||||
listing.Sort, listing.Order, limit, err = handleSortOrder(w, r, cookieScope)
|
||||
listing.Sort, listing.Order, err = handleSortOrder(w, r, cookieScope)
|
||||
if err != nil {
|
||||
return http.StatusBadRequest, err
|
||||
}
|
||||
|
||||
listing.ApplySort()
|
||||
|
||||
if limit > 0 && limit <= len(listing.Items) {
|
||||
listing.Items = listing.Items[:limit]
|
||||
listing.ItemsLimitedTo = limit
|
||||
}
|
||||
|
||||
listing.Display = displayMode(w, r, cookieScope)
|
||||
c.pg.Data = listing
|
||||
|
||||
return c.pg.Render(c, w, r)
|
||||
}
|
||||
|
||||
|
@ -121,10 +99,9 @@ func displayMode(w http.ResponseWriter, r *http.Request, scope string) string {
|
|||
|
||||
// handleSortOrder gets and stores for a Listing the 'sort' and 'order',
|
||||
// and reads 'limit' if given. The latter is 0 if not given. Sets cookies.
|
||||
func handleSortOrder(w http.ResponseWriter, r *http.Request, scope string) (sort string, order string, limit int, err error) {
|
||||
func handleSortOrder(w http.ResponseWriter, r *http.Request, scope string) (sort string, order string, err error) {
|
||||
sort = r.URL.Query().Get("sort")
|
||||
order = r.URL.Query().Get("order")
|
||||
limitQuery := r.URL.Query().Get("limit")
|
||||
|
||||
// If the query 'sort' or 'order' is empty, use defaults or any values
|
||||
// previously saved in Cookies.
|
||||
|
@ -158,13 +135,5 @@ func handleSortOrder(w http.ResponseWriter, r *http.Request, scope string) (sort
|
|||
})
|
||||
}
|
||||
|
||||
if limitQuery != "" {
|
||||
limit, err = strconv.Atoi(limitQuery)
|
||||
// If the 'limit' query can't be interpreted as a number, return err.
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue