|
|
|
@ -11,6 +11,19 @@ import (
|
|
|
|
|
"bufio"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
/* FileSystemRequest:
|
|
|
|
|
* Makes a request to the filesystem either through
|
|
|
|
|
* the FileCache or directly to a function like listDir().
|
|
|
|
|
* It carries the requested filesystem path and any extra
|
|
|
|
|
* needed information, for the moment just a set of details
|
|
|
|
|
* about the virtual host.. Opens things up a lot more for
|
|
|
|
|
* the future :)
|
|
|
|
|
*/
|
|
|
|
|
type FileSystemRequest struct {
|
|
|
|
|
Path string
|
|
|
|
|
Host *ConnHost
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* File:
|
|
|
|
|
* Wraps around the cached contents of a file and
|
|
|
|
|
* helps with management of this content by the
|
|
|
|
@ -32,8 +45,8 @@ func NewFile(contents FileContents) *File {
|
|
|
|
|
return f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *File) Contents(connHost ConnHost) []byte {
|
|
|
|
|
return f.contents.Render(connHost)
|
|
|
|
|
func (f *File) Contents(request *FileSystemRequest) []byte {
|
|
|
|
|
return f.contents.Render(request)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *File) LoadContents() *GophorError {
|
|
|
|
@ -89,8 +102,8 @@ func (f *File) RUnlock() {
|
|
|
|
|
* are requested.
|
|
|
|
|
*/
|
|
|
|
|
type FileContents interface {
|
|
|
|
|
Render(ConnHost) []byte
|
|
|
|
|
Load() *GophorError
|
|
|
|
|
Render(*FileSystemRequest) []byte
|
|
|
|
|
Load() *GophorError
|
|
|
|
|
Clear()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -196,10 +209,10 @@ func unixLineEndSplitter(data []byte, atEOF bool) (advance int, token []byte, er
|
|
|
|
|
* This negates need to check if RestrictedFilesRegex is nil every
|
|
|
|
|
* single call.
|
|
|
|
|
*/
|
|
|
|
|
var listDir func(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError)
|
|
|
|
|
var listDir func(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError)
|
|
|
|
|
|
|
|
|
|
func _listDir(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError) {
|
|
|
|
|
return _listDirBase(dirPath, func(dirContents *[]byte, file os.FileInfo, host ConnHost) {
|
|
|
|
|
func _listDir(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError) {
|
|
|
|
|
return _listDirBase(request, func(dirContents *[]byte, file os.FileInfo) {
|
|
|
|
|
/* If requested hidden */
|
|
|
|
|
if _, ok := hidden[file.Name()]; ok {
|
|
|
|
|
return
|
|
|
|
@ -209,23 +222,23 @@ func _listDir(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte
|
|
|
|
|
switch {
|
|
|
|
|
case file.Mode() & os.ModeDir != 0:
|
|
|
|
|
/* Directory -- create directory listing */
|
|
|
|
|
itemPath := path.Join(dirPath, file.Name())
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, connHost.Name, connHost.Port)...)
|
|
|
|
|
itemPath := path.Join(request.Path, file.Name())
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
|
|
|
|
|
|
|
|
|
|
case file.Mode() & os.ModeType == 0:
|
|
|
|
|
/* Regular file -- find item type and creating listing */
|
|
|
|
|
itemPath := path.Join(dirPath, file.Name())
|
|
|
|
|
itemPath := path.Join(request.Path, file.Name())
|
|
|
|
|
itemType := getItemType(itemPath)
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, connHost.Name, connHost.Port)...)
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* Ignore */
|
|
|
|
|
}
|
|
|
|
|
}, connHost)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func _listDirRegexMatch(dirPath string, hidden map[string]bool, connHost ConnHost) ([]byte, *GophorError) {
|
|
|
|
|
return _listDirBase(dirPath, func(dirContents *[]byte, file os.FileInfo, host ConnHost) {
|
|
|
|
|
func _listDirRegexMatch(request *FileSystemRequest, hidden map[string]bool) ([]byte, *GophorError) {
|
|
|
|
|
return _listDirBase(request, func(dirContents *[]byte, file os.FileInfo) {
|
|
|
|
|
/* If regex match in restricted files || requested hidden */
|
|
|
|
|
if isRestrictedFile(file.Name()) {
|
|
|
|
|
return
|
|
|
|
@ -237,33 +250,33 @@ func _listDirRegexMatch(dirPath string, hidden map[string]bool, connHost ConnHos
|
|
|
|
|
switch {
|
|
|
|
|
case file.Mode() & os.ModeDir != 0:
|
|
|
|
|
/* Directory -- create directory listing */
|
|
|
|
|
itemPath := path.Join(dirPath, file.Name())
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, host.Name, host.Port)...)
|
|
|
|
|
itemPath := path.Join(request.Path, file.Name())
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(TypeDirectory, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
|
|
|
|
|
|
|
|
|
|
case file.Mode() & os.ModeType == 0:
|
|
|
|
|
/* Regular file -- find item type and creating listing */
|
|
|
|
|
itemPath := path.Join(dirPath, file.Name())
|
|
|
|
|
itemPath := path.Join(request.Path, file.Name())
|
|
|
|
|
itemType := getItemType(itemPath)
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, host.Name, host.Port)...)
|
|
|
|
|
*dirContents = append(*dirContents, buildLine(itemType, file.Name(), itemPath, request.Host.Name, request.Host.Port)...)
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
/* Ignore */
|
|
|
|
|
}
|
|
|
|
|
}, connHost)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.FileInfo, connHost ConnHost), connHost ConnHost) ([]byte, *GophorError) {
|
|
|
|
|
func _listDirBase(request *FileSystemRequest, iterFunc func(dirContents *[]byte, file os.FileInfo)) ([]byte, *GophorError) {
|
|
|
|
|
/* Open directory file descriptor */
|
|
|
|
|
fd, err := os.Open(dirPath)
|
|
|
|
|
fd, err := os.Open(request.Path)
|
|
|
|
|
if err != nil {
|
|
|
|
|
Config.LogSystemError("failed to open %s: %s\n", dirPath, err.Error())
|
|
|
|
|
Config.LogSystemError("failed to open %s: %s\n", request.Path, err.Error())
|
|
|
|
|
return nil, &GophorError{ FileOpenErr, err }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read files in directory */
|
|
|
|
|
files, err := fd.Readdir(-1)
|
|
|
|
|
if err != nil {
|
|
|
|
|
Config.LogSystemError("failed to enumerate dir %s: %s\n", dirPath, err.Error())
|
|
|
|
|
Config.LogSystemError("failed to enumerate dir %s: %s\n", request.Path, err.Error())
|
|
|
|
|
return nil, &GophorError{ DirListErr, err }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -274,14 +287,14 @@ func _listDirBase(dirPath string, iterFunc func(dirContents *[]byte, file os.Fil
|
|
|
|
|
dirContents := make([]byte, 0)
|
|
|
|
|
|
|
|
|
|
/* First add a title + a space */
|
|
|
|
|
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+Config.Hostname+dirPath+" ]", "TITLE", NullHost, NullPort)...)
|
|
|
|
|
dirContents = append(dirContents, buildLine(TypeInfo, "[ "+request.Host.Name+request.Path+" ]", "TITLE", NullHost, NullPort)...)
|
|
|
|
|
dirContents = append(dirContents, buildInfoLine("")...)
|
|
|
|
|
|
|
|
|
|
/* Add a 'back' entry. GoLang Readdir() seems to miss this */
|
|
|
|
|
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), Config.Hostname, Config.Port)...)
|
|
|
|
|
dirContents = append(dirContents, buildLine(TypeDirectory, "..", path.Join(fd.Name(), ".."), request.Host.Name, request.Host.Port)...)
|
|
|
|
|
|
|
|
|
|
/* Walk through files :D */
|
|
|
|
|
for _, file := range files { iterFunc(&dirContents, file, connHost) }
|
|
|
|
|
for _, file := range files { iterFunc(&dirContents, file) }
|
|
|
|
|
|
|
|
|
|
return dirContents, nil
|
|
|
|
|
}
|
|
|
|
|