Skip to content

Commit 7b4829b

Browse files
author
Michael Hoisie
committed
Updates to multipart encoding
1 parent 6069c74 commit 7b4829b

File tree

1 file changed

+36
-22
lines changed

1 file changed

+36
-22
lines changed

request.go

+36-22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ import (
1111
"strings"
1212
)
1313

14+
type filedata struct {
15+
Filename string
16+
Data []byte
17+
}
18+
1419
type Request struct {
1520
Method string // GET, POST, PUT, etc.
1621
RawURL string // The raw URL given in the request.
@@ -26,9 +31,10 @@ type Request struct {
2631
UserAgent string
2732
Params map[string][]string
2833
Cookies map[string]string
29-
Files map[string][]byte
34+
Files map[string]filedata
3035
}
3136

37+
3238
type badStringError struct {
3339
what string
3440
str string
@@ -147,22 +153,23 @@ func (r *Request) ParseParams() (err os.Error) {
147153
}
148154
query = string(b)
149155
case "multipart/form-data":
150-
r.Files = make(map[string][]byte)
156+
r.Files = make(map[string]filedata)
151157
boundary := strings.Split(ct, "boundary=", 2)[1]
152158
var b []byte
153159
if b, err = ioutil.ReadAll(r.Body); err != nil {
154160
return err
155161
}
156-
parts := bytes.Split(b, strings.Bytes("--"+boundary+"\r\n"), 0)
162+
parts := bytes.Split(b, strings.Bytes("--"+boundary+"--\r\n"), 0)
163+
parts = bytes.Split(parts[0], strings.Bytes("--"+boundary+"\r\n"), 0)
157164
for _, data := range (parts) {
158-
if len(data) == 0 {
165+
if len(data) < 2 {
159166
continue
160167
}
168+
data = data[0 : len(data)-2] // remove the \r\n
161169
var line []byte
162170
var rest = data
163-
headers := map[string]string{}
164-
isfile := false
165-
var name string
171+
//content-disposition params
172+
cdparams := map[string]string{}
166173
for {
167174
res := bytes.Split(rest, []byte{'\r', '\n'}, 2)
168175
if len(res) != 2 {
@@ -178,24 +185,31 @@ func (r *Request) ParseParams() (err os.Error) {
178185
n := strings.TrimSpace(header[0])
179186
v := strings.TrimSpace(header[1])
180187
if n == "Content-Disposition" {
181-
parts := strings.Split(v, ";", 0)
182-
for _, parm := range (parts[1:]) {
183-
pp := strings.Split(parm, "=", 2)
184-
pn := strings.TrimSpace(pp[0])
185-
pv := strings.TrimSpace(pp[1])
186-
if pn == "name" {
187-
name = pv[1 : len(pv)-1]
188-
} else if pn == "filename" {
189-
isfile = true
190-
}
188+
cdparts := strings.Split(v, ";", 0)
189+
for _, cdparam := range (cdparts[1:]) {
190+
split := strings.Split(cdparam, "=", 2)
191+
pname := strings.TrimSpace(split[0])
192+
pval := strings.TrimSpace(split[1])
193+
cdparams[pname] = pval
191194
}
192195
}
193-
194-
headers[n] = v
195196
}
196-
if isfile {
197-
parts = bytes.Split(rest, strings.Bytes("\r\n--"+boundary+"--\r\n"), 0)
198-
r.Files[name] = parts[0]
197+
//if the param doesn't have a name, ignore it
198+
if _, ok := cdparams["name"]; !ok {
199+
continue
200+
}
201+
name := cdparams["name"]
202+
//check if name is quoted
203+
if strings.HasPrefix(name, `"`) {
204+
name = name[1 : len(name)-1]
205+
}
206+
207+
//if it's a file, store it in the Files member
208+
if filename, ok := cdparams["filename"]; ok {
209+
if strings.HasPrefix(filename, `"`) {
210+
filename = filename[1 : len(filename)-1]
211+
}
212+
r.Files[name] = filedata{filename, rest}
199213
} else {
200214
_, ok := r.Params[name]
201215
if !ok {

0 commit comments

Comments
 (0)