~john-koepi/ubuntu/trusty/golang/default

« back to all changes in this revision

Viewing changes to src/pkg/mime/multipart/multipart.go

  • Committer: Bazaar Package Importer
  • Author(s): Ondřej Surý
  • Date: 2011-08-03 17:04:59 UTC
  • mfrom: (14.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110803170459-wzd99m3567y80ila
Tags: 1:59-1
* Imported Upstream version 59
* Refresh patches to a new release
* Fix FTBFS on ARM (Closes: #634270)
* Update version.bash to work with Debian packaging and not hg
  repository

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
        "regexp"
25
25
)
26
26
 
 
27
// TODO(bradfitz): inline these once the compiler can inline them in
 
28
// read-only situation (such as bytes.HasSuffix)
 
29
var lf = []byte("\n")
 
30
var crlf = []byte("\r\n")
 
31
 
27
32
var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")
28
33
 
29
34
var emptyParams = make(map[string]string)
30
35
 
31
 
// Reader is an iterator over parts in a MIME multipart body.
32
 
// Reader's underlying parser consumes its input as needed.  Seeking
33
 
// isn't supported.
34
 
type Reader interface {
35
 
        // NextPart returns the next part in the multipart or an error.
36
 
        // When there are no more parts, the error os.EOF is returned.
37
 
        NextPart() (*Part, os.Error)
38
 
 
39
 
        // ReadForm parses an entire multipart message whose parts have
40
 
        // a Content-Disposition of "form-data".
41
 
        // It stores up to maxMemory bytes of the file parts in memory
42
 
        // and the remainder on disk in temporary files.
43
 
        ReadForm(maxMemory int64) (*Form, os.Error)
44
 
}
45
 
 
46
36
// A Part represents a single part in a multipart body.
47
37
type Part struct {
48
38
        // The headers of the body, if any, with the keys canonicalized
51
41
        Header textproto.MIMEHeader
52
42
 
53
43
        buffer *bytes.Buffer
54
 
        mr     *multiReader
 
44
        mr     *Reader
55
45
 
56
46
        disposition       string
57
47
        dispositionParams map[string]string
91
81
 
92
82
// NewReader creates a new multipart Reader reading from r using the
93
83
// given MIME boundary.
94
 
func NewReader(reader io.Reader, boundary string) Reader {
 
84
func NewReader(reader io.Reader, boundary string) *Reader {
95
85
        b := []byte("\r\n--" + boundary + "--")
96
 
        return &multiReader{
 
86
        return &Reader{
97
87
                bufReader: bufio.NewReader(reader),
98
88
 
 
89
                nl:               b[:2],
99
90
                nlDashBoundary:   b[:len(b)-2],
100
91
                dashBoundaryDash: b[2:],
101
92
                dashBoundary:     b[2 : len(b)-2],
102
93
        }
103
94
}
104
95
 
105
 
// Implementation ....
106
 
 
107
 
func newPart(mr *multiReader) (*Part, os.Error) {
 
96
func newPart(mr *Reader) (*Part, os.Error) {
108
97
        bp := &Part{
109
98
                Header: make(map[string][]string),
110
99
                mr:     mr,
188
177
        return nil
189
178
}
190
179
 
191
 
type multiReader struct {
 
180
// Reader is an iterator over parts in a MIME multipart body.
 
181
// Reader's underlying parser consumes its input as needed.  Seeking
 
182
// isn't supported.
 
183
type Reader struct {
192
184
        bufReader *bufio.Reader
193
185
 
194
186
        currentPart *Part
195
187
        partsRead   int
196
188
 
197
 
        nlDashBoundary, dashBoundaryDash, dashBoundary []byte
 
189
        nl, nlDashBoundary, dashBoundaryDash, dashBoundary []byte
198
190
}
199
191
 
200
 
func (mr *multiReader) NextPart() (*Part, os.Error) {
 
192
// NextPart returns the next part in the multipart or an error.
 
193
// When there are no more parts, the error os.EOF is returned.
 
194
func (mr *Reader) NextPart() (*Part, os.Error) {
201
195
        if mr.currentPart != nil {
202
196
                mr.currentPart.Close()
203
197
        }
233
227
                        continue
234
228
                }
235
229
 
236
 
                if bytes.Equal(line, []byte("\r\n")) {
237
 
                        // Consume the "\r\n" separator between the
238
 
                        // body of the previous part and the boundary
239
 
                        // line we now expect will follow. (either a
240
 
                        // new part or the end boundary)
 
230
                // Consume the "\n" or "\r\n" separator between the
 
231
                // body of the previous part and the boundary line we
 
232
                // now expect will follow. (either a new part or the
 
233
                // end boundary)
 
234
                if bytes.Equal(line, mr.nl) {
241
235
                        expectNewPart = true
242
236
                        continue
243
237
                }
247
241
        panic("unreachable")
248
242
}
249
243
 
250
 
func (mr *multiReader) isBoundaryDelimiterLine(line []byte) bool {
 
244
func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
251
245
        // http://tools.ietf.org/html/rfc2046#section-5.1
252
246
        //   The boundary delimiter line is then defined as a line
253
247
        //   consisting entirely of two hyphen characters ("-",
257
251
        if !bytes.HasPrefix(line, mr.dashBoundary) {
258
252
                return false
259
253
        }
260
 
        if bytes.HasSuffix(line, []byte("\r\n")) {
261
 
                return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-2])
 
254
        if bytes.HasSuffix(line, mr.nl) {
 
255
                return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-len(mr.nl)])
262
256
        }
263
257
        // Violate the spec and also support newlines without the
264
258
        // carriage return...
265
 
        if bytes.HasSuffix(line, []byte("\n")) {
266
 
                return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1])
 
259
        if mr.partsRead == 0 && bytes.HasSuffix(line, lf) {
 
260
                if onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1]) {
 
261
                        mr.nl = mr.nl[1:]
 
262
                        mr.nlDashBoundary = mr.nlDashBoundary[1:]
 
263
                        return true
 
264
                }
267
265
        }
268
266
        return false
269
267
}
280
278
func hasPrefixThenNewline(s, prefix []byte) bool {
281
279
        return bytes.HasPrefix(s, prefix) &&
282
280
                (len(s) == len(prefix)+1 && s[len(s)-1] == '\n' ||
283
 
                        len(s) == len(prefix)+2 && bytes.HasSuffix(s, []byte("\r\n")))
 
281
                        len(s) == len(prefix)+2 && bytes.HasSuffix(s, crlf))
284
282
}