OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [mime/] [multipart/] [formdata.go] - Blame information for rev 801

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2011 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
package multipart
6
 
7
import (
8
        "bytes"
9
        "errors"
10
        "io"
11
        "io/ioutil"
12
        "net/textproto"
13
        "os"
14
)
15
 
16
// TODO(adg,bradfitz): find a way to unify the DoS-prevention strategy here
17
// with that of the http package's ParseForm.
18
 
19
// ReadForm parses an entire multipart message whose parts have
20
// a Content-Disposition of "form-data".
21
// It stores up to maxMemory bytes of the file parts in memory
22
// and the remainder on disk in temporary files.
23
func (r *Reader) ReadForm(maxMemory int64) (f *Form, err error) {
24
        form := &Form{make(map[string][]string), make(map[string][]*FileHeader)}
25
        defer func() {
26
                if err != nil {
27
                        form.RemoveAll()
28
                }
29
        }()
30
 
31
        maxValueBytes := int64(10 << 20) // 10 MB is a lot of text.
32
        for {
33
                p, err := r.NextPart()
34
                if err == io.EOF {
35
                        break
36
                }
37
                if err != nil {
38
                        return nil, err
39
                }
40
 
41
                name := p.FormName()
42
                if name == "" {
43
                        continue
44
                }
45
                filename := p.FileName()
46
 
47
                var b bytes.Buffer
48
 
49
                if filename == "" {
50
                        // value, store as string in memory
51
                        n, err := io.CopyN(&b, p, maxValueBytes)
52
                        if err != nil && err != io.EOF {
53
                                return nil, err
54
                        }
55
                        maxValueBytes -= n
56
                        if maxValueBytes == 0 {
57
                                return nil, errors.New("multipart: message too large")
58
                        }
59
                        form.Value[name] = append(form.Value[name], b.String())
60
                        continue
61
                }
62
 
63
                // file, store in memory or on disk
64
                fh := &FileHeader{
65
                        Filename: filename,
66
                        Header:   p.Header,
67
                }
68
                n, err := io.CopyN(&b, p, maxMemory+1)
69
                if err != nil && err != io.EOF {
70
                        return nil, err
71
                }
72
                if n > maxMemory {
73
                        // too big, write to disk and flush buffer
74
                        file, err := ioutil.TempFile("", "multipart-")
75
                        if err != nil {
76
                                return nil, err
77
                        }
78
                        defer file.Close()
79
                        _, err = io.Copy(file, io.MultiReader(&b, p))
80
                        if err != nil {
81
                                os.Remove(file.Name())
82
                                return nil, err
83
                        }
84
                        fh.tmpfile = file.Name()
85
                } else {
86
                        fh.content = b.Bytes()
87
                        maxMemory -= n
88
                }
89
                form.File[name] = append(form.File[name], fh)
90
        }
91
 
92
        return form, nil
93
}
94
 
95
// Form is a parsed multipart form.
96
// Its File parts are stored either in memory or on disk,
97
// and are accessible via the *FileHeader's Open method.
98
// Its Value parts are stored as strings.
99
// Both are keyed by field name.
100
type Form struct {
101
        Value map[string][]string
102
        File  map[string][]*FileHeader
103
}
104
 
105
// RemoveAll removes any temporary files associated with a Form.
106
func (f *Form) RemoveAll() error {
107
        var err error
108
        for _, fhs := range f.File {
109
                for _, fh := range fhs {
110
                        if fh.tmpfile != "" {
111
                                e := os.Remove(fh.tmpfile)
112
                                if e != nil && err == nil {
113
                                        err = e
114
                                }
115
                        }
116
                }
117
        }
118
        return err
119
}
120
 
121
// A FileHeader describes a file part of a multipart request.
122
type FileHeader struct {
123
        Filename string
124
        Header   textproto.MIMEHeader
125
 
126
        content []byte
127
        tmpfile string
128
}
129
 
130
// Open opens and returns the FileHeader's associated File.
131
func (fh *FileHeader) Open() (File, error) {
132
        if b := fh.content; b != nil {
133
                r := io.NewSectionReader(sliceReaderAt(b), 0, int64(len(b)))
134
                return sectionReadCloser{r}, nil
135
        }
136
        return os.Open(fh.tmpfile)
137
}
138
 
139
// File is an interface to access the file part of a multipart message.
140
// Its contents may be either stored in memory or on disk.
141
// If stored on disk, the File's underlying concrete type will be an *os.File.
142
type File interface {
143
        io.Reader
144
        io.ReaderAt
145
        io.Seeker
146
        io.Closer
147
}
148
 
149
// helper types to turn a []byte into a File
150
 
151
type sectionReadCloser struct {
152
        *io.SectionReader
153
}
154
 
155
func (rc sectionReadCloser) Close() error {
156
        return nil
157
}
158
 
159
type sliceReaderAt []byte
160
 
161
func (r sliceReaderAt) ReadAt(b []byte, off int64) (int, error) {
162
        if int(off) >= len(r) || off < 0 {
163
                return 0, io.ErrUnexpectedEOF
164
        }
165
        n := copy(b, r[int(off):])
166
        return n, nil
167
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.