aboutsummaryrefslogtreecommitdiff
path: root/pkg/util/fixWriter.go
blob: 51637ebe01444c73dfe767ba6741becce337694b (plain)
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
package util

import "io"

type fixWriter struct {
	w io.Writer
}

var lf = []byte{'\n'}
var cr = []byte{'\r'}

func (f fixWriter) Write(p []byte) (n int, err error) {
	crFound := false
	start := 0

	write := func(str []byte) {
		var j int
		j, err = f.w.Write(str)
		n = n + j
	}

	for idx, b := range p {
		if crFound && b != '\n' {
			// insert '\n'
			if write(p[start:idx]); err != nil {
				return
			}
			if write(lf); err != nil {
				return
			}

			start = idx
		} else if !crFound && b == '\n' {
			// insert '\r'
			if write(p[start:idx]); err != nil {
				return
			}
			if write(cr); err != nil {
				return
			}

			start = idx
		}
		crFound = b == '\r'
	}

	// write the remainder
	if write(p[start:]); err != nil {
		return
	}

	if crFound { // dangling \r
		write(lf)
	}

	return
}

// Cyrus IMAP really cares about single \r and \n.
// Implement this fixer to change them into \r\n.
func FixWriter(w io.Writer) io.Writer {
	return &fixWriter{w}
}