package main import ( "bytes" "flag" "fmt" "io" "mime" "net/mail" "sort" "xinu.tv/email/db" "github.com/golang/glog" ) var ( dumpMime = flag.Bool("mime", false, "show multipart mime types for message") headers = flag.Bool("headers", false, "show only headers") ) func printMultipartMime(hash string, r io.Reader) error { msg, err := mail.ReadMessage(r) if err != nil { return err } mediatype, params, err := mime.ParseMediaType(msg.Header.Get("Content-Type")) if err != nil { return err } glog.Infof("%s mt: %s p: %v", hash, mediatype, params) return nil } func printHeaders(hash string, r io.Reader) error { msg, err := mail.ReadMessage(r) if err != nil { return err } hdrs := make([]string, 0, len(msg.Header)) for k := range msg.Header { hdrs = append(hdrs, k) } fmt.Println(hash) sort.Strings(hdrs) for _, k := range hdrs { vs := msg.Header[k] fmt.Printf("%s:", k) for _, v := range vs { fmt.Printf(" %s", v) } fmt.Println() } return nil } func printOneBlob(hash string, blob []byte) error { r := bytes.NewReader(blob) switch { case *dumpMime: if err := printMultipartMime(hash, r); err != nil { // err != nil expected when mime type not found, so we log and // squelch the error. glog.Warningf("%s: %v", hash, err) return nil } case *headers: if err := printHeaders(hash, r); err != nil { return err } default: fmt.Println(string(blob)) } return nil } type hashError struct { hash string error } func (he hashError) Error() string { return fmt.Sprintf("%s: %v", he.hash, he.error) } func printAllBlobs(c *db.Conn) error { oCh := make(chan db.Original) errc := make(chan error) donec := make(chan struct{}) defer close(donec) go c.Originals(oCh, errc, donec) for { select { case o := <-oCh: if err := printOneBlob(o.Hash, o.Blob); err != nil { return hashError{hash: o.Hash, error: err} } case err := <-errc: return err } } } func main() { defer glog.Flush() flag.Parse() c, err := db.NewConn("") if err != nil { glog.Fatal(err) } if flag.NArg() == 0 { if err := printAllBlobs(c); err != nil { glog.Fatal(err) } return } var blob []byte for _, hash := range flag.Args() { if err := c.OriginalBlobByHash(hash, &blob); err != nil { glog.Fatal(err) } if err := printOneBlob(hash, blob); err != nil { glog.Fatal(err) } } }