diff --git a/general/logging/console.go b/general/logging/console.go new file mode 100644 index 0000000..595c73f --- /dev/null +++ b/general/logging/console.go @@ -0,0 +1,36 @@ +// Package logging handles the various mediums and logic of logging messages and reports. +package logging + +import ( + "log" + "strings" + + "github.com/Ennovar/gPanel/general/networking" +) + +const ( + PRIVATE_PREFIX string = "PRIVATE::" + PUBLIC_PREFIX string = "PUBLIC::" +) + +const ( + NORMAL_LOG int = 1 + FATAL_LOG int = 2 +) + +// Console logs a prefix, IP, and message all appeneded together to the console. +func Console(prefix string, logType int, msg string) { + rawClientIP, _ := networking.GetClientIP() + clientIP := strings.TrimSpace(string(rawClientIP)) + + msg = prefix + clientIP + "::" + msg + + switch logType { + default: + fallthrough + case 1: + log.Println(msg) + case 2: + log.Fatal(msg) + } +} diff --git a/general/logging/file.go b/general/logging/file.go new file mode 100644 index 0000000..e0c8217 --- /dev/null +++ b/general/logging/file.go @@ -0,0 +1,42 @@ +// Package logging handles the various mediums and logic of logging messages and reports. +package logging + +import "os" + +const ( + PRIVATE_LOG_FOLDER string = "logs/private/" + PUBLIC_LOG_FOLDER string = "logs/public/" +) + +const ( + ERROR string = "error.log" + WARNING string = "warning.log" +) + +// File logs a given message to a log file +func File(logFolder string, logFile string, msg string) (string, error) { + msg += "\n" + + f, err := os.OpenFile(logFolder+logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + + if err != nil { + return "", err + } else { + writtenBytes, err := f.Write([]byte(msg)) + + if err != nil { + return string(writtenBytes), err + } else { + err := f.Close() + + if err != nil { + return string(writtenBytes), err + } else { + return string(writtenBytes), nil + } + + } + + } + +} diff --git a/general/networking/ip_address.go b/general/networking/ip_address.go index 4c7396f..c0e7dad 100644 --- a/general/networking/ip_address.go +++ b/general/networking/ip_address.go @@ -1,3 +1,5 @@ +// Package networking contains various functions used to communicate between networks and +// draw data from the client network. package networking import ( @@ -5,16 +7,8 @@ import ( "net/http" ) -/* - A function to get the client IP - - @return []byte - The IP Address - @return error - If no error exists, the value is nil - - Known Problems: Uses an external API -*/ +// GetClientIP returns the current client's IP as an array of bytes. +// BUG(george-e-shaw-iv) Uses an external API func GetClientIP() ([]byte, error) { resp, err := http.Get("http://myexternalip.com/raw") diff --git a/general/routing/contentTypes.go b/general/routing/contentTypes.go new file mode 100644 index 0000000..4b8db09 --- /dev/null +++ b/general/routing/contentTypes.go @@ -0,0 +1,42 @@ +// Package routing contains various functions related to HTTP routing +package routing + +import ( + "errors" + "strings" +) + +// getContentType returns the http header safe content-type attribute for the +// requested path. If the requested path is not formatted correctly with an extension +// then the function will return the zero-value for a string and an error. +// BUG(george-e-shaw-iv) Cannot handle interpreted files such as .php files +// BUG(george-e-shaw-iv) Does not cover the bulk of encountered content types on the web +func GetContentType(path string) (string, error) { + var contentType string + splitPath := strings.Split(path, ".") + + if len(splitPath) == 1 && splitPath[0] == path { + return contentType, errors.New("Invalid path, contained no period-separated content-type") + } + + fileType := splitPath[len(splitPath)-1] + + switch fileType { + case "html": + contentType = "text/html" + case "css": + contentType = "text/css" + case "js": + contentType = "text/javascript" + case "png": + contentType = "image/png" + case "jpg": + fallthrough + case "jpeg": + contentType = "image/jpeg" + default: + contentType = "text/plain" + } + + return contentType, nil +} diff --git a/general/routing/http_status.go b/general/routing/http_status.go new file mode 100644 index 0000000..1bcddbc --- /dev/null +++ b/general/routing/http_status.go @@ -0,0 +1,9 @@ +// Package routing contains various functions related to HTTP routing +package routing + +import "net/http" + +func HttpThrowStatus(code int, context http.ResponseWriter) { + context.WriteHeader(code) + context.Write([]byte(http.StatusText(code))) +} diff --git a/main.go b/main.go index ef83cf0..cebc595 100644 --- a/main.go +++ b/main.go @@ -4,13 +4,13 @@ import ( "log" "net/http" - "github.com/Ennovar/gPanel/private_server/routing" - "github.com/Ennovar/gPanel/public_server/routing" + "github.com/Ennovar/gPanel/private_server" + "github.com/Ennovar/gPanel/public_server" ) func main() { - private := privateRouting.NewPrivateHost() - public := publicRouting.NewPublicWeb() + private := private_server.NewPrivateHost() + public := public_server.NewPublicWeb() log.Printf("To Exit: CTRL+C") diff --git a/private_server/logging/logging.go b/private_server/logging/logging.go deleted file mode 100644 index c9a7c2b..0000000 --- a/private_server/logging/logging.go +++ /dev/null @@ -1,91 +0,0 @@ -package privateLogging - -import ( - "log" - "os" - "strings" - - "github.com/Ennovar/gPanel/general/networking" -) - -const ( - CONSOLE_PREFIX string = "PRIVATE::" - LOG_FOLDER string = "logs/private/" -) - -/* - A function to log to the console - - @param logType int - The integer identifier cooresponding to the type of log. - The following integers are defined: - - 1: Normal (log.Println) - - 2: Fatal (log.Fatal) - @param msg string - The message to log - - @return bool - Dependant on whether or not logType was defined with a valid logType -*/ -func Console(logType int, msg string) bool { - rawClientIP, _ := networking.GetClientIP() - clientIP := strings.TrimSpace(string(rawClientIP)) - - msg = CONSOLE_PREFIX + clientIP + "::" + msg - - switch logType { - case 1: - log.Println(msg) - case 2: - log.Println(msg) - default: - return false - } - - return true -} - -/* - A function to log errors for the public server into files - - @param fileType int - The integer identifier cooresponding to the file to log to. - The following integers are defined: - - 1: error.log - - 2: warning.log - @param msg string - The message to log. - - @return bool - Dependant on whether or not fileType was defined with a valid fileType OR if file operations fail -*/ -func File(fileType int, msg string) bool { - msg += "\n" - fileName := LOG_FOLDER - - switch fileType { - case 1: - fileName += "error.log" - case 2: - fileName += "warning.log" - default: - return false - } - - f, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return false - } else { - _, err := f.Write([]byte(msg)) - if err != nil { - return false - } else { - err := f.Close() - if err != nil { - return false - } else { - return true - } - } - } -} diff --git a/private_server/private_server.go b/private_server/private_server.go new file mode 100644 index 0000000..ea6d296 --- /dev/null +++ b/private_server/private_server.go @@ -0,0 +1,58 @@ +// Package private_server handles the logic of the private_server +package private_server + +import ( + "bufio" + "net/http" + "os" + + "github.com/Ennovar/gPanel/general/logging" + "github.com/Ennovar/gPanel/general/routing" +) + +type privateHost struct { + Auth int + Directory string +} + +func NewPrivateHost() privateHost { + priv := privateHost{} + + priv.Auth = 1 // Handle Auth + priv.Directory = "private/" + + return priv +} + +func (priv *privateHost) ServeHTTP(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path[1:] + path = (priv.Directory + path) + + if priv.Auth != 1 { + routing.HttpThrowStatus(404, w) + logging.Console(logging.PRIVATE_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 401 error.") + } else { + f, err := os.Open(path) + + if err == nil { + bufferedReader := bufio.NewReader(f) + contentType, err := routing.GetContentType(path) + + if err == nil { + w.Header().Add("Content Type", contentType) + bufferedReader.WriteTo(w) + + logging.Console(logging.PRIVATE_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 200 success.") + } else { + routing.HttpThrowStatus(404, w) + logging.Console(logging.PRIVATE_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" content type could not be determined, 404 error.") + } + + } else { + routing.HttpThrowStatus(404, w) + logging.Console(logging.PRIVATE_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 404 error.") + } + + } + +} diff --git a/private_server/routing/routing.go b/private_server/routing/routing.go deleted file mode 100644 index c7c696f..0000000 --- a/private_server/routing/routing.go +++ /dev/null @@ -1,66 +0,0 @@ -package privateRouting - -import ( - "bufio" - "net/http" - "os" - "strings" - - "github.com/Ennovar/gPanel/private_server/logging" -) - -type privateHost struct { - Auth int - Directory string -} - -func NewPrivateHost() privateHost { - priv := privateHost{} - - priv.Auth = 1 // Handle Auth - priv.Directory = "private/" - - return priv -} - -func (priv *privateHost) ServeHTTP(w http.ResponseWriter, req *http.Request) { - path := req.URL.Path[1:] - path = (priv.Directory + path) - - if priv.Auth != 1 { - w.WriteHeader(401) - w.Write([]byte("401 - " + http.StatusText(401))) - - privateLogging.Console(2, "Path \""+path+"\" rendered a 401 error: "+http.StatusText(401)) - } else { - privateLogging.Console(1, path) - f, err := os.Open(path) - - if err == nil { - bufferedReader := bufio.NewReader(f) - var contentType string - - if strings.HasSuffix(path, ".html") { - contentType = "text/html" - } else if strings.HasSuffix(path, ".css") { - contentType = "text/css" - } else if strings.HasSuffix(path, ".js") { - contentType = "text/javascript" - } else if strings.HasSuffix(path, ".png") { - contentType = "image/png" - } else if strings.HasSuffix(path, ".jpg") || strings.HasSuffix(path, ".jpeg") { - contentType = "image/jpeg" - } else { - contentType = "text/plain" - } - - w.Header().Add("Content Type", contentType) - bufferedReader.WriteTo(w) - } else { - w.WriteHeader(404) - w.Write([]byte("404 - " + http.StatusText(404))) - - privateLogging.Console(2, "Path \""+path+"\" rendered a 404 error: "+http.StatusText(404)) - } - } -} diff --git a/public_server/logging/logging.go b/public_server/logging/logging.go deleted file mode 100644 index 1c9f73d..0000000 --- a/public_server/logging/logging.go +++ /dev/null @@ -1,91 +0,0 @@ -package publicLogging - -import ( - "log" - "os" - "strings" - - "github.com/Ennovar/gPanel/general/networking" -) - -const ( - CONSOLE_PREFIX string = "PUBLIC::" - LOG_FOLDER string = "logs/public/" -) - -/* - A function to log to the console - - @param logType int - The integer identifier cooresponding to the type of log. - The following integers are defined: - - 1: Normal (log.Println) - - 2: Fatal (log.Fatal) - @param msg string - The message to log - - @return bool - Dependant on whether or not logType was defined with a valid logType -*/ -func Console(logType int, msg string) bool { - rawClientIP, _ := networking.GetClientIP() - clientIP := strings.TrimSpace(string(rawClientIP)) - - msg = CONSOLE_PREFIX + clientIP + "::" + msg - - switch logType { - case 1: - log.Println(msg) - case 2: - log.Println(msg) - default: - return false - } - - return true -} - -/* - A function to log errors for the public server into files - - @param fileType int - The integer identifier cooresponding to the file to log to. - The following integers are defined: - - 1: error.log - - 2: warning.log - @param msg string - The message to log. - - @return bool - Dependant on whether or not fileType was defined with a valid fileType OR if file operations fail -*/ -func File(fileType int, msg string) bool { - msg += "\n" - fileName := LOG_FOLDER - - switch fileType { - case 1: - fileName += "error.log" - case 2: - fileName += "warning.log" - default: - return false - } - - f, err := os.OpenFile(fileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) - if err != nil { - return false - } else { - _, err := f.Write([]byte(msg)) - if err != nil { - return false - } else { - err := f.Close() - if err != nil { - return false - } else { - return true - } - } - } -} diff --git a/public_server/public_server.go b/public_server/public_server.go new file mode 100644 index 0000000..d918490 --- /dev/null +++ b/public_server/public_server.go @@ -0,0 +1,50 @@ +// Package public_server handles the logic of the public facing website +package public_server + +import ( + "bufio" + "net/http" + "os" + + "github.com/Ennovar/gPanel/general/logging" + "github.com/Ennovar/gPanel/general/routing" +) + +type publicWeb struct { + Directory string +} + +func NewPublicWeb() publicWeb { + pub := publicWeb{} + + pub.Directory = "public/" + + return pub +} + +func (pub *publicWeb) ServeHTTP(w http.ResponseWriter, req *http.Request) { + path := req.URL.Path[1:] + path = (pub.Directory + path) + + f, err := os.Open(path) + + if err == nil { + bufferedReader := bufio.NewReader(f) + contentType, err := routing.GetContentType(path) + + if err == nil { + w.Header().Add("Content Type", contentType) + bufferedReader.WriteTo(w) + + logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 200 success.") + } else { + routing.HttpThrowStatus(404, w) + logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" content type could not be determined, 404 error.") + } + + } else { + routing.HttpThrowStatus(404, w) + logging.Console(logging.PUBLIC_PREFIX, logging.NORMAL_LOG, "Path \""+path+"\" rendered a 404 error.") + } + +} diff --git a/public_server/routing/routing.go b/public_server/routing/routing.go deleted file mode 100644 index c72c61c..0000000 --- a/public_server/routing/routing.go +++ /dev/null @@ -1,57 +0,0 @@ -package publicRouting - -import ( - "bufio" - "net/http" - "os" - "strings" - - "github.com/Ennovar/gPanel/public_server/logging" -) - -type publicWeb struct { - Directory string -} - -func NewPublicWeb() publicWeb { - pub := publicWeb{} - - pub.Directory = "public/" - - return pub -} - -func (pub *publicWeb) ServeHTTP(w http.ResponseWriter, req *http.Request) { - path := req.URL.Path[1:] - path = (pub.Directory + path) - - publicLogging.Console(1, path) - f, err := os.Open(path) - - if err == nil { - bufferedReader := bufio.NewReader(f) - var contentType string - - if strings.HasSuffix(path, ".html") { - contentType = "text/html" - } else if strings.HasSuffix(path, ".css") { - contentType = "text/css" - } else if strings.HasSuffix(path, ".js") { - contentType = "text/javascript" - } else if strings.HasSuffix(path, ".png") { - contentType = "image/png" - } else if strings.HasSuffix(path, ".jpg") || strings.HasSuffix(path, ".jpeg") { - contentType = "image/jpeg" - } else { - contentType = "text/plain" - } - - w.Header().Add("Content Type", contentType) - bufferedReader.WriteTo(w) - } else { - w.WriteHeader(404) - w.Write([]byte("404 - " + http.StatusText(404))) - - publicLogging.Console(2, "Path \""+path+"\" rendered a 404 error: "+http.StatusText(404)) - } -}