update code to latest go
[epoint] / pkg / document / document.go
index 0c8b0f4..b82b167 100644 (file)
@@ -4,7 +4,7 @@
 // utf-8 text of key-value pairs.
 // The body contains a content-type MIME header so the document
 // can be used in OpenPGP/MIME (RFC 3156) emails.
-// The format of the key-value pairs are similar to MIME header
+// The format of the key-value pairs is similar to MIME header
 // fields: keys and values are separated by ": ", repeated keys
 // are not allowed, long values can be split before a space.
 //
@@ -13,7 +13,7 @@
 // -----BEGIN PGP SIGNED MESSAGE-----
 // Hash: SHA1
 //
-// Content-Type: text/plain.epoint.type; charset=utf-8
+// Content-Type: text/vnd.epoint.type; charset=utf-8
 //
 // Key: Value1
 // Another-Key: Value2
@@ -31,8 +31,7 @@ package document
 // TODO: trailing space handling in ParseFields
 // TODO: fields of notice (last notice, serial, failure notice,..)
 // TODO: limits and cert type specific input validation
-// TODO: fix Cert mess
-// TODO: nonce is id, id is even number of hex digits (require only drawer.nonce to be uniq)
+// TODO: hex nonce, uniq nonce vs uniq drawer.nonce
 // TODO: denom, issuer from key (key representation: armor?)
 
 import (
@@ -161,13 +160,13 @@ type Cert struct {
 
 type DebitCert struct {
        Cert
-       Beneficiary      string
+       Beneficiary string
 }
 
 type CreditCert struct {
        Cert
-       Drawer           string
-       DebitCert        string
+       Drawer    string
+       DebitCert string
 }
 
 type BounceCert struct {
@@ -181,6 +180,7 @@ type BounceCert struct {
        References   []string
 }
 
+// Common cert part of a debit or credit cert
 func ToCert(v interface{}) (cert *Cert, err error) {
        cert = new(Cert)
        switch x := v.(type) {
@@ -207,10 +207,10 @@ func cleanBody(s []byte) []byte {
 func Id(c *Signed) string {
        h := sha1.New()
        h.Write(c.Body)
-       return fmt.Sprintf("%040X", h.Sum())
+       return fmt.Sprintf("%040X", h.Sum(nil))
 }
 
-// parse an epoint document without checking the signature and format details
+// Parse an epoint document without checking the signature and format details
 func Parse(s []byte) (iv interface{}, c *Signed, err error) {
        c, err = ParseSigned(s)
        if err != nil {
@@ -224,7 +224,7 @@ func Parse(s []byte) (iv interface{}, c *Signed, err error) {
        return
 }
 
-// format and sign an epoint document
+// Format and sign an epoint document
 func Format(iv interface{}, key *openpgp.Entity) (s []byte, c *Signed, err error) {
        doc, err := FormatStruct(iv)
        if err != nil {
@@ -242,17 +242,15 @@ func Format(iv interface{}, key *openpgp.Entity) (s []byte, c *Signed, err error
        return
 }
 
-// verify an epoint document, return the cleaned version as well
-func Verify(c *Signed, key openpgp.KeyRing) (err error) {
+// Verify an epoint document, return the cleaned version as well
+func Verify(c *Signed, keys openpgp.KeyRing) (err error) {
        msg := bytes.NewBuffer(c.Body)
        sig := bytes.NewBuffer(c.Signature)
-       // TODO: verify signature
-       _, _ = msg, sig
-       //      _, err = openpgp.CheckArmoredDetachedSignature(key, msg, sig)
+       _, err = openpgp.CheckArmoredDetachedSignature(keys, msg, sig)
        return
 }
 
-// sign body with given secret key
+// Sign body with given secret key
 func Sign(body []byte, key *openpgp.Entity) (c *Signed, err error) {
        c = new(Signed)
        c.Hash = "SHA256"
@@ -471,7 +469,7 @@ func parseStruct(v reflect.Value, fields map[string]string, seen map[string]bool
                        fv.SetString(val)
                case "int":
                        var val int64
-                       val, err = strconv.Atoi64(s)
+                       val, err = strconv.ParseInt(s, 10, 64)
                        fv.SetInt(val)
                case "date":
                        var val int64
@@ -495,6 +493,7 @@ func parseStruct(v reflect.Value, fields map[string]string, seen map[string]bool
        return
 }
 
+// ParseStruct parses an epoint document and returns a struct representation
 func ParseStruct(doc *Document) (iv interface{}, err error) {
        switch doc.Type {
        case "Draft":
@@ -560,7 +559,7 @@ func formatStruct(v reflect.Value, doc *Document) (err error) {
                case "text":
                        val = formatString(fv.String())
                case "int":
-                       val = strconv.Itoa64(fv.Int())
+                       val = strconv.FormatInt(fv.Int(), 10)
                case "date":
                        val = formatDate(fv.Int())
                case "ids":
@@ -581,7 +580,7 @@ func formatStruct(v reflect.Value, doc *Document) (err error) {
        return
 }
 
-// turn a struct into a document
+// FormatStruct turns a struct into a document
 func FormatStruct(iv interface{}) (doc *Document, err error) {
        v := reflect.ValueOf(iv)
        if v.Kind() != reflect.Ptr || v.IsNil() || v.Elem().Kind() != reflect.Struct {
@@ -594,6 +593,7 @@ func FormatStruct(iv interface{}) (doc *Document, err error) {
        return
 }
 
+// ParseFields parses a key value sequence into a fields map
 func ParseFields(s []byte) (fields map[string]string, rest []byte, err error) {
        rest = s
        fields = make(map[string]string)
@@ -675,11 +675,11 @@ func parseDate(s string) (int64, error) {
        if err != nil {
                return 0, err
        }
-       return t.Seconds(), nil
+       return t.Unix(), nil
 }
 
 func formatDate(i int64) string {
-       return time.SecondsToUTC(i).Format(time.RFC3339)
+       return time.Unix(i,0).UTC().Format(time.RFC3339)
 }
 
 func getLine(data []byte) (line, rest []byte) {