www.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package www
  2. import (
  3. "io/ioutil"
  4. "net/http"
  5. "net/url"
  6. "path/filepath"
  7. "strings"
  8. "imuslab.com/arozos/mod/database"
  9. "imuslab.com/arozos/mod/user"
  10. )
  11. /*
  12. www package
  13. This package is the replacement handler for global homepage function in ArozOS.
  14. This allow users to host and create their website using any folder within the user
  15. access file system.
  16. */
  17. type Options struct {
  18. UserHandler *user.UserHandler
  19. Database *database.Database
  20. }
  21. type Handler struct {
  22. Options Options
  23. }
  24. /*
  25. New WebRoot Handler create a new handler for handling and routing webroots
  26. */
  27. func NewWebRootHandler(options Options) *Handler {
  28. //Create the homepage database table
  29. options.Database.NewTable("www")
  30. //Return the handler object
  31. return &Handler{
  32. Options: options,
  33. }
  34. }
  35. func (h *Handler) RouteRequest(w http.ResponseWriter, r *http.Request) {
  36. //Check if it is reaching www root folder or any files directly under www.
  37. if filepath.ToSlash(filepath.Clean(r.URL.Path)) == "/www" {
  38. //Direct access of the root folder. Serve the homepage description.
  39. http.ServeFile(w, r, "web/SystemAO/www/index.html")
  40. return
  41. } else if filepath.ToSlash(filepath.Dir(r.URL.Path)) == "/www" {
  42. //Missing the last / at the end of the path
  43. r.URL.Path = r.URL.Path + "/"
  44. http.Redirect(w, r, filepath.ToSlash(filepath.Dir(r.URL.Path))+"/", http.StatusTemporaryRedirect)
  45. return
  46. }
  47. //Escape the URL
  48. decodedValue, err := url.QueryUnescape(r.URL.Path)
  49. if err != nil {
  50. //failed to decode. Just use its raw value
  51. decodedValue = r.URL.Path
  52. }
  53. //Check the user name of the user root
  54. parsedRequestURL := strings.Split(filepath.ToSlash(filepath.Clean(decodedValue)[1:]), "/")
  55. //Malparsed URL. Ignore request
  56. if len(parsedRequestURL) < 2 {
  57. http.NotFound(w, r)
  58. return
  59. }
  60. //Extract user information
  61. username := parsedRequestURL[1]
  62. userinfo, err := h.Options.UserHandler.GetUserInfoFromUsername(username)
  63. if err != nil {
  64. http.NotFound(w, r)
  65. return
  66. }
  67. //Check if this user enabled homepage
  68. enabled := h.CheckUserHomePageEnabled(userinfo.Username)
  69. if !enabled {
  70. w.WriteHeader(http.StatusNotFound)
  71. w.Write([]byte("404 - Page not found"))
  72. return
  73. }
  74. //Check if the user have his webroot correctly configured
  75. webroot, err := h.GetUserWebRoot(userinfo.Username)
  76. if err != nil {
  77. //User do not have a correctly configured webroot. Serve instruction
  78. w.WriteHeader(http.StatusInternalServerError)
  79. if fileExists("./system/www/nowebroot.html") {
  80. content, err := ioutil.ReadFile("./system/www/nowebroot.html")
  81. if err != nil {
  82. w.Write([]byte("500 - Internal Server Error"))
  83. } else {
  84. w.Write(content)
  85. }
  86. } else {
  87. w.Write([]byte("500 - Internal Server Error"))
  88. }
  89. return
  90. }
  91. //User webroot real path conversion
  92. webrootRealpath, err := userinfo.VirtualPathToRealPath(webroot)
  93. if err != nil {
  94. w.WriteHeader(http.StatusInternalServerError)
  95. w.Write([]byte("500 - Internal Server Error"))
  96. return
  97. }
  98. //Perform path rewrite
  99. rewrittenPath := strings.Join(parsedRequestURL[2:], "/")
  100. //Actual accessing file path
  101. targetFilePath := filepath.ToSlash(filepath.Join(webrootRealpath, rewrittenPath))
  102. //Check if the file exists
  103. if !fileExists(targetFilePath) {
  104. w.WriteHeader(http.StatusNotFound)
  105. w.Write([]byte("404 - Page not found"))
  106. return
  107. }
  108. //Fix mimetype of js files on Windows 10 bug
  109. if filepath.Ext(targetFilePath) == ".js" {
  110. w.Header().Set("Content-Type", "application/javascript")
  111. }
  112. //Record the client IP for analysis, to be added in the future if needed
  113. //Serve the file
  114. http.ServeFile(w, r, targetFilePath)
  115. }