diff --git a/vcf2fritzbox.go b/vcf2fritzbox.go index 30b53e4..49a897c 100644 --- a/vcf2fritzbox.go +++ b/vcf2fritzbox.go @@ -1,6 +1,7 @@ package main import ( + "bufio" "encoding/xml" "fmt" "io" @@ -11,10 +12,6 @@ import ( "time" ) -func complain(s string) { - fmt.Fprintln(os.Stderr, s) -} - func optExit(err error) { if err != nil { fmt.Fprintln(os.Stderr, err) @@ -22,46 +19,8 @@ func optExit(err error) { } } -// the vCard RFC says, a single logical line can be "folded" to multiple physical lines, -// so this shit must be done -type UnfoldingReader struct { - buf []byte - i int - j int -} - -func NewUnfoldingReader(buf []byte) *UnfoldingReader { - return &UnfoldingReader{buf, 0, 0} -} - -func replaceFold(s string) string { - // Yes, I know and I don't care - return strings.TrimSpace(strings.ReplaceAll(strings.ReplaceAll(s, "\r\n ", ""), "\r\n\t", "")) -} - -func (r *UnfoldingReader) ReadLine() (string, bool) { - readCR := false - readCRLF := false - for r.j = r.i; r.j < len(r.buf); r.j++ { - if r.buf[r.j] == '\r' { - readCR = true - } else if readCR && r.buf[r.j] == '\n' { - readCRLF = true - } else if readCRLF && r.buf[r.j] != ' ' && r.buf[r.j] != '\t' { - break - } else { - readCRLF = false - } - } - var s string - if r.i < len(r.buf) { - s = replaceFold(string(r.buf[r.i:r.j])) - } else { - s = "" - } - notEOB := (r.i < len(r.buf)) - r.i = r.j - return s, notEOB +func unfold(s string) string { + return strings.ReplaceAll(strings.ReplaceAll(s, "\r\n ", ""), "\r\n\t", "") } func vCardValue(line string) string { @@ -185,9 +144,11 @@ func (n *Number) WriteFritzboxXML(s io.Writer, i int) { } func GetContacts(buf []byte) (c ContactSet) { - r := NewUnfoldingReader(buf) + s := unfold(string(buf)) + scanner := bufio.NewScanner(strings.NewReader(s)) var current *Contact - for l, ok := r.ReadLine(); ok; l, ok = r.ReadLine() { + for scanner.Scan() { + l := strings.TrimSpace(scanner.Text()) if l == "BEGIN:VCARD" { current = &Contact{} } else if l == "END:VCARD" { @@ -197,6 +158,7 @@ func GetContacts(buf []byte) (c ContactSet) { current.setValue(l) } } + optExit(scanner.Err()) if current != nil { c = append(c, *current) }