SaveMultipartFile saves multipart file fh under the given filename path. The path is used as-is and must be a server-trusted destination filename. Do not pass the attacker-controlled fh.Filename directly without validating it and constraining it to the intended destination directory.
(fh *multipart.FileHeader, path string)
| 1164 | // Do not pass the attacker-controlled fh.Filename directly without validating |
| 1165 | // it and constraining it to the intended destination directory. |
| 1166 | func SaveMultipartFile(fh *multipart.FileHeader, path string) (err error) { |
| 1167 | var ( |
| 1168 | f multipart.File |
| 1169 | ff *os.File |
| 1170 | ) |
| 1171 | f, err = fh.Open() |
| 1172 | if err != nil { |
| 1173 | return err |
| 1174 | } |
| 1175 | |
| 1176 | var ok bool |
| 1177 | if ff, ok = f.(*os.File); ok { |
| 1178 | // Windows can't rename files that are opened. |
| 1179 | if err = f.Close(); err != nil { |
| 1180 | return err |
| 1181 | } |
| 1182 | |
| 1183 | // If renaming fails we try the normal copying method. |
| 1184 | // Renaming could fail if the files are on different devices. |
| 1185 | if os.Rename(ff.Name(), path) == nil { |
| 1186 | return nil |
| 1187 | } |
| 1188 | |
| 1189 | // Reopen f for the code below. |
| 1190 | if f, err = fh.Open(); err != nil { |
| 1191 | return err |
| 1192 | } |
| 1193 | } |
| 1194 | |
| 1195 | defer func() { |
| 1196 | e := f.Close() |
| 1197 | if err == nil { |
| 1198 | err = e |
| 1199 | } |
| 1200 | }() |
| 1201 | |
| 1202 | if ff, err = os.Create(path); err != nil { |
| 1203 | return err |
| 1204 | } |
| 1205 | defer func() { |
| 1206 | e := ff.Close() |
| 1207 | if err == nil { |
| 1208 | err = e |
| 1209 | } |
| 1210 | }() |
| 1211 | _, err = copyZeroAlloc(ff, f) |
| 1212 | return err |
| 1213 | } |
| 1214 | |
| 1215 | // FormValue returns form value associated with the given key. |
| 1216 | // |
searching dependent graphs…