// Copyright 2010 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 implements MIME multipart parsing, as defined in RFC
2046.

The implementation is sufficient for HTTP (RFC 2388) and the multipart
bodies generated by popular browsers.
*/
package multipart

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime"
	"net/textproto"
	"os"
)

// TODO(bradfitz): inline these once the compiler can inline them in
// read-only situation (such as bytes.HasSuffix)
var lf = []byte("\n")
var crlf = []byte("\r\n")

var emptyParams = make(map[string]string)

// A Part represents a single part in a multipart body.
type Part struct {
	// The headers of the body, if any, with the keys canonicalized
	// in the same fashion that the Go http.Request headers are.
	// i.e. "foo-bar" changes case to "Foo-Bar"
	Header textproto.MIMEHeader

	buffer *bytes.Buffer
	mr     *Reader

	disposition       string
	dispositionParams map[string]string
}

// FormName returns the name parameter if p has a Content-Disposition
// of type "form-data".  Otherwise it returns the empty string.
func (p *Part) FormName() string {
	// See http://tools.ietf.org/html/rfc2183 section 2 for EBNF
	// of Content-Disposition value format.
	if p.dispositionParams == nil {
		p.parseContentDisposition()
	}
	if p.disposition != "form-data" {
		return ""
	}
	return p.dispositionParams["name"]
}

// FileName returns the filename parameter of the Part's
// Content-Disposition header.
func (p *Part) FileName() string {
	if p.dispositionParams == nil {
		p.parseContentDisposition()
	}
	return p.dispositionParams["filename"]
}

func (p *Part) parseContentDisposition() {
	v := p.Header.Get("Content-Disposition")
	var err os.Error
	p.disposition, p.dispositionParams, err = mime.ParseMediaType(v)
	if err != nil {
		p.dispositionParams = emptyParams
	}
}

// NewReader creates a new multipart Reader reading from r using the
// given MIME boundary.
func NewReader(reader io.Reader, boundary string) *Reader {
	b := []byte("\r\n--" + boundary + "--")
	return &Reader{
		bufReader: bufio.NewReader(reader),

		nl:               b[:2],
		nlDashBoundary:   b[:len(b)-2],
		dashBoundaryDash: b[2:],
		dashBoundary:     b[2 : len(b)-2],
	}
}

func newPart(mr *Reader) (*Part, os.Error) {
	bp := &Part{
		Header: make(map[string][]string),
		mr:     mr,
		buffer: new(bytes.Buffer),
	}
	if err := bp.populateHeaders(); err != nil {
		return nil, err
	}
	return bp, nil
}

func (bp *Part) populateHeaders() os.Error {
	r := textproto.NewReader(bp.mr.bufReader)
	header, err := r.ReadMIMEHeader()
	if err == nil {
		bp.Header = header
	}
	return err
}

// Read reads the body of a part, after its headers and before the
// next part (if any) begins.
func (bp *Part) Read(p []byte) (n int, err os.Error) {
	if bp.buffer.Len() >= len(p) {
		// Internal buffer of unconsumed data is large enough for
		// the read request.  No need to parse more at the moment.
		return bp.buffer.Read(p)
	}
	peek, err := bp.mr.bufReader.Peek(4096) // TODO(bradfitz): add buffer size accessor
	unexpectedEof := err == os.EOF
	if err != nil && !unexpectedEof {
		return 0, fmt.Errorf("multipart: Part Read: %v", err)
	}
	if peek == nil {
		panic("nil peek buf")
	}

	// Search the peek buffer for "\r\n--boundary". If found,
	// consume everything up to the boundary. If not, consume only
	// as much of the peek buffer as cannot hold the boundary
	// string.
	nCopy := 0
	foundBoundary := false
	if idx := bytes.Index(peek, bp.mr.nlDashBoundary); idx != -1 {
		nCopy = idx
		foundBoundary = true
	} else if safeCount := len(peek) - len(bp.mr.nlDashBoundary); safeCount > 0 {
		nCopy = safeCount
	} else if unexpectedEof {
		// If we've run out of peek buffer and the boundary
		// wasn't found (and can't possibly fit), we must have
		// hit the end of the file unexpectedly.
		return 0, io.ErrUnexpectedEOF
	}
	if nCopy > 0 {
		if _, err := io.CopyN(bp.buffer, bp.mr.bufReader, int64(nCopy)); err != nil {
			return 0, err
		}
	}
	n, err = bp.buffer.Read(p)
	if err == os.EOF && !foundBoundary {
		// If the boundary hasn't been reached there's more to
		// read, so don't pass through an EOF from the buffer
		err = nil
	}
	return
}

func (bp *Part) Close() os.Error {
	io.Copy(ioutil.Discard, bp)
	return nil
}

// Reader is an iterator over parts in a MIME multipart body.
// Reader's underlying parser consumes its input as needed.  Seeking
// isn't supported.
type Reader struct {
	bufReader *bufio.Reader

	currentPart *Part
	partsRead   int

	nl, nlDashBoundary, dashBoundaryDash, dashBoundary []byte
}

// NextPart returns the next part in the multipart or an error.
// When there are no more parts, the error os.EOF is returned.
func (mr *Reader) NextPart() (*Part, os.Error) {
	if mr.currentPart != nil {
		mr.currentPart.Close()
	}

	expectNewPart := false
	for {
		line, err := mr.bufReader.ReadSlice('\n')
		if err != nil {
			return nil, fmt.Errorf("multipart: NextPart: %v", err)
		}

		if mr.isBoundaryDelimiterLine(line) {
			mr.partsRead++
			bp, err := newPart(mr)
			if err != nil {
				return nil, err
			}
			mr.currentPart = bp
			return bp, nil
		}

		if hasPrefixThenNewline(line, mr.dashBoundaryDash) {
			// Expected EOF
			return nil, os.EOF
		}

		if expectNewPart {
			return nil, fmt.Errorf("multipart: expecting a new Part; got line %q", string(line))
		}

		if mr.partsRead == 0 {
			// skip line
			continue
		}

		// Consume the "\n" or "\r\n" separator between the
		// body of the previous part and the boundary line we
		// now expect will follow. (either a new part or the
		// end boundary)
		if bytes.Equal(line, mr.nl) {
			expectNewPart = true
			continue
		}

		return nil, fmt.Errorf("multipart: unexpected line in Next(): %q", line)
	}
	panic("unreachable")
}

func (mr *Reader) isBoundaryDelimiterLine(line []byte) bool {
	// http://tools.ietf.org/html/rfc2046#section-5.1
	//   The boundary delimiter line is then defined as a line
	//   consisting entirely of two hyphen characters ("-",
	//   decimal value 45) followed by the boundary parameter
	//   value from the Content-Type header field, optional linear
	//   whitespace, and a terminating CRLF.
	if !bytes.HasPrefix(line, mr.dashBoundary) {
		return false
	}
	if bytes.HasSuffix(line, mr.nl) {
		return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-len(mr.nl)])
	}
	// Violate the spec and also support newlines without the
	// carriage return...
	if mr.partsRead == 0 && bytes.HasSuffix(line, lf) {
		if onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1]) {
			mr.nl = mr.nl[1:]
			mr.nlDashBoundary = mr.nlDashBoundary[1:]
			return true
		}
	}
	return false
}

func onlyHorizontalWhitespace(s []byte) bool {
	for _, b := range s {
		if b != ' ' && b != '\t' {
			return false
		}
	}
	return true
}

func hasPrefixThenNewline(s, prefix []byte) bool {
	return bytes.HasPrefix(s, prefix) &&
		(len(s) == len(prefix)+1 && s[len(s)-1] == '\n' ||
			len(s) == len(prefix)+2 && bytes.HasSuffix(s, crlf))
}
