improve code commenting
Signed-off-by: kim (grufwub) <grufwub@gmail.com>
This commit is contained in:
parent
242fc9895a
commit
0f2a2099f2
17
cache.go
17
cache.go
@ -49,6 +49,12 @@ func checkCacheFreshness() {
|
|||||||
Config.FileCache.CacheMutex.Unlock()
|
Config.FileCache.CacheMutex.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FileCache:
|
||||||
|
* Object to hold and help manage our file cache. Uses a fixed map
|
||||||
|
* as a means of easily collecting files by path, but also being able
|
||||||
|
* to remove cached files in a LRU style. Uses a RW mutex to lock the
|
||||||
|
* cache map for appropriate functions and ensure thread safety.
|
||||||
|
*/
|
||||||
type FileCache struct {
|
type FileCache struct {
|
||||||
CacheMap *FixedMap
|
CacheMap *FixedMap
|
||||||
CacheMutex sync.RWMutex
|
CacheMutex sync.RWMutex
|
||||||
@ -62,6 +68,7 @@ func (fc *FileCache) Init(size int, fileSizeMax float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *FileCache) FetchRegular(request *FileSystemRequest) ([]byte, *GophorError) {
|
func (fc *FileCache) FetchRegular(request *FileSystemRequest) ([]byte, *GophorError) {
|
||||||
|
/* Calls fc.Fetch() but with the filecontents init function for a regular file */
|
||||||
return fc.Fetch(request, func(path string) FileContents {
|
return fc.Fetch(request, func(path string) FileContents {
|
||||||
contents := new(RegularFileContents)
|
contents := new(RegularFileContents)
|
||||||
contents.path = path
|
contents.path = path
|
||||||
@ -70,6 +77,7 @@ func (fc *FileCache) FetchRegular(request *FileSystemRequest) ([]byte, *GophorEr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *FileCache) FetchGophermap(request *FileSystemRequest) ([]byte, *GophorError) {
|
func (fc *FileCache) FetchGophermap(request *FileSystemRequest) ([]byte, *GophorError) {
|
||||||
|
/* Calls fc.Fetch() but with the filecontents init function for a gophermap */
|
||||||
return fc.Fetch(request, func(path string) FileContents {
|
return fc.Fetch(request, func(path string) FileContents {
|
||||||
contents := new(GophermapContents)
|
contents := new(GophermapContents)
|
||||||
contents.path = path
|
contents.path = path
|
||||||
@ -82,7 +90,8 @@ func (fc *FileCache) Fetch(request *FileSystemRequest, newFileContents func(stri
|
|||||||
fc.CacheMutex.RLock()
|
fc.CacheMutex.RLock()
|
||||||
file := fc.CacheMap.Get(request.Path)
|
file := fc.CacheMap.Get(request.Path)
|
||||||
|
|
||||||
/* TODO: work on efficiency */
|
/* TODO: work on efficiency. improve use of mutex?? */
|
||||||
|
|
||||||
if file != nil {
|
if file != nil {
|
||||||
/* File in cache -- before doing anything get file read lock */
|
/* File in cache -- before doing anything get file read lock */
|
||||||
file.RLock()
|
file.RLock()
|
||||||
@ -107,7 +116,9 @@ func (fc *FileCache) Fetch(request *FileSystemRequest, newFileContents func(stri
|
|||||||
file.RLock()
|
file.RLock()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Before we do ANYTHING, we need to check file-size on disk */
|
/* Perform filesystem stat ready for checking file size later.
|
||||||
|
* Doing this now allows us to weed-out non-existent files early
|
||||||
|
*/
|
||||||
stat, err := os.Stat(request.Path)
|
stat, err := os.Stat(request.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
/* Error stat'ing file, unlock read mutex then return error */
|
/* Error stat'ing file, unlock read mutex then return error */
|
||||||
@ -122,7 +133,7 @@ func (fc *FileCache) Fetch(request *FileSystemRequest, newFileContents func(stri
|
|||||||
file = NewFile(contents)
|
file = NewFile(contents)
|
||||||
|
|
||||||
/* NOTE: file isn't in cache yet so no need to lock file write mutex
|
/* NOTE: file isn't in cache yet so no need to lock file write mutex
|
||||||
* before loading from disk
|
* before loading contents from disk
|
||||||
*/
|
*/
|
||||||
gophorErr := file.LoadContents()
|
gophorErr := file.LoadContents()
|
||||||
if gophorErr != nil {
|
if gophorErr != nil {
|
||||||
|
@ -5,12 +5,15 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* ServerConfig:
|
||||||
|
* Holds onto global server configuration details
|
||||||
|
* and any data objects we want to keep in memory
|
||||||
|
* (e.g. loggers, restricted files regular expressions
|
||||||
|
* and file cache)
|
||||||
|
*/
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
/* Base settings */
|
/* Base settings */
|
||||||
RootDir string
|
RootDir string
|
||||||
Hostname string
|
|
||||||
Port string
|
|
||||||
TlsPort string
|
|
||||||
|
|
||||||
/* Caps.txt information */
|
/* Caps.txt information */
|
||||||
Description string
|
Description string
|
||||||
|
9
conn.go
9
conn.go
@ -4,16 +4,15 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Data structure to hold specific host details
|
/* Data structure to hold specific host details */
|
||||||
* for passing on later
|
|
||||||
*/
|
|
||||||
type ConnHost struct {
|
type ConnHost struct {
|
||||||
Name string
|
Name string
|
||||||
Port string
|
Port string
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple wrapper to Listener that generates
|
/* Simple wrapper to Listener that holds onto virtual
|
||||||
* GophorConn instances on each accept
|
* host information and generates GophorConn
|
||||||
|
* instances on each accept
|
||||||
*/
|
*/
|
||||||
type GophorListener struct {
|
type GophorListener struct {
|
||||||
Listener net.Listener
|
Listener net.Listener
|
||||||
|
12
error.go
12
error.go
@ -4,9 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/* Simple error code type defs */
|
||||||
* Client error data structure
|
|
||||||
*/
|
|
||||||
type ErrorCode int
|
type ErrorCode int
|
||||||
type ErrorResponseCode int
|
type ErrorResponseCode int
|
||||||
const (
|
const (
|
||||||
@ -43,11 +41,13 @@ const (
|
|||||||
NoResponse ErrorResponseCode = iota
|
NoResponse ErrorResponseCode = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* Simple GophorError data structure to wrap another error */
|
||||||
type GophorError struct {
|
type GophorError struct {
|
||||||
Code ErrorCode
|
Code ErrorCode
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert error code to string */
|
||||||
func (e *GophorError) Error() string {
|
func (e *GophorError) Error() string {
|
||||||
var str string
|
var str string
|
||||||
switch e.Code {
|
switch e.Code {
|
||||||
@ -91,6 +91,7 @@ func (e *GophorError) Error() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert a gophor error code to appropriate error response code */
|
||||||
func gophorErrorToResponseCode(code ErrorCode) ErrorResponseCode {
|
func gophorErrorToResponseCode(code ErrorCode) ErrorResponseCode {
|
||||||
switch code {
|
switch code {
|
||||||
case PathEnumerationErr:
|
case PathEnumerationErr:
|
||||||
@ -109,7 +110,7 @@ func gophorErrorToResponseCode(code ErrorCode) ErrorResponseCode {
|
|||||||
case DirListErr:
|
case DirListErr:
|
||||||
return ErrorResponse404
|
return ErrorResponse404
|
||||||
|
|
||||||
/* These are errors sending, no point trying to send error */
|
/* These are errors _while_ sending, no point trying to send error */
|
||||||
case SocketWriteErr:
|
case SocketWriteErr:
|
||||||
return NoResponse
|
return NoResponse
|
||||||
case SocketWriteCountErr:
|
case SocketWriteCountErr:
|
||||||
@ -129,6 +130,7 @@ func gophorErrorToResponseCode(code ErrorCode) ErrorResponseCode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generates gopher protocol compatible error response from our code */
|
||||||
func generateGopherErrorResponseFromCode(code ErrorCode) []byte {
|
func generateGopherErrorResponseFromCode(code ErrorCode) []byte {
|
||||||
responseCode := gophorErrorToResponseCode(code)
|
responseCode := gophorErrorToResponseCode(code)
|
||||||
if responseCode == NoResponse {
|
if responseCode == NoResponse {
|
||||||
@ -137,11 +139,13 @@ func generateGopherErrorResponseFromCode(code ErrorCode) []byte {
|
|||||||
return generateGopherErrorResponse(responseCode)
|
return generateGopherErrorResponse(responseCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generates gopher protocol compatible error response for response code */
|
||||||
func generateGopherErrorResponse(code ErrorResponseCode) []byte {
|
func generateGopherErrorResponse(code ErrorResponseCode) []byte {
|
||||||
b := buildError(code.String())
|
b := buildError(code.String())
|
||||||
return append(b, []byte(LastLine)...)
|
return append(b, []byte(LastLine)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Error response code to string */
|
||||||
func (e ErrorResponseCode) String() string {
|
func (e ErrorResponseCode) String() string {
|
||||||
switch e {
|
switch e {
|
||||||
case ErrorResponse200:
|
case ErrorResponse200:
|
||||||
|
@ -17,10 +17,14 @@ type RegularFileContents struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fc *RegularFileContents) Render(request *FileSystemRequest) []byte {
|
func (fc *RegularFileContents) Render(request *FileSystemRequest) []byte {
|
||||||
|
/* Here we can ignore the extra data in request.
|
||||||
|
* We are but a simple cache'd file
|
||||||
|
*/
|
||||||
return fc.contents
|
return fc.contents
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *RegularFileContents) Load() *GophorError {
|
func (fc *RegularFileContents) Load() *GophorError {
|
||||||
|
/* Load the file into memory */
|
||||||
var gophorErr *GophorError
|
var gophorErr *GophorError
|
||||||
fc.contents, gophorErr = bufferedRead(fc.path)
|
fc.contents, gophorErr = bufferedRead(fc.path)
|
||||||
return gophorErr
|
return gophorErr
|
||||||
@ -42,8 +46,10 @@ type GophermapContents struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GophermapContents) Render(request *FileSystemRequest) []byte {
|
func (gc *GophermapContents) Render(request *FileSystemRequest) []byte {
|
||||||
/* We don't just want to read the contents, but also
|
/* We don't just want to read the contents, each section
|
||||||
* execute any included gophermap execute lines
|
* in the sections slice needs a call to render() to
|
||||||
|
* perform their own required actions in producing a
|
||||||
|
* sendable byte slice.
|
||||||
*/
|
*/
|
||||||
returnContents := make([]byte, 0)
|
returnContents := make([]byte, 0)
|
||||||
for _, line := range gc.sections {
|
for _, line := range gc.sections {
|
||||||
@ -54,10 +60,14 @@ func (gc *GophermapContents) Render(request *FileSystemRequest) []byte {
|
|||||||
returnContents = append(returnContents, content...)
|
returnContents = append(returnContents, content...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Finally we end render with last line */
|
||||||
|
returnContents = append(returnContents, []byte(LastLine)...)
|
||||||
|
|
||||||
return returnContents
|
return returnContents
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GophermapContents) Load() *GophorError {
|
func (gc *GophermapContents) Load() *GophorError {
|
||||||
|
/* Load the gophermap into memory as gophermap sections */
|
||||||
var gophorErr *GophorError
|
var gophorErr *GophorError
|
||||||
gc.sections, gophorErr = readGophermap(gc.path)
|
gc.sections, gophorErr = readGophermap(gc.path)
|
||||||
return gophorErr
|
return gophorErr
|
||||||
@ -146,7 +156,7 @@ func readGophermap(path string) ([]GophermapSection, *GophorError) {
|
|||||||
sections = append(sections, NewGophermapText(buildInfoLine(line)))
|
sections = append(sections, NewGophermapText(buildInfoLine(line)))
|
||||||
|
|
||||||
case TypeTitle:
|
case TypeTitle:
|
||||||
/* Reformat title line to send as info title */
|
/* Reformat title line to send as info line with appropriate selector */
|
||||||
if !titleAlready {
|
if !titleAlready {
|
||||||
sections = append(sections, NewGophermapText(buildLine(TypeInfo, line[1:], "TITLE", NullHost, NullPort)))
|
sections = append(sections, NewGophermapText(buildLine(TypeInfo, line[1:], "TITLE", NullHost, NullPort)))
|
||||||
titleAlready = true
|
titleAlready = true
|
||||||
@ -207,9 +217,7 @@ func readGophermap(path string) ([]GophermapSection, *GophorError) {
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Replace pre-set strings */
|
/* Just append to sections slice as gophermap text */
|
||||||
line = strings.Replace(line, ReplaceStrHostname, Config.Hostname, -1)
|
|
||||||
line = strings.Replace(line, ReplaceStrPort, Config.Port, -1)
|
|
||||||
sections = append(sections, NewGophermapText([]byte(line+DOSLineEnd)))
|
sections = append(sections, NewGophermapText([]byte(line+DOSLineEnd)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +232,8 @@ func readGophermap(path string) ([]GophermapSection, *GophorError) {
|
|||||||
|
|
||||||
/* If dir listing requested, append the hidden files map then add
|
/* If dir listing requested, append the hidden files map then add
|
||||||
* to sections slice. We can do this here as the TypeEndBeginList item
|
* to sections slice. We can do this here as the TypeEndBeginList item
|
||||||
* type ALWAYS comes last, at least in the gophermap handled by this context.
|
* type ALWAYS comes last, at least in the gophermap handled by this call
|
||||||
|
* to readGophermap().
|
||||||
*/
|
*/
|
||||||
if dirListing != nil {
|
if dirListing != nil {
|
||||||
dirListing.Hidden = hidden
|
dirListing.Hidden = hidden
|
||||||
|
@ -4,10 +4,12 @@ import (
|
|||||||
"container/list"
|
"container/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* TODO: work on efficiency. use our own lower level data structure? */
|
||||||
|
|
||||||
/* FixedMap:
|
/* FixedMap:
|
||||||
* A fixed size map that pushes the last
|
* A fixed size map that pushes the last
|
||||||
* used value from the stack if size limit
|
* used value from the stack if size limit
|
||||||
* is reached and user attempts .Put()
|
* is reached.
|
||||||
*/
|
*/
|
||||||
type FixedMap struct {
|
type FixedMap struct {
|
||||||
Map map[string]*MapElement
|
Map map[string]*MapElement
|
||||||
@ -32,6 +34,7 @@ func NewFixedMap(size int) *FixedMap {
|
|||||||
return fm
|
return fm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get file in map for key, or nil */
|
||||||
func (fm *FixedMap) Get(key string) *File {
|
func (fm *FixedMap) Get(key string) *File {
|
||||||
elem, ok := fm.Map[key]
|
elem, ok := fm.Map[key]
|
||||||
if ok {
|
if ok {
|
||||||
@ -41,6 +44,8 @@ func (fm *FixedMap) Get(key string) *File {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Put file in map as key, pushing out last file
|
||||||
|
* if size limit reached */
|
||||||
func (fm *FixedMap) Put(key string, value *File) {
|
func (fm *FixedMap) Put(key string, value *File) {
|
||||||
element := fm.List.PushFront(key)
|
element := fm.List.PushFront(key)
|
||||||
fm.Map[key] = &MapElement{ element, value }
|
fm.Map[key] = &MapElement{ element, value }
|
||||||
@ -60,6 +65,7 @@ func (fm *FixedMap) Put(key string, value *File) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Try delete element, else do nothing */
|
||||||
func (fm *FixedMap) Remove(key string) {
|
func (fm *FixedMap) Remove(key string) {
|
||||||
elem, ok := fm.Map[key]
|
elem, ok := fm.Map[key]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
12
format.go
12
format.go
@ -72,12 +72,13 @@ func buildError(selector string) []byte {
|
|||||||
return []byte(ret)
|
return []byte(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build gopher compliant line with supplied information */
|
||||||
func buildLine(t ItemType, name, selector, host string, port string) []byte {
|
func buildLine(t ItemType, name, selector, host string, port string) []byte {
|
||||||
ret := string(t)
|
ret := string(t)
|
||||||
|
|
||||||
/* Add name, truncate name if too long */
|
/* Add name, truncate name if too long */
|
||||||
if len(name) > Config.PageWidth {
|
if len(name) > Config.PageWidth {
|
||||||
ret += name[:Config.PageWidth-4]+"...\t"
|
ret += name[:Config.PageWidth-5]+"...\t"
|
||||||
} else {
|
} else {
|
||||||
ret += name+"\t"
|
ret += name+"\t"
|
||||||
}
|
}
|
||||||
@ -96,16 +97,12 @@ func buildLine(t ItemType, name, selector, host string, port string) []byte {
|
|||||||
return []byte(ret)
|
return []byte(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Build gopher compliant info line */
|
||||||
func buildInfoLine(content string) []byte {
|
func buildInfoLine(content string) []byte {
|
||||||
return buildLine(TypeInfo, content, NullSelector, NullHost, NullPort)
|
return buildLine(TypeInfo, content, NullSelector, NullHost, NullPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* getItemType(name string) ItemType:
|
/* Get item type for named file on disk */
|
||||||
* Here we use an empty function pointer, and set the correct
|
|
||||||
* function to be used during the restricted files regex parsing.
|
|
||||||
* This negates need to check if RestrictedFilesRegex is nil every
|
|
||||||
* single call.
|
|
||||||
*/
|
|
||||||
func getItemType(name string) ItemType {
|
func getItemType(name string) ItemType {
|
||||||
/* Split, name MUST be lower */
|
/* Split, name MUST be lower */
|
||||||
split := strings.Split(strings.ToLower(name), ".")
|
split := strings.Split(strings.ToLower(name), ".")
|
||||||
@ -128,6 +125,7 @@ func getItemType(name string) ItemType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse line type from contents */
|
||||||
func parseLineType(line string) ItemType {
|
func parseLineType(line string) ItemType {
|
||||||
lineLen := len(line)
|
lineLen := len(line)
|
||||||
|
|
||||||
|
4
fs.go
4
fs.go
@ -107,6 +107,7 @@ type FileContents interface {
|
|||||||
Clear()
|
Clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform simple buffered read on a file at path */
|
||||||
func bufferedRead(path string) ([]byte, *GophorError) {
|
func bufferedRead(path string) ([]byte, *GophorError) {
|
||||||
/* Open file */
|
/* Open file */
|
||||||
fd, err := os.Open(path)
|
fd, err := os.Open(path)
|
||||||
@ -144,6 +145,7 @@ func bufferedRead(path string) ([]byte, *GophorError) {
|
|||||||
return contents, nil
|
return contents, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform buffered read on file at path, then scan through with supplied iterator func */
|
||||||
func bufferedScan(path string, scanIterator func(*bufio.Scanner) bool) *GophorError {
|
func bufferedScan(path string, scanIterator func(*bufio.Scanner) bool) *GophorError {
|
||||||
/* First, read raw file contents */
|
/* First, read raw file contents */
|
||||||
contents, gophorErr := bufferedRead(path)
|
contents, gophorErr := bufferedRead(path)
|
||||||
@ -155,7 +157,7 @@ func bufferedScan(path string, scanIterator func(*bufio.Scanner) bool) *GophorEr
|
|||||||
reader := bytes.NewReader(contents)
|
reader := bytes.NewReader(contents)
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
|
|
||||||
/* If contains DOS line-endings, use them! Else, Unix line-endings */
|
/* If contains DOS line-endings, split by DOS! Else, split by Unix */
|
||||||
if bytes.Contains(contents, []byte(DOSLineEnd)) {
|
if bytes.Contains(contents, []byte(DOSLineEnd)) {
|
||||||
scanner.Split(dosLineEndSplitter)
|
scanner.Split(dosLineEndSplitter)
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,8 +100,6 @@ func setupServer() []*GophorListener {
|
|||||||
/* Setup the server configuration instance and enter as much as we can right now */
|
/* Setup the server configuration instance and enter as much as we can right now */
|
||||||
Config = new(ServerConfig)
|
Config = new(ServerConfig)
|
||||||
Config.RootDir = *serverRoot
|
Config.RootDir = *serverRoot
|
||||||
Config.Hostname = *serverHostname
|
|
||||||
Config.Port = strconv.Itoa(*serverPort)
|
|
||||||
Config.Description = *serverDescription
|
Config.Description = *serverDescription
|
||||||
Config.AdminEmail = *serverAdmin
|
Config.AdminEmail = *serverAdmin
|
||||||
Config.Geolocation = *serverGeoloc
|
Config.Geolocation = *serverGeoloc
|
||||||
@ -143,13 +141,15 @@ func setupServer() []*GophorListener {
|
|||||||
listeners := make([]*GophorListener, 0)
|
listeners := make([]*GophorListener, 0)
|
||||||
|
|
||||||
/* If requested, setup unencrypted listener */
|
/* If requested, setup unencrypted listener */
|
||||||
if Config.Port != NullPort {
|
if *serverPort != 0 {
|
||||||
l, err := BeginGophorListen(*serverBindAddr, *serverHostname, Config.Port)
|
l, err := BeginGophorListen(*serverBindAddr, *serverHostname, strconv.Itoa(*serverPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Config.LogSystemFatal("Error setting up (unencrypted) listener: %s\n", err.Error())
|
Config.LogSystemFatal("Error setting up (unencrypted) listener: %s\n", err.Error())
|
||||||
}
|
}
|
||||||
Config.LogSystem("Listening (unencrypted): gopher://%s\n", l.Addr())
|
Config.LogSystem("Listening (unencrypted): gopher://%s\n", l.Addr())
|
||||||
listeners = append(listeners, l)
|
listeners = append(listeners, l)
|
||||||
|
} else {
|
||||||
|
Config.LogSystemFatal("No valid port to listen on :(\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Drop privileges to retrieved UID + GID */
|
/* Drop privileges to retrieved UID + GID */
|
||||||
|
12
html.go
12
html.go
@ -1,17 +1,5 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
/*
|
|
||||||
func generateHtmlErrorResponse(code ErrorResponseCode) []byte {
|
|
||||||
content :=
|
|
||||||
"<html>\n"+
|
|
||||||
"<body>\n"+
|
|
||||||
code.String()+"\n"+
|
|
||||||
"</body>\n"+
|
|
||||||
"</html>\n"
|
|
||||||
return generateHttpResponse(code, content)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func generateHtmlRedirect(url string) []byte {
|
func generateHtmlRedirect(url string) []byte {
|
||||||
content :=
|
content :=
|
||||||
"<html>\n"+
|
"<html>\n"+
|
||||||
|
3
regex.go
3
regex.go
@ -6,9 +6,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func compileUserRestrictedFilesRegex(restrictedFiles string) []*regexp.Regexp {
|
func compileUserRestrictedFilesRegex(restrictedFiles string) []*regexp.Regexp {
|
||||||
/* Try compiling the RestrictedFilesRegex from finalRegex */
|
|
||||||
Config.LogSystem("Compiling restricted file regular expressions\n")
|
Config.LogSystem("Compiling restricted file regular expressions\n")
|
||||||
|
|
||||||
|
/* Return slice */
|
||||||
restrictedFilesRegex := make([]*regexp.Regexp, 0)
|
restrictedFilesRegex := make([]*regexp.Regexp, 0)
|
||||||
|
|
||||||
/* Split the user supplied RestrictedFiles string by new-line */
|
/* Split the user supplied RestrictedFiles string by new-line */
|
||||||
@ -23,6 +23,7 @@ func compileUserRestrictedFilesRegex(restrictedFiles string) []*regexp.Regexp {
|
|||||||
return restrictedFilesRegex
|
return restrictedFilesRegex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Iterate through restricted file expressions, check if file _is_ restricted */
|
||||||
func isRestrictedFile(name string) bool {
|
func isRestrictedFile(name string) bool {
|
||||||
for _, regex := range Config.RestrictedFiles {
|
for _, regex := range Config.RestrictedFiles {
|
||||||
if regex.MatchString(name) {
|
if regex.MatchString(name) {
|
||||||
|
16
worker.go
16
worker.go
@ -42,7 +42,6 @@ func (worker *Worker) Serve() {
|
|||||||
buf := make([]byte, SocketReadBufSize)
|
buf := make([]byte, SocketReadBufSize)
|
||||||
received := make([]byte, 0)
|
received := make([]byte, 0)
|
||||||
|
|
||||||
/* Buffered read from listener */
|
|
||||||
iter := 0
|
iter := 0
|
||||||
for {
|
for {
|
||||||
/* Buffered read from listener */
|
/* Buffered read from listener */
|
||||||
@ -78,7 +77,7 @@ func (worker *Worker) Serve() {
|
|||||||
if gophorErr != nil {
|
if gophorErr != nil {
|
||||||
Config.LogSystemError("%s\n", gophorErr.Error())
|
Config.LogSystemError("%s\n", gophorErr.Error())
|
||||||
|
|
||||||
/* Try generate response bytes from error code */
|
/* Generate response bytes from error code */
|
||||||
response := generateGopherErrorResponseFromCode(gophorErr.Code)
|
response := generateGopherErrorResponseFromCode(gophorErr.Code)
|
||||||
|
|
||||||
/* If we got response bytes to send? SEND 'EM! */
|
/* If we got response bytes to send? SEND 'EM! */
|
||||||
@ -112,7 +111,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
|
|||||||
/* According to Gopher spec, only read up to first Tab or Crlf */
|
/* According to Gopher spec, only read up to first Tab or Crlf */
|
||||||
dataStr := readUpToFirstTabOrCrlf(data)
|
dataStr := readUpToFirstTabOrCrlf(data)
|
||||||
|
|
||||||
/* Handle URL request if so */
|
/* Handle URL request if so. TODO: this is so unelegant... */
|
||||||
lenBefore := len(dataStr)
|
lenBefore := len(dataStr)
|
||||||
dataStr = strings.TrimPrefix(dataStr, "URL:")
|
dataStr = strings.TrimPrefix(dataStr, "URL:")
|
||||||
switch len(dataStr) {
|
switch len(dataStr) {
|
||||||
@ -127,7 +126,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
|
|||||||
/* Sanitize supplied path */
|
/* Sanitize supplied path */
|
||||||
requestPath := sanitizePath(dataStr)
|
requestPath := sanitizePath(dataStr)
|
||||||
|
|
||||||
/* Handle policy files */
|
/* Handle policy files. TODO: this is so unelegant... */
|
||||||
switch requestPath {
|
switch requestPath {
|
||||||
case "/"+CapsTxtStr:
|
case "/"+CapsTxtStr:
|
||||||
return worker.SendRaw(generateCapsTxt())
|
return worker.SendRaw(generateCapsTxt())
|
||||||
@ -142,8 +141,9 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
|
|||||||
return &GophorError{ FileOpenErr, err }
|
return &GophorError{ FileOpenErr, err }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If not empty requestPath, check file type.
|
||||||
/* If not empty requestPath, check file type */
|
* Default type is directory.
|
||||||
|
*/
|
||||||
fileType := FileTypeDir
|
fileType := FileTypeDir
|
||||||
if requestPath != "." {
|
if requestPath != "." {
|
||||||
stat, err := file.Stat()
|
stat, err := file.Stat()
|
||||||
@ -164,9 +164,7 @@ func (worker *Worker) RespondGopher(data []byte) *GophorError {
|
|||||||
/* Don't need the file handle anymore */
|
/* Don't need the file handle anymore */
|
||||||
file.Close()
|
file.Close()
|
||||||
|
|
||||||
/* TODO: work on efficiency */
|
/* Handle file type. TODO: work on efficiency */
|
||||||
|
|
||||||
/* Handle file type */
|
|
||||||
response := make([]byte, 0)
|
response := make([]byte, 0)
|
||||||
switch fileType {
|
switch fileType {
|
||||||
/* Directory */
|
/* Directory */
|
||||||
|
Loading…
Reference in New Issue
Block a user