more updates

Former-commit-id: 8c19eda25f
pull/726/head
Henrique Dias 2017-06-19 18:23:57 +01:00
parent 8d4981fcb8
commit bd7184d5df
16 changed files with 79 additions and 83 deletions

View File

@ -24,7 +24,7 @@ type editor struct {
} }
// newEditor gets the editor based on a FileInfo struct // newEditor gets the editor based on a FileInfo struct
func newEditor(r *http.Request, i *file) (*editor, error) { func newEditor(r *http.Request, i *fileInfo) (*editor, error) {
var err error var err error
// Create a new editor variable and set the mode // Create a new editor variable and set the mode

22
file.go
View File

@ -13,8 +13,8 @@ import (
humanize "github.com/dustin/go-humanize" humanize "github.com/dustin/go-humanize"
) )
// file contains the information about a particular file or directory. // fileInfo contains the information about a particular file or directory.
type file struct { type fileInfo struct {
Name string Name string
Size int64 Size int64
URL string URL string
@ -30,11 +30,11 @@ type file struct {
UserAllowed bool // Indicates if the user has enough permissions UserAllowed bool // Indicates if the user has enough permissions
} }
// getFile retrieves the file information and the error, if there is any. // getFileInfo retrieves the file information and the error, if there is any.
func getFile(url *url.URL, c *Config, u *User) (*file, error) { func getFileInfo(url *url.URL, c *FileManager, u *User) (*fileInfo, error) {
var err error var err error
i := &file{URL: c.PrefixURL + url.Path} i := &fileInfo{URL: c.PrefixURL + url.Path}
i.VirtualPath = strings.Replace(url.Path, c.BaseURL, "", 1) i.VirtualPath = strings.Replace(url.Path, c.BaseURL, "", 1)
i.VirtualPath = strings.TrimPrefix(i.VirtualPath, "/") i.VirtualPath = strings.TrimPrefix(i.VirtualPath, "/")
i.VirtualPath = "/" + i.VirtualPath i.VirtualPath = "/" + i.VirtualPath
@ -75,7 +75,7 @@ var textExtensions = [...]string{
// RetrieveFileType obtains the mimetype and a simplified internal Type // RetrieveFileType obtains the mimetype and a simplified internal Type
// using the first 512 bytes from the file. // using the first 512 bytes from the file.
func (i *file) RetrieveFileType() error { func (i fileInfo) RetrieveFileType() error {
i.Mimetype = mime.TypeByExtension(i.Extension) i.Mimetype = mime.TypeByExtension(i.Extension)
if i.Mimetype == "" { if i.Mimetype == "" {
@ -126,7 +126,7 @@ func (i *file) RetrieveFileType() error {
} }
// Reads the file. // Reads the file.
func (i *file) Read() error { func (i fileInfo) Read() error {
if len(i.Content) != 0 { if len(i.Content) != 0 {
return nil return nil
} }
@ -140,22 +140,22 @@ func (i *file) Read() error {
} }
// StringifyContent returns the string version of Raw // StringifyContent returns the string version of Raw
func (i file) StringifyContent() string { func (i fileInfo) StringifyContent() string {
return string(i.Content) return string(i.Content)
} }
// HumanSize returns the size of the file as a human-readable string // HumanSize returns the size of the file as a human-readable string
// in IEC format (i.e. power of 2 or base 1024). // in IEC format (i.e. power of 2 or base 1024).
func (i file) HumanSize() string { func (i fileInfo) HumanSize() string {
return humanize.IBytes(uint64(i.Size)) return humanize.IBytes(uint64(i.Size))
} }
// HumanModTime returns the modified time of the file as a human-readable string. // HumanModTime returns the modified time of the file as a human-readable string.
func (i file) HumanModTime(format string) string { func (i fileInfo) HumanModTime(format string) string {
return i.ModTime.Format(format) return i.ModTime.Format(format)
} }
// CanBeEdited checks if the extension of a file is supported by the editor // CanBeEdited checks if the extension of a file is supported by the editor
func (i file) CanBeEdited() bool { func (i fileInfo) CanBeEdited() bool {
return i.Type == "text" return i.Type == "text"
} }

View File

@ -10,8 +10,8 @@ import (
"golang.org/x/net/webdav" "golang.org/x/net/webdav"
) )
// Config is a configuration for browsing in a particular path. // FileManager is a configuration for browsing in a particular path.
type Config struct { type FileManager struct {
*User *User
PrefixURL string // A part of the URL that is stripped from the http.Request PrefixURL string // A part of the URL that is stripped from the http.Request
BaseURL string // The base URL of FileManager interface BaseURL string // The base URL of FileManager interface
@ -27,8 +27,8 @@ type Config struct {
// New creates a new FileManager object with the default settings // New creates a new FileManager object with the default settings
// for a certain scope. // for a certain scope.
func New(scope string) *Config { func New(scope string) *FileManager {
cfg := &Config{ fm := &FileManager{
User: &User{ User: &User{
Scope: scope, Scope: scope,
FileSystem: webdav.Dir(scope), FileSystem: webdav.Dir(scope),
@ -46,26 +46,26 @@ func New(scope string) *Config {
BaseURL: "", BaseURL: "",
PrefixURL: "", PrefixURL: "",
WebDavURL: "/webdav", WebDavURL: "/webdav",
BeforeSave: func(r *http.Request, c *Config, u *User) error { return nil }, BeforeSave: func(r *http.Request, c *FileManager, u *User) error { return nil },
AfterSave: func(r *http.Request, c *Config, u *User) error { return nil }, AfterSave: func(r *http.Request, c *FileManager, u *User) error { return nil },
} }
cfg.Handler = &webdav.Handler{ fm.Handler = &webdav.Handler{
Prefix: cfg.WebDavURL, Prefix: fm.WebDavURL,
FileSystem: cfg.FileSystem, FileSystem: fm.FileSystem,
LockSystem: webdav.NewMemLS(), LockSystem: webdav.NewMemLS(),
} }
return cfg return fm
} }
// AbsoluteURL ... // AbsoluteURL ...
func (c Config) AbsoluteURL() string { func (c FileManager) AbsoluteURL() string {
return c.PrefixURL + c.BaseURL return c.PrefixURL + c.BaseURL
} }
// AbsoluteWebdavURL ... // AbsoluteWebdavURL ...
func (c Config) AbsoluteWebdavURL() string { func (c FileManager) AbsoluteWebdavURL() string {
return c.PrefixURL + c.WebDavURL return c.PrefixURL + c.WebDavURL
} }
@ -113,4 +113,4 @@ func (u User) Allowed(url string) bool {
} }
// Command is a user-defined command that is executed in some moments. // Command is a user-defined command that is executed in some moments.
type Command func(r *http.Request, c *Config, u *User) error type Command func(r *http.Request, c *FileManager, u *User) error

View File

@ -11,9 +11,9 @@ import (
) )
// ServeHTTP starts FileManager. // ServeHTTP starts FileManager.
func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (c *FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
var ( var (
fi *file fi *fileInfo
user *User user *User
code int code int
err error err error
@ -127,7 +127,7 @@ func (c *Config) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error)
if r.Method == http.MethodGet { if r.Method == http.MethodGet {
// Gets the information of the directory/file // Gets the information of the directory/file
fi, err = getFile(r.URL, c, user) fi, err = getFileInfo(r.URL, c, user)
code = errorToHTTPCode(err, false) code = errorToHTTPCode(err, false)
if err != nil { if err != nil {
if r.Method == http.MethodGet { if r.Method == http.MethodGet {

View File

@ -14,7 +14,7 @@ import (
) )
// checksum calculates the hash of a filemanager. Supports MD5, SHA1, SHA256 and SHA512. // checksum calculates the hash of a filemanager. Supports MD5, SHA1, SHA256 and SHA512.
func (c *Config) checksum(w http.ResponseWriter, r *http.Request, i *file) (int, error) { func (c *FileManager) checksum(w http.ResponseWriter, r *http.Request, i *fileInfo) (int, error) {
query := r.URL.Query().Get("checksum") query := r.URL.Query().Get("checksum")
file, err := os.Open(i.Path) file, err := os.Open(i.Path)

View File

@ -22,7 +22,7 @@ var (
) )
// command handles the requests for VCS related commands: git, svn and mercurial // command handles the requests for VCS related commands: git, svn and mercurial
func (c *Config) command(w http.ResponseWriter, r *http.Request, u *User) (int, error) { func (c *FileManager) command(w http.ResponseWriter, r *http.Request, u *User) (int, error) {
// Upgrades the connection to a websocket and checks for errors. // Upgrades the connection to a websocket and checks for errors.
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {

View File

@ -14,7 +14,7 @@ import (
// download creates an archive in one of the supported formats (zip, tar, // download creates an archive in one of the supported formats (zip, tar,
// tar.gz or tar.bz2) and sends it to be downloaded. // tar.gz or tar.bz2) and sends it to be downloaded.
func (c *Config) download(w http.ResponseWriter, r *http.Request, i *file) (int, error) { func (c *FileManager) download(w http.ResponseWriter, r *http.Request, i *fileInfo) (int, error) {
query := r.URL.Query().Get("download") query := r.URL.Query().Get("download")
if !i.IsDir { if !i.IsDir {

View File

@ -10,11 +10,11 @@ import (
) )
// serveListing presents the user with a listage of a directory folder. // serveListing presents the user with a listage of a directory folder.
func (c *Config) serveListing(w http.ResponseWriter, r *http.Request, u *User, i *file) (int, error) { func (c *FileManager) serveListing(w http.ResponseWriter, r *http.Request, u *User, i *fileInfo) (int, error) {
var err error var err error
// Loads the content of the directory // Loads the content of the directory
listing, err := GetListing(u, i.VirtualPath, c.PrefixURL+r.URL.Path) listing, err := getListing(u, i.VirtualPath, c.PrefixURL+r.URL.Path)
if err != nil { if err != nil {
return errorToHTTPCode(err, true), err return errorToHTTPCode(err, true), err
} }

View File

@ -14,7 +14,7 @@ import (
) )
// preProccessPUT is used to update a file that was edited // preProccessPUT is used to update a file that was edited
func (c *Config) preProccessPUT(w http.ResponseWriter, r *http.Request, u *User) (err error) { func (c *FileManager) preProccessPUT(w http.ResponseWriter, r *http.Request, u *User) (err error) {
var ( var (
data = map[string]interface{}{} data = map[string]interface{}{}
file []byte file []byte

View File

@ -43,7 +43,7 @@ func parseSearch(value string) *searchOptions {
} }
// search ... // search ...
func (c *Config) search(w http.ResponseWriter, r *http.Request, u *User) (int, error) { func (c *FileManager) search(w http.ResponseWriter, r *http.Request, u *User) (int, error) {
// Upgrades the connection to a websocket and checks for errors. // Upgrades the connection to a websocket and checks for errors.
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {

View File

@ -7,7 +7,7 @@ import (
// serveSingle serves a single file in an editor (if it is editable), shows the // serveSingle serves a single file in an editor (if it is editable), shows the
// plain file, or downloads it if it can't be shown. // plain file, or downloads it if it can't be shown.
func (c *Config) serveSingle(w http.ResponseWriter, r *http.Request, u *User, i *file) (int, error) { func (c *FileManager) serveSingle(w http.ResponseWriter, r *http.Request, u *User, i *fileInfo) (int, error) {
var err error var err error
if err = i.RetrieveFileType(); err != nil { if err = i.RetrieveFileType(); err != nil {

View File

@ -1,24 +0,0 @@
package filemanager
import (
"net/http"
"os"
)
// errorToHTTPCode converts errors to HTTP Status Code.
func errorToHTTPCode(err error, gone bool) int {
switch {
case os.IsPermission(err):
return http.StatusForbidden
case os.IsNotExist(err):
if !gone {
return http.StatusNotFound
}
return http.StatusGone
case os.IsExist(err):
return http.StatusGone
default:
return http.StatusInternalServerError
}
}

View File

@ -11,14 +11,14 @@ import (
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
) )
// A Listing is the context used to fill out a template. // A listing is the context used to fill out a template.
type Listing struct { type listing struct {
// The name of the directory (the last element of the path) // The name of the directory (the last element of the path)
Name string Name string
// The full path of the request relatively to a File System // The full path of the request relatively to a File System
Path string Path string
// The items (files and folders) in the path // The items (files and folders) in the path
Items []file Items []fileInfo
// The number of directories in the listing // The number of directories in the listing
NumDirs int NumDirs int
// The number of files (items that aren't directories) in the listing // The number of files (items that aren't directories) in the listing
@ -32,8 +32,8 @@ type Listing struct {
httpserver.Context `json:"-"` httpserver.Context `json:"-"`
} }
// GetListing gets the information about a specific directory and its files. // getListing gets the information about a specific directory and its files.
func GetListing(u *User, filePath string, baseURL string) (*Listing, error) { func getListing(u *User, filePath string, baseURL string) (*listing, error) {
// Gets the directory information using the Virtual File System of // Gets the directory information using the Virtual File System of
// the user configuration. // the user configuration.
file, err := u.FileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0) file, err := u.FileSystem.OpenFile(context.TODO(), filePath, os.O_RDONLY, 0)
@ -49,7 +49,7 @@ func GetListing(u *User, filePath string, baseURL string) (*Listing, error) {
} }
var ( var (
fileinfos []*file fileinfos []fileInfo
dirCount, fileCount int dirCount, fileCount int
) )
@ -71,7 +71,7 @@ func GetListing(u *User, filePath string, baseURL string) (*Listing, error) {
// Absolute URL // Absolute URL
url := url.URL{Path: baseURL + name} url := url.URL{Path: baseURL + name}
i := &file{ i := fileInfo{
Name: f.Name(), Name: f.Name(),
Size: f.Size(), Size: f.Size(),
ModTime: f.ModTime(), ModTime: f.ModTime(),
@ -85,7 +85,7 @@ func GetListing(u *User, filePath string, baseURL string) (*Listing, error) {
fileinfos = append(fileinfos, i) fileinfos = append(fileinfos, i)
} }
return &Listing{ return &listing{
Name: path.Base(filePath), Name: path.Base(filePath),
Path: filePath, Path: filePath,
Items: fileinfos, Items: fileinfos,
@ -95,7 +95,7 @@ func GetListing(u *User, filePath string, baseURL string) (*Listing, error) {
} }
// ApplySort applies the sort order using .Order and .Sort // ApplySort applies the sort order using .Order and .Sort
func (l Listing) ApplySort() { func (l listing) ApplySort() {
// Check '.Order' to know how to sort // Check '.Order' to know how to sort
if l.Order == "desc" { if l.Order == "desc" {
switch l.Sort { switch l.Sort {
@ -124,10 +124,10 @@ func (l Listing) ApplySort() {
} }
} }
// Implement sorting for Listing // Implement sorting for listing
type byName Listing type byName listing
type bySize Listing type bySize listing
type byTime Listing type byTime listing
// By Name // By Name
func (l byName) Len() int { func (l byName) Len() int {

11
page.go
View File

@ -11,6 +11,15 @@ import (
"strings" "strings"
) )
// Create the functions map, then the template, check for erros and
// execute the template if there aren't errors
var functionMap = template.FuncMap{
"Defined": defined,
"CSS": css,
"Marshal": marshal,
"EncodeBase64": encodeBase64,
}
// page contains the informations and functions needed to show the Page // page contains the informations and functions needed to show the Page
type page struct { type page struct {
Info *pageInfo Info *pageInfo
@ -23,7 +32,7 @@ type pageInfo struct {
Path string Path string
IsDir bool IsDir bool
User *User User *User
Config *Config Config *FileManager
Data interface{} Data interface{}
Editor bool Editor bool
Display string Display string

View File

@ -5,18 +5,11 @@ import (
"encoding/json" "encoding/json"
"html/template" "html/template"
"log" "log"
"net/http"
"os"
"reflect" "reflect"
) )
// Create the functions map, then the template, check for erros and
// execute the template if there aren't errors
var functionMap = template.FuncMap{
"Defined": defined,
"CSS": css,
"Marshal": marshal,
"EncodeBase64": encodeBase64,
}
// defined checks if variable is defined in a struct // defined checks if variable is defined in a struct
func defined(data interface{}, field string) bool { func defined(data interface{}, field string) bool {
t := reflect.Indirect(reflect.ValueOf(data)).Type() t := reflect.Indirect(reflect.ValueOf(data)).Type()
@ -45,3 +38,21 @@ func marshal(v interface{}) template.JS {
func encodeBase64(s string) string { func encodeBase64(s string) string {
return base64.StdEncoding.EncodeToString([]byte(s)) return base64.StdEncoding.EncodeToString([]byte(s))
} }
// errorToHTTPCode converts errors to HTTP Status Code.
func errorToHTTPCode(err error, gone bool) int {
switch {
case os.IsPermission(err):
return http.StatusForbidden
case os.IsNotExist(err):
if !gone {
return http.StatusNotFound
}
return http.StatusGone
case os.IsExist(err):
return http.StatusGone
default:
return http.StatusInternalServerError
}
}