177 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Go
		
	
	
package filemanager
 | 
						|
 | 
						|
import (
 | 
						|
	"bytes"
 | 
						|
	"encoding/base64"
 | 
						|
	"encoding/json"
 | 
						|
	"html/template"
 | 
						|
	"log"
 | 
						|
	"net/http"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/hacdias/filemanager/variables"
 | 
						|
)
 | 
						|
 | 
						|
// functions contains the non-standard functions that are available
 | 
						|
// to use on the HTML templates.
 | 
						|
var functions = template.FuncMap{
 | 
						|
	"Defined": variables.FieldInStruct,
 | 
						|
	"CSS": func(s string) template.CSS {
 | 
						|
		return template.CSS(s)
 | 
						|
	},
 | 
						|
	"Marshal": func(v interface{}) template.JS {
 | 
						|
		a, _ := json.Marshal(v)
 | 
						|
		return template.JS(a)
 | 
						|
	},
 | 
						|
	"EncodeBase64": func(s string) string {
 | 
						|
		return base64.StdEncoding.EncodeToString([]byte(s))
 | 
						|
	},
 | 
						|
}
 | 
						|
 | 
						|
// page contains the information needed to fill a page template.
 | 
						|
type page struct {
 | 
						|
	minimal   bool
 | 
						|
	Name      string
 | 
						|
	Path      string
 | 
						|
	IsDir     bool
 | 
						|
	User      *User
 | 
						|
	PrefixURL string
 | 
						|
	BaseURL   string
 | 
						|
	WebDavURL string
 | 
						|
	Data      interface{}
 | 
						|
	Editor    bool
 | 
						|
	Display   string
 | 
						|
}
 | 
						|
 | 
						|
// breadcrumbItem contains the Name and the URL of a breadcrumb piece.
 | 
						|
type breadcrumbItem struct {
 | 
						|
	Name string
 | 
						|
	URL  string
 | 
						|
}
 | 
						|
 | 
						|
// BreadcrumbMap returns p.Path where every element is a map
 | 
						|
// of URLs and path segment names.
 | 
						|
func (p page) BreadcrumbMap() []breadcrumbItem {
 | 
						|
	result := []breadcrumbItem{}
 | 
						|
 | 
						|
	if len(p.Path) == 0 {
 | 
						|
		return result
 | 
						|
	}
 | 
						|
 | 
						|
	// skip trailing slash
 | 
						|
	lpath := p.Path
 | 
						|
	if lpath[len(lpath)-1] == '/' {
 | 
						|
		lpath = lpath[:len(lpath)-1]
 | 
						|
	}
 | 
						|
 | 
						|
	parts := strings.Split(lpath, "/")
 | 
						|
	for i, part := range parts {
 | 
						|
		if i == len(parts)-1 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		if i == 0 && part == "" {
 | 
						|
			result = append([]breadcrumbItem{{
 | 
						|
				Name: "/",
 | 
						|
				URL:  "/",
 | 
						|
			}}, result...)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		result = append([]breadcrumbItem{{
 | 
						|
			Name: part,
 | 
						|
			URL:  strings.Join(parts[:i+1], "/") + "/",
 | 
						|
		}}, result...)
 | 
						|
	}
 | 
						|
 | 
						|
	return result
 | 
						|
}
 | 
						|
 | 
						|
// PreviousLink returns the URL of the previous folder.
 | 
						|
func (p page) PreviousLink() string {
 | 
						|
	path := strings.TrimSuffix(p.Path, "/")
 | 
						|
	path = strings.TrimPrefix(path, "/")
 | 
						|
	path = p.BaseURL + "/" + path
 | 
						|
	path = path[0 : len(path)-len(p.Name)]
 | 
						|
 | 
						|
	if len(path) < len(p.BaseURL+"/") {
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
 | 
						|
	return path
 | 
						|
}
 | 
						|
 | 
						|
// PrintAsHTML formats the page in HTML and executes the template
 | 
						|
func (p page) PrintAsHTML(w http.ResponseWriter, m *FileManager, templates ...string) (int, error) {
 | 
						|
	templates = append(templates, "templates")
 | 
						|
 | 
						|
	if p.minimal {
 | 
						|
		templates = append(templates, "minimal")
 | 
						|
	} else {
 | 
						|
		templates = append(templates, "base")
 | 
						|
	}
 | 
						|
 | 
						|
	var tpl *template.Template
 | 
						|
 | 
						|
	// For each template, add it to the the tpl variable
 | 
						|
	for i, t := range templates {
 | 
						|
		// Get the template from the assets
 | 
						|
		Page, err := getTemplate(m, t+".tmpl")
 | 
						|
 | 
						|
		// Check if there is some error. If so, the template doesn't exist
 | 
						|
		if err != nil {
 | 
						|
			log.Print(err)
 | 
						|
			return http.StatusInternalServerError, err
 | 
						|
		}
 | 
						|
 | 
						|
		// If it's the first iteration, creates a new template and add the
 | 
						|
		// functions map
 | 
						|
		if i == 0 {
 | 
						|
			tpl, err = template.New(t).Funcs(functions).Parse(Page)
 | 
						|
		} else {
 | 
						|
			tpl, err = tpl.Parse(string(Page))
 | 
						|
		}
 | 
						|
 | 
						|
		if err != nil {
 | 
						|
			log.Print(err)
 | 
						|
			return http.StatusInternalServerError, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	buf := &bytes.Buffer{}
 | 
						|
	err := tpl.Execute(buf, p)
 | 
						|
 | 
						|
	if err != nil {
 | 
						|
		return http.StatusInternalServerError, err
 | 
						|
	}
 | 
						|
 | 
						|
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
 | 
						|
	_, err = buf.WriteTo(w)
 | 
						|
	return http.StatusOK, err
 | 
						|
}
 | 
						|
 | 
						|
// PrintAsJSON prints the current Page information in JSON
 | 
						|
func (p page) PrintAsJSON(w http.ResponseWriter) (int, error) {
 | 
						|
	marsh, err := json.MarshalIndent(p.Data, "", "    ")
 | 
						|
	if err != nil {
 | 
						|
		return http.StatusInternalServerError, err
 | 
						|
	}
 | 
						|
 | 
						|
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
 | 
						|
	if _, err := w.Write(marsh); err != nil {
 | 
						|
		return http.StatusInternalServerError, err
 | 
						|
	}
 | 
						|
 | 
						|
	return http.StatusOK, nil
 | 
						|
}
 | 
						|
 | 
						|
func getTemplate(m *FileManager, template string) (string, error) {
 | 
						|
	if m.Assets.Templates != nil {
 | 
						|
		if tpl, err := m.Assets.Templates.String(template); err == nil {
 | 
						|
			return tpl, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return m.Assets.baseTemplates.String(template)
 | 
						|
}
 |