// 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"
	"regexp"
)

var headerRegexp *regexp.Regexp = regexp.MustCompile("^([a-zA-Z0-9\\-]+): *([^\r\n]+)")

var emptyParams = make(map[string]string)

// 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 interface {
	// NextPart returns the next part in the multipart or an error.
	// When there are no more parts, the error os.EOF is returned.
	NextPart() (*Part, os.Error)

	// 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.
	ReadForm(maxMemory int64) (*Form, os.Error)
}

// 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     *multiReader

	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")
	p.disposition, p.dispositionParams = mime.ParseMediaType(v)
	if p.dispositionParams == 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 &multiReader{
		bufReader: bufio.NewReader(reader),

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

// Implementation ....

func newPart(mr *multiReader) (*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 {
	for {
		lineBytes, err := bp.mr.bufReader.ReadSlice('\n')
		if err != nil {
			return err
		}
		line := string(lineBytes)
		if line == "\n" || line == "\r\n" {
			return nil
		}
		if matches := headerRegexp.FindStringSubmatch(line); len(matches) == 3 {
			bp.Header.Add(matches[1], matches[2])
			continue
		}
		return os.NewError("Unexpected header line found parsing multipart body")
	}
	panic("unreachable")
}

// 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
}

type multiReader struct {
	bufReader *bufio.Reader

	currentPart *Part
	partsRead   int

	nlDashBoundary, dashBoundaryDash, dashBoundary []byte
}

func (mr *multiReader) 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
		}

		if bytes.Equal(line, []byte("\r\n")) {
			// Consume the "\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)
			expectNewPart = true
			continue
		}

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

func (mr *multiReader) 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, []byte("\r\n")) {
		return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-2])
	}
	// Violate the spec and also support newlines without the
	// carriage return...
	if bytes.HasSuffix(line, []byte("\n")) {
		return onlyHorizontalWhitespace(line[len(mr.dashBoundary) : len(line)-1])
	}
	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, []byte("\r\n")))
}
