diff --git a/main.go b/main.go index 6661b19..18d022b 100644 --- a/main.go +++ b/main.go @@ -107,8 +107,8 @@ func main() { // Serve static files (CSS, JS, etc.) from the /static directory http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir)))) - // Serve files in the /data/news/ directory under /news-assets/ - http.Handle("/news-assets/", http.StripPrefix("/news-assets/", http.FileServer(http.Dir(dataDir+"/news/")))) + // Custom handler to serve only directories and their contents under /news-assets/ + http.Handle("/news-assets/", http.StripPrefix("/news-assets/", http.HandlerFunc(serveDirectoriesOnly))) // Serve downloads.html at /downloads http.HandleFunc("/download", func(w http.ResponseWriter, r *http.Request) { @@ -433,6 +433,59 @@ func watchForChanges(dir string) { select {} } +// serveDirectoriesOnly handles requests and only serves directories and their contents. +func serveDirectoriesOnly(w http.ResponseWriter, r *http.Request) { + requestedPath := filepath.Join(dataDir, "news", r.URL.Path) + + // Check if the requested path is a directory + fileInfo, err := os.Stat(requestedPath) + if err != nil { + http.NotFound(w, r) // If the path doesn't exist, return a 404 + return + } + + // Block access to any files at the root level or the .git directory + if isRootLevel(requestedPath) || isRestrictedDirectory(requestedPath) { + http.NotFound(w, r) // Block access to root-level files like .md and the .git directory + return + } + + // Block access to any .md files at the root level + if isRootLevel(requestedPath) && strings.HasSuffix(requestedPath, ".md") { + http.NotFound(w, r) // Block access to root-level .md files + return + } + + // If the path is a directory, serve its contents + if fileInfo.IsDir() { + http.FileServer(http.Dir(requestedPath)).ServeHTTP(w, r) + return + } + + // Serve the file within the subdirectory + http.FileServer(http.Dir(filepath.Join(dataDir, "news"))).ServeHTTP(w, r) +} + +// isRootLevel checks if the file is at the root level of /news-assets/ +func isRootLevel(path string) bool { + relPath, err := filepath.Rel(filepath.Join(dataDir, "news"), path) + if err != nil { + return false + } + + // The relative path should not contain any slashes if it's at the root level + return !strings.Contains(relPath, string(os.PathSeparator)) +} + +// isRestrictedDirectory checks if the path is within a restricted directory like .git +func isRestrictedDirectory(path string) bool { + // Normalize the path + cleanPath := filepath.Clean(path) + + // Check if the path contains .git directory or other restricted directories + return strings.Contains(cleanPath, string(os.PathSeparator)+".git") || strings.HasSuffix(cleanPath, ".git") +} + func handleFileChange(path string, isNew bool) { if filepath.Ext(path) == ".md" { creationTimesM.Lock()