summaryrefslogtreecommitdiff
path: root/src/pkg/mime/multipart/writer.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/mime/multipart/writer.go')
-rw-r--r--src/pkg/mime/multipart/writer.go184
1 files changed, 0 insertions, 184 deletions
diff --git a/src/pkg/mime/multipart/writer.go b/src/pkg/mime/multipart/writer.go
deleted file mode 100644
index e13a956af..000000000
--- a/src/pkg/mime/multipart/writer.go
+++ /dev/null
@@ -1,184 +0,0 @@
-// 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 multipart
-
-import (
- "bytes"
- "crypto/rand"
- "errors"
- "fmt"
- "io"
- "net/textproto"
- "strings"
-)
-
-// A Writer generates multipart messages.
-type Writer struct {
- w io.Writer
- boundary string
- lastpart *part
-}
-
-// NewWriter returns a new multipart Writer with a random boundary,
-// writing to w.
-func NewWriter(w io.Writer) *Writer {
- return &Writer{
- w: w,
- boundary: randomBoundary(),
- }
-}
-
-// Boundary returns the Writer's boundary.
-func (w *Writer) Boundary() string {
- return w.boundary
-}
-
-// SetBoundary overrides the Writer's default randomly-generated
-// boundary separator with an explicit value.
-//
-// SetBoundary must be called before any parts are created, may only
-// contain certain ASCII characters, and must be 1-69 bytes long.
-func (w *Writer) SetBoundary(boundary string) error {
- if w.lastpart != nil {
- return errors.New("mime: SetBoundary called after write")
- }
- // rfc2046#section-5.1.1
- if len(boundary) < 1 || len(boundary) > 69 {
- return errors.New("mime: invalid boundary length")
- }
- for _, b := range boundary {
- if 'A' <= b && b <= 'Z' || 'a' <= b && b <= 'z' || '0' <= b && b <= '9' {
- continue
- }
- switch b {
- case '\'', '(', ')', '+', '_', ',', '-', '.', '/', ':', '=', '?':
- continue
- }
- return errors.New("mime: invalid boundary character")
- }
- w.boundary = boundary
- return nil
-}
-
-// FormDataContentType returns the Content-Type for an HTTP
-// multipart/form-data with this Writer's Boundary.
-func (w *Writer) FormDataContentType() string {
- return "multipart/form-data; boundary=" + w.boundary
-}
-
-func randomBoundary() string {
- var buf [30]byte
- _, err := io.ReadFull(rand.Reader, buf[:])
- if err != nil {
- panic(err)
- }
- return fmt.Sprintf("%x", buf[:])
-}
-
-// CreatePart creates a new multipart section with the provided
-// header. The body of the part should be written to the returned
-// Writer. After calling CreatePart, any previous part may no longer
-// be written to.
-func (w *Writer) CreatePart(header textproto.MIMEHeader) (io.Writer, error) {
- if w.lastpart != nil {
- if err := w.lastpart.close(); err != nil {
- return nil, err
- }
- }
- var b bytes.Buffer
- if w.lastpart != nil {
- fmt.Fprintf(&b, "\r\n--%s\r\n", w.boundary)
- } else {
- fmt.Fprintf(&b, "--%s\r\n", w.boundary)
- }
- // TODO(bradfitz): move this to textproto.MimeHeader.Write(w), have it sort
- // and clean, like http.Header.Write(w) does.
- for k, vv := range header {
- for _, v := range vv {
- fmt.Fprintf(&b, "%s: %s\r\n", k, v)
- }
- }
- fmt.Fprintf(&b, "\r\n")
- _, err := io.Copy(w.w, &b)
- if err != nil {
- return nil, err
- }
- p := &part{
- mw: w,
- }
- w.lastpart = p
- return p, nil
-}
-
-var quoteEscaper = strings.NewReplacer("\\", "\\\\", `"`, "\\\"")
-
-func escapeQuotes(s string) string {
- return quoteEscaper.Replace(s)
-}
-
-// CreateFormFile is a convenience wrapper around CreatePart. It creates
-// a new form-data header with the provided field name and file name.
-func (w *Writer) CreateFormFile(fieldname, filename string) (io.Writer, error) {
- h := make(textproto.MIMEHeader)
- h.Set("Content-Disposition",
- fmt.Sprintf(`form-data; name="%s"; filename="%s"`,
- escapeQuotes(fieldname), escapeQuotes(filename)))
- h.Set("Content-Type", "application/octet-stream")
- return w.CreatePart(h)
-}
-
-// CreateFormField calls CreatePart with a header using the
-// given field name.
-func (w *Writer) CreateFormField(fieldname string) (io.Writer, error) {
- h := make(textproto.MIMEHeader)
- h.Set("Content-Disposition",
- fmt.Sprintf(`form-data; name="%s"`, escapeQuotes(fieldname)))
- return w.CreatePart(h)
-}
-
-// WriteField calls CreateFormField and then writes the given value.
-func (w *Writer) WriteField(fieldname, value string) error {
- p, err := w.CreateFormField(fieldname)
- if err != nil {
- return err
- }
- _, err = p.Write([]byte(value))
- return err
-}
-
-// Close finishes the multipart message and writes the trailing
-// boundary end line to the output.
-func (w *Writer) Close() error {
- if w.lastpart != nil {
- if err := w.lastpart.close(); err != nil {
- return err
- }
- w.lastpart = nil
- }
- _, err := fmt.Fprintf(w.w, "\r\n--%s--\r\n", w.boundary)
- return err
-}
-
-type part struct {
- mw *Writer
- closed bool
- we error // last error that occurred writing
-}
-
-func (p *part) close() error {
- p.closed = true
- return p.we
-}
-
-func (p *part) Write(d []byte) (n int, err error) {
- if p.closed {
- return 0, errors.New("multipart: can't write to finished part")
- }
- n, err = p.mw.w.Write(d)
- if err != nil {
- p.we = err
- }
- return
-}