package main import ( "bufio" "bytes" "errors" "fmt" "io" "io/ioutil" "os" "strings" ) type File struct { Comment string B64 []byte Body []byte } const ( commentHdr = "untrusted comment: " verifyWith = "verify with " pubKey = "%s public key" secKey = "%s secret key" sigFrom = "signature from %s" ) func checkComment(comment string) error { // compatibility with original version if len(comment) > 1024 { return errors.New("comment line to long") } if !strings.HasPrefix(comment, commentHdr) { return errors.New("expected untrusted comment") } return nil } func Parse(r io.Reader) (File, error) { buf := bufio.NewReader(r) comment, err := buf.ReadString('\n') if err != nil { return File{}, err } if err := checkComment(comment); err != nil { return File{}, err } comment = comment[len(commentHdr):] b64, err := buf.ReadBytes('\n') if err != nil { return File{}, err } body, err := ioutil.ReadAll(buf) if err != nil { return File{}, err } return File{ Comment: strings.TrimSpace(comment), B64: bytes.TrimSpace(b64), Body: body, }, nil } func ParseFile(fname string) (File, error) { fd, err := os.Open(fname) if err != nil { return File{}, err } defer fd.Close() return Parse(fd) } func (f File) Encode(w io.Writer) error { fmt.Fprintf(w, "%v%v\n", commentHdr, f.Comment) fmt.Fprintf(w, "%v\n", string(f.B64)) if f.Body != nil { fmt.Fprintf(w, "%v", string(f.Body)) } return nil } func (f File) EncodeFile(fname string) error { fd, err := os.Create(fname) if err != nil { return err } defer fd.Close() return f.Encode(fd) }