YMhut Box
Unified management service is running.
package web import ( "bytes" "errors" "mime" "net/http" "os" "path/filepath" "strings" "time" webassets "ymhut-box/server/unified-management/web" ) func (r *router) handleDownload(w http.ResponseWriter, req *http.Request) { name := strings.TrimPrefix(cleanPath(req.URL.Path), "/downloads/") if name == "" || strings.Contains(name, "..") || strings.ContainsAny(name, `/\`) { writeError(w, http.StatusForbidden, "FORBIDDEN", errors.New("invalid filename")) return } path := filepath.Join(r.cfg.DownloadsDir, name) resolved, err := filepath.Abs(path) if err != nil { writeError(w, http.StatusInternalServerError, "PATH_FAILED", err) return } base, _ := filepath.Abs(r.cfg.DownloadsDir) if !strings.HasPrefix(resolved, base) { writeError(w, http.StatusForbidden, "FORBIDDEN", errors.New("path escape rejected")) return } http.ServeFile(w, req, resolved) } func serveStaticAsset(w http.ResponseWriter, req *http.Request, root, embedRoot, assetPath string) { if strings.Contains(assetPath, "..") || strings.ContainsAny(assetPath, `\`) { writeError(w, http.StatusForbidden, "FORBIDDEN", errors.New("invalid asset path")) return } if tryServeDiskFile(w, req, root, assetPath) { return } if serveEmbeddedFile(w, req, embedRoot+"/"+filepath.ToSlash(assetPath)) { return } http.NotFound(w, req) } func tryServeDiskFile(w http.ResponseWriter, req *http.Request, root, assetPath string) bool { path := filepath.Join(root, filepath.FromSlash(assetPath)) resolved, err := filepath.Abs(path) if err != nil { writeError(w, http.StatusInternalServerError, "PATH_FAILED", err) return true } base, _ := filepath.Abs(root) if resolved != base && !strings.HasPrefix(resolved, base+string(os.PathSeparator)) { writeError(w, http.StatusForbidden, "FORBIDDEN", errors.New("path escape rejected")) return true } info, err := os.Stat(resolved) if err != nil || info.IsDir() { return false } http.ServeFile(w, req, resolved) return true } func serveEmbeddedFile(w http.ResponseWriter, req *http.Request, name string) bool { if strings.Contains(name, "..") || strings.ContainsAny(name, `\`) { writeError(w, http.StatusForbidden, "FORBIDDEN", errors.New("invalid embedded asset path")) return true } data, err := webassets.ReadFile(name) if err != nil { return false } if contentType := mime.TypeByExtension(filepath.Ext(name)); contentType != "" { w.Header().Set("Content-Type", contentType) } http.ServeContent(w, req, filepath.Base(name), time.Time{}, bytes.NewReader(data)) return true } func (r *router) servePortal(w http.ResponseWriter, req *http.Request) { index := filepath.Join(r.cfg.PortalWebDir, "index.html") if _, err := os.Stat(index); err == nil { http.ServeFile(w, req, index) return } if serveEmbeddedFile(w, req, "portal/dist/index.html") { return } w.Header().Set("Content-Type", "text/html; charset=utf-8") _, _ = w.Write([]byte(`
Unified management service is running.
Build web/admin to enable the Vue console.