summaryrefslogtreecommitdiff
path: root/src/pkg/net/textproto
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/net/textproto')
-rw-r--r--src/pkg/net/textproto/Makefile15
-rw-r--r--src/pkg/net/textproto/header.go43
-rw-r--r--src/pkg/net/textproto/pipeline.go117
-rw-r--r--src/pkg/net/textproto/reader.go492
-rw-r--r--src/pkg/net/textproto/reader_test.go140
-rw-r--r--src/pkg/net/textproto/textproto.go121
-rw-r--r--src/pkg/net/textproto/writer.go119
-rw-r--r--src/pkg/net/textproto/writer_test.go35
8 files changed, 0 insertions, 1082 deletions
diff --git a/src/pkg/net/textproto/Makefile b/src/pkg/net/textproto/Makefile
deleted file mode 100644
index cadf3ab69..000000000
--- a/src/pkg/net/textproto/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# 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.
-
-include ../../../Make.inc
-
-TARG=net/textproto
-GOFILES=\
- header.go\
- pipeline.go\
- reader.go\
- textproto.go\
- writer.go\
-
-include ../../../Make.pkg
diff --git a/src/pkg/net/textproto/header.go b/src/pkg/net/textproto/header.go
deleted file mode 100644
index 288deb2ce..000000000
--- a/src/pkg/net/textproto/header.go
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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 textproto
-
-// A MIMEHeader represents a MIME-style header mapping
-// keys to sets of values.
-type MIMEHeader map[string][]string
-
-// Add adds the key, value pair to the header.
-// It appends to any existing values associated with key.
-func (h MIMEHeader) Add(key, value string) {
- key = CanonicalMIMEHeaderKey(key)
- h[key] = append(h[key], value)
-}
-
-// Set sets the header entries associated with key to
-// the single element value. It replaces any existing
-// values associated with key.
-func (h MIMEHeader) Set(key, value string) {
- h[CanonicalMIMEHeaderKey(key)] = []string{value}
-}
-
-// Get gets the first value associated with the given key.
-// If there are no values associated with the key, Get returns "".
-// Get is a convenience method. For more complex queries,
-// access the map directly.
-func (h MIMEHeader) Get(key string) string {
- if h == nil {
- return ""
- }
- v := h[CanonicalMIMEHeaderKey(key)]
- if len(v) == 0 {
- return ""
- }
- return v[0]
-}
-
-// Del deletes the values associated with key.
-func (h MIMEHeader) Del(key string) {
- h[CanonicalMIMEHeaderKey(key)] = nil, false
-}
diff --git a/src/pkg/net/textproto/pipeline.go b/src/pkg/net/textproto/pipeline.go
deleted file mode 100644
index 8c25884b3..000000000
--- a/src/pkg/net/textproto/pipeline.go
+++ /dev/null
@@ -1,117 +0,0 @@
-// 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 textproto
-
-import (
- "sync"
-)
-
-// A Pipeline manages a pipelined in-order request/response sequence.
-//
-// To use a Pipeline p to manage multiple clients on a connection,
-// each client should run:
-//
-// id := p.Next() // take a number
-//
-// p.StartRequest(id) // wait for turn to send request
-// «send request»
-// p.EndRequest(id) // notify Pipeline that request is sent
-//
-// p.StartResponse(id) // wait for turn to read response
-// «read response»
-// p.EndResponse(id) // notify Pipeline that response is read
-//
-// A pipelined server can use the same calls to ensure that
-// responses computed in parallel are written in the correct order.
-type Pipeline struct {
- mu sync.Mutex
- id uint
- request sequencer
- response sequencer
-}
-
-// Next returns the next id for a request/response pair.
-func (p *Pipeline) Next() uint {
- p.mu.Lock()
- id := p.id
- p.id++
- p.mu.Unlock()
- return id
-}
-
-// StartRequest blocks until it is time to send (or, if this is a server, receive)
-// the request with the given id.
-func (p *Pipeline) StartRequest(id uint) {
- p.request.Start(id)
-}
-
-// EndRequest notifies p that the request with the given id has been sent
-// (or, if this is a server, received).
-func (p *Pipeline) EndRequest(id uint) {
- p.request.End(id)
-}
-
-// StartResponse blocks until it is time to receive (or, if this is a server, send)
-// the request with the given id.
-func (p *Pipeline) StartResponse(id uint) {
- p.response.Start(id)
-}
-
-// EndResponse notifies p that the response with the given id has been received
-// (or, if this is a server, sent).
-func (p *Pipeline) EndResponse(id uint) {
- p.response.End(id)
-}
-
-// A sequencer schedules a sequence of numbered events that must
-// happen in order, one after the other. The event numbering must start
-// at 0 and increment without skipping. The event number wraps around
-// safely as long as there are not 2^32 simultaneous events pending.
-type sequencer struct {
- mu sync.Mutex
- id uint
- wait map[uint]chan uint
-}
-
-// Start waits until it is time for the event numbered id to begin.
-// That is, except for the first event, it waits until End(id-1) has
-// been called.
-func (s *sequencer) Start(id uint) {
- s.mu.Lock()
- if s.id == id {
- s.mu.Unlock()
- return
- }
- c := make(chan uint)
- if s.wait == nil {
- s.wait = make(map[uint]chan uint)
- }
- s.wait[id] = c
- s.mu.Unlock()
- <-c
-}
-
-// End notifies the sequencer that the event numbered id has completed,
-// allowing it to schedule the event numbered id+1. It is a run-time error
-// to call End with an id that is not the number of the active event.
-func (s *sequencer) End(id uint) {
- s.mu.Lock()
- if s.id != id {
- panic("out of sync")
- }
- id++
- s.id = id
- if s.wait == nil {
- s.wait = make(map[uint]chan uint)
- }
- c, ok := s.wait[id]
- if ok {
- s.wait[id] = nil, false
- }
- s.mu.Unlock()
- if ok {
- c <- 1
- }
-}
diff --git a/src/pkg/net/textproto/reader.go b/src/pkg/net/textproto/reader.go
deleted file mode 100644
index e65374903..000000000
--- a/src/pkg/net/textproto/reader.go
+++ /dev/null
@@ -1,492 +0,0 @@
-// 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 textproto
-
-import (
- "bufio"
- "bytes"
- "container/vector"
- "io"
- "io/ioutil"
- "os"
- "strconv"
-)
-
-// BUG(rsc): To let callers manage exposure to denial of service
-// attacks, Reader should allow them to set and reset a limit on
-// the number of bytes read from the connection.
-
-// A Reader implements convenience methods for reading requests
-// or responses from a text protocol network connection.
-type Reader struct {
- R *bufio.Reader
- dot *dotReader
-}
-
-// NewReader returns a new Reader reading from r.
-func NewReader(r *bufio.Reader) *Reader {
- return &Reader{R: r}
-}
-
-// ReadLine reads a single line from r,
-// eliding the final \n or \r\n from the returned string.
-func (r *Reader) ReadLine() (string, os.Error) {
- line, err := r.ReadLineBytes()
- return string(line), err
-}
-
-// ReadLineBytes is like ReadLine but returns a []byte instead of a string.
-func (r *Reader) ReadLineBytes() ([]byte, os.Error) {
- r.closeDot()
- line, err := r.R.ReadBytes('\n')
- n := len(line)
- if n > 0 && line[n-1] == '\n' {
- n--
- if n > 0 && line[n-1] == '\r' {
- n--
- }
- }
- return line[0:n], err
-}
-
-// ReadContinuedLine reads a possibly continued line from r,
-// eliding the final trailing ASCII white space.
-// Lines after the first are considered continuations if they
-// begin with a space or tab character. In the returned data,
-// continuation lines are separated from the previous line
-// only by a single space: the newline and leading white space
-// are removed.
-//
-// For example, consider this input:
-//
-// Line 1
-// continued...
-// Line 2
-//
-// The first call to ReadContinuedLine will return "Line 1 continued..."
-// and the second will return "Line 2".
-//
-// A line consisting of only white space is never continued.
-//
-func (r *Reader) ReadContinuedLine() (string, os.Error) {
- line, err := r.ReadContinuedLineBytes()
- return string(line), err
-}
-
-// trim returns s with leading and trailing spaces and tabs removed.
-// It does not assume Unicode or UTF-8.
-func trim(s []byte) []byte {
- i := 0
- for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
- i++
- }
- n := len(s)
- for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
- n--
- }
- return s[i:n]
-}
-
-// ReadContinuedLineBytes is like ReadContinuedLine but
-// returns a []byte instead of a string.
-func (r *Reader) ReadContinuedLineBytes() ([]byte, os.Error) {
- // Read the first line.
- line, err := r.ReadLineBytes()
- if err != nil {
- return line, err
- }
- if len(line) == 0 { // blank line - no continuation
- return line, nil
- }
- line = trim(line)
-
- // Look for a continuation line.
- c, err := r.R.ReadByte()
- if err != nil {
- // Delay err until we read the byte next time.
- return line, nil
- }
- if c != ' ' && c != '\t' {
- // Not a continuation.
- r.R.UnreadByte()
- return line, nil
- }
-
- // Read continuation lines.
- for {
- // Consume leading spaces; one already gone.
- for {
- c, err = r.R.ReadByte()
- if err != nil {
- break
- }
- if c != ' ' && c != '\t' {
- r.R.UnreadByte()
- break
- }
- }
- var cont []byte
- cont, err = r.ReadLineBytes()
- cont = trim(cont)
- line = append(line, ' ')
- line = append(line, cont...)
- if err != nil {
- break
- }
-
- // Check for leading space on next line.
- if c, err = r.R.ReadByte(); err != nil {
- break
- }
- if c != ' ' && c != '\t' {
- r.R.UnreadByte()
- break
- }
- }
-
- // Delay error until next call.
- if len(line) > 0 {
- err = nil
- }
- return line, err
-}
-
-func (r *Reader) readCodeLine(expectCode int) (code int, continued bool, message string, err os.Error) {
- line, err := r.ReadLine()
- if err != nil {
- return
- }
- if len(line) < 4 || line[3] != ' ' && line[3] != '-' {
- err = ProtocolError("short response: " + line)
- return
- }
- continued = line[3] == '-'
- code, err = strconv.Atoi(line[0:3])
- if err != nil || code < 100 {
- err = ProtocolError("invalid response code: " + line)
- return
- }
- message = line[4:]
- if 1 <= expectCode && expectCode < 10 && code/100 != expectCode ||
- 10 <= expectCode && expectCode < 100 && code/10 != expectCode ||
- 100 <= expectCode && expectCode < 1000 && code != expectCode {
- err = &Error{code, message}
- }
- return
-}
-
-// ReadCodeLine reads a response code line of the form
-// code message
-// where code is a 3-digit status code and the message
-// extends to the rest of the line. An example of such a line is:
-// 220 plan9.bell-labs.com ESMTP
-//
-// If the prefix of the status does not match the digits in expectCode,
-// ReadCodeLine returns with err set to &Error{code, message}.
-// For example, if expectCode is 31, an error will be returned if
-// the status is not in the range [310,319].
-//
-// If the response is multi-line, ReadCodeLine returns an error.
-//
-// An expectCode <= 0 disables the check of the status code.
-//
-func (r *Reader) ReadCodeLine(expectCode int) (code int, message string, err os.Error) {
- code, continued, message, err := r.readCodeLine(expectCode)
- if err == nil && continued {
- err = ProtocolError("unexpected multi-line response: " + message)
- }
- return
-}
-
-// ReadResponse reads a multi-line response of the form
-// code-message line 1
-// code-message line 2
-// ...
-// code message line n
-// where code is a 3-digit status code. Each line should have the same code.
-// The response is terminated by a line that uses a space between the code and
-// the message line rather than a dash. Each line in message is separated by
-// a newline (\n).
-//
-// If the prefix of the status does not match the digits in expectCode,
-// ReadResponse returns with err set to &Error{code, message}.
-// For example, if expectCode is 31, an error will be returned if
-// the status is not in the range [310,319].
-//
-// An expectCode <= 0 disables the check of the status code.
-//
-func (r *Reader) ReadResponse(expectCode int) (code int, message string, err os.Error) {
- code, continued, message, err := r.readCodeLine(expectCode)
- for err == nil && continued {
- var code2 int
- var moreMessage string
- code2, continued, moreMessage, err = r.readCodeLine(expectCode)
- if code != code2 {
- err = ProtocolError("status code mismatch: " + strconv.Itoa(code) + ", " + strconv.Itoa(code2))
- }
- message += "\n" + moreMessage
- }
- return
-}
-
-// DotReader returns a new Reader that satisfies Reads using the
-// decoded text of a dot-encoded block read from r.
-// The returned Reader is only valid until the next call
-// to a method on r.
-//
-// Dot encoding is a common framing used for data blocks
-// in text protocols such as SMTP. The data consists of a sequence
-// of lines, each of which ends in "\r\n". The sequence itself
-// ends at a line containing just a dot: ".\r\n". Lines beginning
-// with a dot are escaped with an additional dot to avoid
-// looking like the end of the sequence.
-//
-// The decoded form returned by the Reader's Read method
-// rewrites the "\r\n" line endings into the simpler "\n",
-// removes leading dot escapes if present, and stops with error os.EOF
-// after consuming (and discarding) the end-of-sequence line.
-func (r *Reader) DotReader() io.Reader {
- r.closeDot()
- r.dot = &dotReader{r: r}
- return r.dot
-}
-
-type dotReader struct {
- r *Reader
- state int
-}
-
-// Read satisfies reads by decoding dot-encoded data read from d.r.
-func (d *dotReader) Read(b []byte) (n int, err os.Error) {
- // Run data through a simple state machine to
- // elide leading dots, rewrite trailing \r\n into \n,
- // and detect ending .\r\n line.
- const (
- stateBeginLine = iota // beginning of line; initial state; must be zero
- stateDot // read . at beginning of line
- stateDotCR // read .\r at beginning of line
- stateCR // read \r (possibly at end of line)
- stateData // reading data in middle of line
- stateEOF // reached .\r\n end marker line
- )
- br := d.r.R
- for n < len(b) && d.state != stateEOF {
- var c byte
- c, err = br.ReadByte()
- if err != nil {
- if err == os.EOF {
- err = io.ErrUnexpectedEOF
- }
- break
- }
- switch d.state {
- case stateBeginLine:
- if c == '.' {
- d.state = stateDot
- continue
- }
- if c == '\r' {
- d.state = stateCR
- continue
- }
- d.state = stateData
-
- case stateDot:
- if c == '\r' {
- d.state = stateDotCR
- continue
- }
- if c == '\n' {
- d.state = stateEOF
- continue
- }
- d.state = stateData
-
- case stateDotCR:
- if c == '\n' {
- d.state = stateEOF
- continue
- }
- // Not part of .\r\n.
- // Consume leading dot and emit saved \r.
- br.UnreadByte()
- c = '\r'
- d.state = stateData
-
- case stateCR:
- if c == '\n' {
- d.state = stateBeginLine
- break
- }
- // Not part of \r\n. Emit saved \r
- br.UnreadByte()
- c = '\r'
- d.state = stateData
-
- case stateData:
- if c == '\r' {
- d.state = stateCR
- continue
- }
- if c == '\n' {
- d.state = stateBeginLine
- }
- }
- b[n] = c
- n++
- }
- if err == nil && d.state == stateEOF {
- err = os.EOF
- }
- if err != nil && d.r.dot == d {
- d.r.dot = nil
- }
- return
-}
-
-// closeDot drains the current DotReader if any,
-// making sure that it reads until the ending dot line.
-func (r *Reader) closeDot() {
- if r.dot == nil {
- return
- }
- buf := make([]byte, 128)
- for r.dot != nil {
- // When Read reaches EOF or an error,
- // it will set r.dot == nil.
- r.dot.Read(buf)
- }
-}
-
-// ReadDotBytes reads a dot-encoding and returns the decoded data.
-//
-// See the documentation for the DotReader method for details about dot-encoding.
-func (r *Reader) ReadDotBytes() ([]byte, os.Error) {
- return ioutil.ReadAll(r.DotReader())
-}
-
-// ReadDotLines reads a dot-encoding and returns a slice
-// containing the decoded lines, with the final \r\n or \n elided from each.
-//
-// See the documentation for the DotReader method for details about dot-encoding.
-func (r *Reader) ReadDotLines() ([]string, os.Error) {
- // We could use ReadDotBytes and then Split it,
- // but reading a line at a time avoids needing a
- // large contiguous block of memory and is simpler.
- var v vector.StringVector
- var err os.Error
- for {
- var line string
- line, err = r.ReadLine()
- if err != nil {
- if err == os.EOF {
- err = io.ErrUnexpectedEOF
- }
- break
- }
-
- // Dot by itself marks end; otherwise cut one dot.
- if len(line) > 0 && line[0] == '.' {
- if len(line) == 1 {
- break
- }
- line = line[1:]
- }
- v.Push(line)
- }
- return v, err
-}
-
-// ReadMIMEHeader reads a MIME-style header from r.
-// The header is a sequence of possibly continued Key: Value lines
-// ending in a blank line.
-// The returned map m maps CanonicalMIMEHeaderKey(key) to a
-// sequence of values in the same order encountered in the input.
-//
-// For example, consider this input:
-//
-// My-Key: Value 1
-// Long-Key: Even
-// Longer Value
-// My-Key: Value 2
-//
-// Given that input, ReadMIMEHeader returns the map:
-//
-// map[string][]string{
-// "My-Key": {"Value 1", "Value 2"},
-// "Long-Key": {"Even Longer Value"},
-// }
-//
-func (r *Reader) ReadMIMEHeader() (MIMEHeader, os.Error) {
- m := make(MIMEHeader)
- for {
- kv, err := r.ReadContinuedLineBytes()
- if len(kv) == 0 {
- return m, err
- }
-
- // Key ends at first colon; must not have spaces.
- i := bytes.IndexByte(kv, ':')
- if i < 0 || bytes.IndexByte(kv[0:i], ' ') >= 0 {
- return m, ProtocolError("malformed MIME header line: " + string(kv))
- }
- key := CanonicalMIMEHeaderKey(string(kv[0:i]))
-
- // Skip initial spaces in value.
- i++ // skip colon
- for i < len(kv) && (kv[i] == ' ' || kv[i] == '\t') {
- i++
- }
- value := string(kv[i:])
-
- v := vector.StringVector(m[key])
- v.Push(value)
- m[key] = v
-
- if err != nil {
- return m, err
- }
- }
- panic("unreachable")
-}
-
-// CanonicalMIMEHeaderKey returns the canonical format of the
-// MIME header key s. The canonicalization converts the first
-// letter and any letter following a hyphen to upper case;
-// the rest are converted to lowercase. For example, the
-// canonical key for "accept-encoding" is "Accept-Encoding".
-func CanonicalMIMEHeaderKey(s string) string {
- // Quick check for canonical encoding.
- needUpper := true
- for i := 0; i < len(s); i++ {
- c := s[i]
- if needUpper && 'a' <= c && c <= 'z' {
- goto MustRewrite
- }
- if !needUpper && 'A' <= c && c <= 'Z' {
- goto MustRewrite
- }
- needUpper = c == '-'
- }
- return s
-
-MustRewrite:
- // Canonicalize: first letter upper case
- // and upper case after each dash.
- // (Host, User-Agent, If-Modified-Since).
- // MIME headers are ASCII only, so no Unicode issues.
- a := []byte(s)
- upper := true
- for i, v := range a {
- if upper && 'a' <= v && v <= 'z' {
- a[i] = v + 'A' - 'a'
- }
- if !upper && 'A' <= v && v <= 'Z' {
- a[i] = v + 'a' - 'A'
- }
- upper = v == '-'
- }
- return string(a)
-}
diff --git a/src/pkg/net/textproto/reader_test.go b/src/pkg/net/textproto/reader_test.go
deleted file mode 100644
index 0658e58b8..000000000
--- a/src/pkg/net/textproto/reader_test.go
+++ /dev/null
@@ -1,140 +0,0 @@
-// 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 textproto
-
-import (
- "bufio"
- "io"
- "os"
- "reflect"
- "strings"
- "testing"
-)
-
-type canonicalHeaderKeyTest struct {
- in, out string
-}
-
-var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{
- {"a-b-c", "A-B-C"},
- {"a-1-c", "A-1-C"},
- {"User-Agent", "User-Agent"},
- {"uSER-aGENT", "User-Agent"},
- {"user-agent", "User-Agent"},
- {"USER-AGENT", "User-Agent"},
-}
-
-func TestCanonicalMIMEHeaderKey(t *testing.T) {
- for _, tt := range canonicalHeaderKeyTests {
- if s := CanonicalMIMEHeaderKey(tt.in); s != tt.out {
- t.Errorf("CanonicalMIMEHeaderKey(%q) = %q, want %q", tt.in, s, tt.out)
- }
- }
-}
-
-func reader(s string) *Reader {
- return NewReader(bufio.NewReader(strings.NewReader(s)))
-}
-
-func TestReadLine(t *testing.T) {
- r := reader("line1\nline2\n")
- s, err := r.ReadLine()
- if s != "line1" || err != nil {
- t.Fatalf("Line 1: %s, %v", s, err)
- }
- s, err = r.ReadLine()
- if s != "line2" || err != nil {
- t.Fatalf("Line 2: %s, %v", s, err)
- }
- s, err = r.ReadLine()
- if s != "" || err != os.EOF {
- t.Fatalf("EOF: %s, %v", s, err)
- }
-}
-
-func TestReadContinuedLine(t *testing.T) {
- r := reader("line1\nline\n 2\nline3\n")
- s, err := r.ReadContinuedLine()
- if s != "line1" || err != nil {
- t.Fatalf("Line 1: %s, %v", s, err)
- }
- s, err = r.ReadContinuedLine()
- if s != "line 2" || err != nil {
- t.Fatalf("Line 2: %s, %v", s, err)
- }
- s, err = r.ReadContinuedLine()
- if s != "line3" || err != nil {
- t.Fatalf("Line 3: %s, %v", s, err)
- }
- s, err = r.ReadContinuedLine()
- if s != "" || err != os.EOF {
- t.Fatalf("EOF: %s, %v", s, err)
- }
-}
-
-func TestReadCodeLine(t *testing.T) {
- r := reader("123 hi\n234 bye\n345 no way\n")
- code, msg, err := r.ReadCodeLine(0)
- if code != 123 || msg != "hi" || err != nil {
- t.Fatalf("Line 1: %d, %s, %v", code, msg, err)
- }
- code, msg, err = r.ReadCodeLine(23)
- if code != 234 || msg != "bye" || err != nil {
- t.Fatalf("Line 2: %d, %s, %v", code, msg, err)
- }
- code, msg, err = r.ReadCodeLine(346)
- if code != 345 || msg != "no way" || err == nil {
- t.Fatalf("Line 3: %d, %s, %v", code, msg, err)
- }
- if e, ok := err.(*Error); !ok || e.Code != code || e.Msg != msg {
- t.Fatalf("Line 3: wrong error %v\n", err)
- }
- code, msg, err = r.ReadCodeLine(1)
- if code != 0 || msg != "" || err != os.EOF {
- t.Fatalf("EOF: %d, %s, %v", code, msg, err)
- }
-}
-
-func TestReadDotLines(t *testing.T) {
- r := reader("dotlines\r\n.foo\r\n..bar\n...baz\nquux\r\n\r\n.\r\nanother\n")
- s, err := r.ReadDotLines()
- want := []string{"dotlines", "foo", ".bar", "..baz", "quux", ""}
- if !reflect.DeepEqual(s, want) || err != nil {
- t.Fatalf("ReadDotLines: %v, %v", s, err)
- }
-
- s, err = r.ReadDotLines()
- want = []string{"another"}
- if !reflect.DeepEqual(s, want) || err != io.ErrUnexpectedEOF {
- t.Fatalf("ReadDotLines2: %v, %v", s, err)
- }
-}
-
-func TestReadDotBytes(t *testing.T) {
- r := reader("dotlines\r\n.foo\r\n..bar\n...baz\nquux\r\n\r\n.\r\nanot.her\r\n")
- b, err := r.ReadDotBytes()
- want := []byte("dotlines\nfoo\n.bar\n..baz\nquux\n\n")
- if !reflect.DeepEqual(b, want) || err != nil {
- t.Fatalf("ReadDotBytes: %q, %v", b, err)
- }
-
- b, err = r.ReadDotBytes()
- want = []byte("anot.her\n")
- if !reflect.DeepEqual(b, want) || err != io.ErrUnexpectedEOF {
- t.Fatalf("ReadDotBytes2: %q, %v", b, err)
- }
-}
-
-func TestReadMIMEHeader(t *testing.T) {
- r := reader("my-key: Value 1 \r\nLong-key: Even \n Longer Value\r\nmy-Key: Value 2\r\n\n")
- m, err := r.ReadMIMEHeader()
- want := MIMEHeader{
- "My-Key": {"Value 1", "Value 2"},
- "Long-Key": {"Even Longer Value"},
- }
- if !reflect.DeepEqual(m, want) || err != nil {
- t.Fatalf("ReadMIMEHeader: %v, %v; want %v", m, err, want)
- }
-}
diff --git a/src/pkg/net/textproto/textproto.go b/src/pkg/net/textproto/textproto.go
deleted file mode 100644
index 9f19b5495..000000000
--- a/src/pkg/net/textproto/textproto.go
+++ /dev/null
@@ -1,121 +0,0 @@
-// 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 textproto implements generic support for text-based request/response
-// protocols in the style of HTTP, NNTP, and SMTP.
-//
-// The package provides:
-//
-// Error, which represents a numeric error response from
-// a server.
-//
-// Pipeline, to manage pipelined requests and responses
-// in a client.
-//
-// Reader, to read numeric response code lines,
-// key: value headers, lines wrapped with leading spaces
-// on continuation lines, and whole text blocks ending
-// with a dot on a line by itself.
-//
-// Writer, to write dot-encoded text blocks.
-//
-package textproto
-
-import (
- "bufio"
- "fmt"
- "io"
- "net"
- "os"
-)
-
-// An Error represents a numeric error response from a server.
-type Error struct {
- Code int
- Msg string
-}
-
-func (e *Error) String() string {
- return fmt.Sprintf("%03d %s", e.Code, e.Msg)
-}
-
-// A ProtocolError describes a protocol violation such
-// as an invalid response or a hung-up connection.
-type ProtocolError string
-
-func (p ProtocolError) String() string {
- return string(p)
-}
-
-// A Conn represents a textual network protocol connection.
-// It consists of a Reader and Writer to manage I/O
-// and a Pipeline to sequence concurrent requests on the connection.
-// These embedded types carry methods with them;
-// see the documentation of those types for details.
-type Conn struct {
- Reader
- Writer
- Pipeline
- conn io.ReadWriteCloser
-}
-
-// NewConn returns a new Conn using conn for I/O.
-func NewConn(conn io.ReadWriteCloser) *Conn {
- return &Conn{
- Reader: Reader{R: bufio.NewReader(conn)},
- Writer: Writer{W: bufio.NewWriter(conn)},
- conn: conn,
- }
-}
-
-// Close closes the connection.
-func (c *Conn) Close() os.Error {
- return c.conn.Close()
-}
-
-// Dial connects to the given address on the given network using net.Dial
-// and then returns a new Conn for the connection.
-func Dial(network, addr string) (*Conn, os.Error) {
- c, err := net.Dial(network, addr)
- if err != nil {
- return nil, err
- }
- return NewConn(c), nil
-}
-
-// Cmd is a convenience method that sends a command after
-// waiting its turn in the pipeline. The command text is the
-// result of formatting format with args and appending \r\n.
-// Cmd returns the id of the command, for use with StartResponse and EndResponse.
-//
-// For example, a client might run a HELP command that returns a dot-body
-// by using:
-//
-// id, err := c.Cmd("HELP")
-// if err != nil {
-// return nil, err
-// }
-//
-// c.StartResponse(id)
-// defer c.EndResponse(id)
-//
-// if _, _, err = c.ReadCodeLine(110); err != nil {
-// return nil, err
-// }
-// text, err := c.ReadDotAll()
-// if err != nil {
-// return nil, err
-// }
-// return c.ReadCodeLine(250)
-//
-func (c *Conn) Cmd(format string, args ...interface{}) (id uint, err os.Error) {
- id = c.Next()
- c.StartRequest(id)
- err = c.PrintfLine(format, args...)
- c.EndRequest(id)
- if err != nil {
- return 0, err
- }
- return id, nil
-}
diff --git a/src/pkg/net/textproto/writer.go b/src/pkg/net/textproto/writer.go
deleted file mode 100644
index 4e705f6c3..000000000
--- a/src/pkg/net/textproto/writer.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// 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 textproto
-
-import (
- "bufio"
- "fmt"
- "io"
- "os"
-)
-
-// A Writer implements convenience methods for writing
-// requests or responses to a text protocol network connection.
-type Writer struct {
- W *bufio.Writer
- dot *dotWriter
-}
-
-// NewWriter returns a new Writer writing to w.
-func NewWriter(w *bufio.Writer) *Writer {
- return &Writer{W: w}
-}
-
-var crnl = []byte{'\r', '\n'}
-var dotcrnl = []byte{'.', '\r', '\n'}
-
-// PrintfLine writes the formatted output followed by \r\n.
-func (w *Writer) PrintfLine(format string, args ...interface{}) os.Error {
- w.closeDot()
- fmt.Fprintf(w.W, format, args...)
- w.W.Write(crnl)
- return w.W.Flush()
-}
-
-// DotWriter returns a writer that can be used to write a dot-encoding to w.
-// It takes care of inserting leading dots when necessary,
-// translating line-ending \n into \r\n, and adding the final .\r\n line
-// when the DotWriter is closed. The caller should close the
-// DotWriter before the next call to a method on w.
-//
-// See the documentation for Reader's DotReader method for details about dot-encoding.
-func (w *Writer) DotWriter() io.WriteCloser {
- w.closeDot()
- w.dot = &dotWriter{w: w}
- return w.dot
-}
-
-func (w *Writer) closeDot() {
- if w.dot != nil {
- w.dot.Close() // sets w.dot = nil
- }
-}
-
-type dotWriter struct {
- w *Writer
- state int
-}
-
-const (
- wstateBeginLine = iota // beginning of line; initial state; must be zero
- wstateCR // wrote \r (possibly at end of line)
- wstateData // writing data in middle of line
-)
-
-func (d *dotWriter) Write(b []byte) (n int, err os.Error) {
- bw := d.w.W
- for n < len(b) {
- c := b[n]
- switch d.state {
- case wstateBeginLine:
- d.state = wstateData
- if c == '.' {
- // escape leading dot
- bw.WriteByte('.')
- }
- fallthrough
-
- case wstateData:
- if c == '\r' {
- d.state = wstateCR
- }
- if c == '\n' {
- bw.WriteByte('\r')
- d.state = wstateBeginLine
- }
-
- case wstateCR:
- d.state = wstateData
- if c == '\n' {
- d.state = wstateBeginLine
- }
- }
- if err = bw.WriteByte(c); err != nil {
- break
- }
- n++
- }
- return
-}
-
-func (d *dotWriter) Close() os.Error {
- if d.w.dot == d {
- d.w.dot = nil
- }
- bw := d.w.W
- switch d.state {
- default:
- bw.WriteByte('\r')
- fallthrough
- case wstateCR:
- bw.WriteByte('\n')
- fallthrough
- case wstateBeginLine:
- bw.Write(dotcrnl)
- }
- return bw.Flush()
-}
diff --git a/src/pkg/net/textproto/writer_test.go b/src/pkg/net/textproto/writer_test.go
deleted file mode 100644
index e03ab5e15..000000000
--- a/src/pkg/net/textproto/writer_test.go
+++ /dev/null
@@ -1,35 +0,0 @@
-// 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 textproto
-
-import (
- "bufio"
- "bytes"
- "testing"
-)
-
-func TestPrintfLine(t *testing.T) {
- var buf bytes.Buffer
- w := NewWriter(bufio.NewWriter(&buf))
- err := w.PrintfLine("foo %d", 123)
- if s := buf.String(); s != "foo 123\r\n" || err != nil {
- t.Fatalf("s=%q; err=%s", s, err)
- }
-}
-
-func TestDotWriter(t *testing.T) {
- var buf bytes.Buffer
- w := NewWriter(bufio.NewWriter(&buf))
- d := w.DotWriter()
- n, err := d.Write([]byte("abc\n.def\n..ghi\n.jkl\n."))
- if n != 21 || err != nil {
- t.Fatalf("Write: %d, %s", n, err)
- }
- d.Close()
- want := "abc\r\n..def\r\n...ghi\r\n..jkl\r\n..\r\n.\r\n"
- if s := buf.String(); s != want {
- t.Fatalf("wrote %q", s)
- }
-}