/
check.go
110 lines (99 loc) · 2.59 KB
/
check.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
// Package check provides request form checking.
package check
import (
"errors"
"fmt"
"io"
"mime/multipart"
"net/http"
"strings"
)
var errNoFileProvided = errors.New("check: no file provided")
// A Checker contains keys with their checking rules.
type Checker map[string][]Rule
// Check makes the check for a multipart.Form (values and files) and returns errors.
//
// Result is guaranteed to be non-nil.
func (c Checker) Check(form *multipart.Form) Errors {
errs := make(Errors)
for key, rules := range c {
for _, rule := range rules {
rule(errs, form, key)
}
}
return errs
}
// CheckValues makes the check for a values map (key to multiple values) and returns errors.
//
// Result is guaranteed to be non-nil.
func (c Checker) CheckValues(values map[string][]string) Errors {
return c.Check(&multipart.Form{Value: values})
}
// CheckFiles makes the check for a files map (key to multiple files) and returns errors.
//
// Result is guaranteed to be non-nil.
func (c Checker) CheckFiles(files map[string][]*multipart.FileHeader) Errors {
return c.Check(&multipart.Form{File: files})
}
// CheckRequest makes the check for an HTTP request and returns errors.
//
// Request data can have multiple values with the same key (or field).
// In this case, all values are checked and if one fails, the error is set for the whole key.
//
// Result is guaranteed to be non-nil.
func (c Checker) CheckRequest(r *http.Request) Errors {
if r.Form == nil {
r.ParseMultipartForm(32 << 20) // 32 MB
}
form := &multipart.Form{Value: r.Form}
if r.MultipartForm != nil {
if r.MultipartForm.Value != nil {
for k, v := range r.MultipartForm.Value {
form.Value[k] = append(form.Value[k], v...)
}
}
form.File = r.MultipartForm.File
}
return c.Check(form)
}
func fileType(file *multipart.FileHeader) (string, error) {
if file == nil {
return "", errNoFileProvided
}
f, err := file.Open()
if err != nil {
return "", err
}
defer f.Seek(0, io.SeekStart) // Reset reader.
fh := make([]byte, 512)
if _, err = f.Read(fh); err != nil {
return "", err
}
ct := http.DetectContentType(fh)
if i := strings.IndexByte(ct, ';'); i != -1 {
ct = ct[:i]
}
return ct, nil
}
func sliceContainsString(ss []string, s string) bool {
for _, e := range ss {
if s == e {
return true
}
}
return false
}
func stringsToInterfaces(ss []string) []interface{} {
ii := make([]interface{}, len(ss))
for i := 0; i < len(ss); i++ {
ii[i] = ss[i]
}
return ii
}
func interfacesToStrings(ii []interface{}) []string {
ss := make([]string, len(ii))
for i := 0; i < len(ii); i++ {
ss[i] = fmt.Sprint(ii[i])
}
return ss
}