@@ -11,6 +11,11 @@ import (
11
11
"strings"
12
12
)
13
13
14
+ type filedata struct {
15
+ Filename string
16
+ Data []byte
17
+ }
18
+
14
19
type Request struct {
15
20
Method string // GET, POST, PUT, etc.
16
21
RawURL string // The raw URL given in the request.
@@ -26,9 +31,10 @@ type Request struct {
26
31
UserAgent string
27
32
Params map [string ][]string
28
33
Cookies map [string ]string
29
- Files map [string ][] byte
34
+ Files map [string ]filedata
30
35
}
31
36
37
+
32
38
type badStringError struct {
33
39
what string
34
40
str string
@@ -147,22 +153,23 @@ func (r *Request) ParseParams() (err os.Error) {
147
153
}
148
154
query = string (b )
149
155
case "multipart/form-data" :
150
- r .Files = make (map [string ][] byte )
156
+ r .Files = make (map [string ]filedata )
151
157
boundary := strings .Split (ct , "boundary=" , 2 )[1 ]
152
158
var b []byte
153
159
if b , err = ioutil .ReadAll (r .Body ); err != nil {
154
160
return err
155
161
}
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 )
157
164
for _ , data := range (parts ) {
158
- if len (data ) == 0 {
165
+ if len (data ) < 2 {
159
166
continue
160
167
}
168
+ data = data [0 : len (data )- 2 ] // remove the \r\n
161
169
var line []byte
162
170
var rest = data
163
- headers := map [string ]string {}
164
- isfile := false
165
- var name string
171
+ //content-disposition params
172
+ cdparams := map [string ]string {}
166
173
for {
167
174
res := bytes .Split (rest , []byte {'\r' , '\n' }, 2 )
168
175
if len (res ) != 2 {
@@ -178,24 +185,31 @@ func (r *Request) ParseParams() (err os.Error) {
178
185
n := strings .TrimSpace (header [0 ])
179
186
v := strings .TrimSpace (header [1 ])
180
187
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
191
194
}
192
195
}
193
-
194
- headers [n ] = v
195
196
}
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 }
199
213
} else {
200
214
_ , ok := r .Params [name ]
201
215
if ! ok {
0 commit comments