/* Package epubzip Helper to write EPUB files. We create a zip with the magic EPUB mimetype. */ package epubzip import ( "archive/zip" "os" "time" ) type EPUBZip struct { w *os.File wz *zip.Writer } // New create a new EPUB func New(path string) (EPUBZip, error) { w, err := os.Create(path) if err != nil { return EPUBZip{}, err } wz := zip.NewWriter(w) return EPUBZip{w, wz}, nil } // Close compress pipe and file. func (e EPUBZip) Close() error { if err := e.wz.Close(); err != nil { return err } return e.w.Close() } // WriteMagic Write mimetype, in a very specific way. // // This will be valid with epubcheck tools. func (e EPUBZip) WriteMagic() error { t := time.Now().UTC() //goland:noinspection GoDeprecation fh := zip.FileHeader{ Name: "mimetype", Method: zip.Store, Modified: t, ModifiedTime: uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11), ModifiedDate: uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9), CompressedSize64: 20, UncompressedSize64: 20, CRC32: 0x2cab616f, } fh.CreatorVersion = fh.CreatorVersion&0xff00 | 20 // preserve compatibility byte fh.ReaderVersion = 20 fh.SetMode(0600) m, err := e.wz.CreateRaw(&fh) if err != nil { return err } _, err = m.Write([]byte("application/epub+zip")) return err } func (e EPUBZip) Copy(fz *zip.File) error { return e.wz.Copy(fz) } // WriteRaw Write image. They are already compressed, so we write them down directly. func (e EPUBZip) WriteRaw(raw ZipImage) error { m, err := e.wz.CreateRaw(raw.Header) if err != nil { return err } _, err = m.Write(raw.Data) return err } // WriteContent Write file. Compressed it using deflate. func (e EPUBZip) WriteContent(file string, content []byte) error { m, err := e.wz.CreateHeader(&zip.FileHeader{ Name: file, Modified: time.Now(), Method: zip.Deflate, }) if err != nil { return err } _, err = m.Write(content) return err }