| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 | package wwwimport (	"io/ioutil"	"net/http"	"net/url"	"path/filepath"	"strings"	"imuslab.com/arozos/mod/database"	"imuslab.com/arozos/mod/user")/*	www package	This package is the replacement handler for global homepage function in ArozOS.	This allow users to host and create their website using any folder within the user	access file system.*/type Options struct {	UserHandler *user.UserHandler	Database    *database.Database}type Handler struct {	Options Options}/*	New WebRoot Handler create a new handler for handling and routing webroots*/func NewWebRootHandler(options Options) *Handler {	//Create the homepage database table	options.Database.NewTable("www")	//Return the handler object	return &Handler{		Options: options,	}}func (h *Handler) RouteRequest(w http.ResponseWriter, r *http.Request) {	//Check if it is reaching www root folder or any files directly under www.	if filepath.ToSlash(filepath.Clean(r.URL.Path)) == "/www" {		//Direct access of the root folder. Serve the homepage description.		http.ServeFile(w, r, "web/SystemAO/www/index.html")		return	} else if filepath.ToSlash(filepath.Dir(r.URL.Path)) == "/www" {		//Missing the last / at the end of the path		r.URL.Path = r.URL.Path + "/"		http.Redirect(w, r, filepath.ToSlash(filepath.Dir(r.URL.Path))+"/", http.StatusTemporaryRedirect)		return	}	//Escape the URL	decodedValue, err := url.QueryUnescape(r.URL.Path)	if err != nil {		//failed to decode. Just use its raw value		decodedValue = r.URL.Path	}	//Check the user name of the user root	parsedRequestURL := strings.Split(filepath.ToSlash(filepath.Clean(decodedValue)[1:]), "/")	//Malparsed URL. Ignore request	if len(parsedRequestURL) < 2 {		http.NotFound(w, r)		return	}	//Extract user information	username := parsedRequestURL[1]	userinfo, err := h.Options.UserHandler.GetUserInfoFromUsername(username)	if err != nil {		http.NotFound(w, r)		return	}	//Check if this user enabled homepage	enabled := h.CheckUserHomePageEnabled(userinfo.Username)	if !enabled {		w.WriteHeader(http.StatusNotFound)		w.Write([]byte("404 - Page not found"))		return	}	//Check if the user have his webroot correctly configured	webroot, err := h.GetUserWebRoot(userinfo.Username)	if err != nil {		//User do not have a correctly configured webroot. Serve instruction		w.WriteHeader(http.StatusInternalServerError)		if fileExists("./system/www/nowebroot.html") {			content, err := ioutil.ReadFile("./system/www/nowebroot.html")			if err != nil {				w.Write([]byte("500 - Internal Server Error"))			} else {				w.Write(content)			}		} else {			w.Write([]byte("500 - Internal Server Error"))		}		return	}	//User webroot real path conversion	webrootRealpath, err := userinfo.VirtualPathToRealPath(webroot)	if err != nil {		w.WriteHeader(http.StatusInternalServerError)		w.Write([]byte("500 - Internal Server Error"))		return	}	//Perform path rewrite	rewrittenPath := strings.Join(parsedRequestURL[2:], "/")	//Actual accessing file path	targetFilePath := filepath.ToSlash(filepath.Join(webrootRealpath, rewrittenPath))	//Check if the file exists	if !fileExists(targetFilePath) {		w.WriteHeader(http.StatusNotFound)		w.Write([]byte("404 - Page not found"))		return	}	//Fix mimetype of js files on Windows 10 bug	if filepath.Ext(targetFilePath) == ".js" {		w.Header().Set("Content-Type", "application/javascript")	}	//Record the client IP for analysis, to be added in the future if needed	//Serve the file	http.ServeFile(w, r, targetFilePath)}
 |