-
Notifications
You must be signed in to change notification settings - Fork 2
/
handlers_file.go
137 lines (118 loc) · 3.63 KB
/
handlers_file.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"fmt"
"github.com/mdbot/wiki/markdown"
"io"
"log"
"mime"
"net/http"
"path/filepath"
"strings"
)
type FileLister interface {
ListFiles() ([]File, error)
}
func ListFilesHandler(t *Templates, fl FileLister) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
files, err := fl.ListFiles()
if err != nil {
log.Printf("Failed to list files: %v\n", err)
w.WriteHeader(http.StatusInternalServerError)
return
}
t.RenderFileList(w, r, files)
}
}
type FileStore interface {
PutFile(name string, content io.ReadCloser, user string, message string) error
}
func UploadHandler(store FileStore) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
if err := request.ParseMultipartForm(1 << 30); err != nil {
log.Printf("Upload failed: couldn't parse multipart data: %v", err)
writer.WriteHeader(http.StatusBadRequest)
return
}
file, _, err := request.FormFile("file")
if err != nil {
log.Printf("Upload failed: couldn't read file: %v", err)
writer.WriteHeader(http.StatusBadRequest)
return
}
name := request.FormValue("name")
if name == "" || !strings.ContainsRune(name, '.') {
log.Printf("Upload failed: invalid file name specified: %v", name)
writer.WriteHeader(http.StatusBadRequest)
return
}
message := request.FormValue("message")
username := "Anonymoose"
if user := getUserForRequest(request); user != nil {
username = user.Name
}
if err := store.PutFile(name, file, username, message); err != nil {
log.Printf("Upload failed: couldn't save file: %v", err)
writer.WriteHeader(http.StatusInternalServerError)
return
}
writer.WriteHeader(http.StatusNoContent)
}
}
func UploadFormHandler(t *Templates) http.HandlerFunc {
return t.RenderUploadForm
}
type FileProvider interface {
GetFile(name string) (io.ReadCloser, error)
}
func FileHandler(provider FileProvider) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
name := strings.TrimPrefix(request.URL.Path, "/files/view/")
reader, err := provider.GetFile(name)
if err != nil {
writer.WriteHeader(http.StatusNotFound)
return
}
defer reader.Close()
mimeType := mime.TypeByExtension(filepath.Ext(name))
if mimeType == "" {
mimeType = "application/octet-stream"
}
writer.Header().Add("Content-Type", mimeType)
writer.Header().Add("X-Content-Type-Options", "nosniff")
if !markdown.CanEmbed(mimeType) {
writer.Header().Add("Content-Disposition", "attachment")
}
_, _ = io.Copy(writer, reader)
}
}
type DeleteFileProvider interface {
DeleteFile(name string, message string, user string) error
}
func DeleteFileConfirmHandler(t *Templates) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
name := strings.TrimPrefix(r.URL.Path, "/files/delete/")
t.RenderDeleteFile(w, r, name)
}
}
func DeleteFileHandler(provider DeleteFileProvider) http.HandlerFunc {
return func(writer http.ResponseWriter, request *http.Request) {
name := strings.TrimPrefix(request.URL.Path, "/files/delete/")
confirm := request.FormValue("confirm")
if confirm == "" {
http.Redirect(writer, request, "/files/delete/"+name, http.StatusSeeOther)
return
}
message := request.FormValue("message")
username := "Anonymoose"
if user := getUserForRequest(request); user != nil {
username = user.Name
}
err := provider.DeleteFile(name, message, username)
if err != nil {
writer.WriteHeader(http.StatusInternalServerError)
return
}
putSessionKey(writer, request, sessionNoticeKey, fmt.Sprintf("Deleted file %s", name))
http.Redirect(writer, request, "/", http.StatusSeeOther)
}
}