-
Notifications
You must be signed in to change notification settings - Fork 6
/
normalize.go
96 lines (86 loc) · 2.34 KB
/
normalize.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package dkim
import (
"regexp"
// "fmt"
"bytes"
"io"
"io/ioutil"
"os"
)
var nonnormalLineRE = regexp.MustCompile("([^\r]|^)\n")
// A normalizeReader wraps an io.Reader to normalize the line endings and
// encoding of a stream of bytes.
// It reads into a tempfile, which it deletes on close, so that it also
// implements the seek
type normalizeReader struct {
// The underlying reader
io.Reader
// Any leftover bytes after doing the normalization from the last
// call.
leftOver []byte
eof bool
unstuff bool
}
// If called, the reader will un dot-stuff lines that it reads.
func (n *normalizeReader) Unstuff() {
n.unstuff = true
}
func (n *normalizeReader) Read(r []byte) (int, error) {
var err error
// If there's already enough from the last read to fill this buffer,
// don't bother with the read.
if len(n.leftOver) < len(r)/2 {
// There wasn't enough data, so append it to the scratch
// buffer
var j int
j, err = n.Reader.Read(r)
n.leftOver = append(n.leftOver, r[:j]...)
if err == io.EOF {
//println("EOF")
n.eof = true
}
}
if len(n.leftOver) == 0 && n.eof {
return 0, io.EOF
}
// Replace all non-normalized lines remaining with \r\n
// n.leftOver = nonnormalLineRE.ReplaceAll(n.leftOver, []byte{'$', '1', '\r', '\n'})
n.leftOver = bytes.Replace(n.leftOver, []byte{'\r', '\n'}, []byte{'\n'}, -1)
n.leftOver = bytes.Replace(n.leftOver, []byte{'\r'}, []byte{'\n'}, -1)
n.leftOver = bytes.Replace(n.leftOver, []byte{'\n'}, []byte{'\r', '\n'}, -1)
if n.unstuff {
n.leftOver = bytes.Replace(n.leftOver, []byte{'\n', '.'}, []byte{'\n'}, -1)
}
// If there's up to len(r), fill up r and return the amount that
// was read.
if len(n.leftOver) <= len(r) {
size := len(n.leftOver)
for i := range n.leftOver {
r[i] = n.leftOver[i]
}
n.leftOver = nil
if n.eof {
return size, io.EOF
}
return size, err
}
// If there was more than len(r), fill up what we can and store
// the rest n.leftOver
for i := range r {
r[i] = n.leftOver[i]
}
n.leftOver = r[len(r):]
return len(r), err
}
func FileBuffer(r io.Reader) (*os.File, error) {
tempfile, err := ioutil.TempFile("", "readbuffer")
if err != nil {
return nil, err
}
_, err = io.Copy(tempfile, r)
tempfile.Seek(0, io.SeekStart)
return tempfile, err
}
func NormalizeReader(r io.Reader) *normalizeReader {
return &normalizeReader{r, nil, false, false}
}