URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [mime/] [multipart/] [formdata.go] - Rev 747
Compare with Previous | Blame | View Log
// Copyright 2011 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package multipartimport ("bytes""errors""io""io/ioutil""net/textproto""os")// TODO(adg,bradfitz): find a way to unify the DoS-prevention strategy here// with that of the http package's ParseForm.// ReadForm parses an entire multipart message whose parts have// a Content-Disposition of "form-data".// It stores up to maxMemory bytes of the file parts in memory// and the remainder on disk in temporary files.func (r *Reader) ReadForm(maxMemory int64) (f *Form, err error) {form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}defer func() {if err != nil {form.RemoveAll()}}()maxValueBytes := int64(10 << 20) // 10 MB is a lot of text.for {p, err := r.NextPart()if err == io.EOF {break}if err != nil {return nil, err}name := p.FormName()if name == "" {continue}filename := p.FileName()var b bytes.Bufferif filename == "" {// value, store as string in memoryn, err := io.CopyN(&b, p, maxValueBytes)if err != nil && err != io.EOF {return nil, err}maxValueBytes -= nif maxValueBytes == 0 {return nil, errors.New("multipart: message too large")}form.Value[name] = append(form.Value[name], b.String())continue}// file, store in memory or on diskfh := &FileHeader{Filename: filename,Header: p.Header,}n, err := io.CopyN(&b, p, maxMemory+1)if err != nil && err != io.EOF {return nil, err}if n > maxMemory {// too big, write to disk and flush bufferfile, err := ioutil.TempFile("", "multipart-")if err != nil {return nil, err}defer file.Close()_, err = io.Copy(file, io.MultiReader(&b, p))if err != nil {os.Remove(file.Name())return nil, err}fh.tmpfile = file.Name()} else {fh.content = b.Bytes()maxMemory -= n}form.File[name] = append(form.File[name], fh)}return form, nil}// Form is a parsed multipart form.// Its File parts are stored either in memory or on disk,// and are accessible via the *FileHeader's Open method.// Its Value parts are stored as strings.// Both are keyed by field name.type Form struct {Value map[string][]stringFile map[string][]*FileHeader}// RemoveAll removes any temporary files associated with a Form.func (f *Form) RemoveAll() error {var err errorfor _, fhs := range f.File {for _, fh := range fhs {if fh.tmpfile != "" {e := os.Remove(fh.tmpfile)if e != nil && err == nil {err = e}}}}return err}// A FileHeader describes a file part of a multipart request.type FileHeader struct {Filename stringHeader textproto.MIMEHeadercontent []bytetmpfile string}// Open opens and returns the FileHeader's associated File.func (fh *FileHeader) Open() (File, error) {if b := fh.content; b != nil {r := io.NewSectionReader(sliceReaderAt(b), 0, int64(len(b)))return sectionReadCloser{r}, nil}return os.Open(fh.tmpfile)}// File is an interface to access the file part of a multipart message.// Its contents may be either stored in memory or on disk.// If stored on disk, the File's underlying concrete type will be an *os.File.type File interface {io.Readerio.ReaderAtio.Seekerio.Closer}// helper types to turn a []byte into a Filetype sectionReadCloser struct {*io.SectionReader}func (rc sectionReadCloser) Close() error {return nil}type sliceReaderAt []bytefunc (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {if int(off) >= len(r) || off < 0 {return 0, io.ErrUnexpectedEOF}n := copy(b, r[int(off):])return n, nil}
