epub-tools-3.0: src/app/EpubTools/EpubMeta/Import.hs
-- License: ISC (see LICENSE)
-- Author: Dino Morelli <dino@ui3.info>
module EpubTools.EpubMeta.Import
( importOpf )
where
import Codec.Archive.Zip ( Entry (..), addEntryToArchive, findEntryByPath
, readEntry, toArchive )
import Codec.Epub.IO ( getPkgPathXmlFromBS, writeArchive )
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BL
import Data.List ( foldl' )
import Data.Maybe ( fromJust )
import System.Directory ( removeFile )
import EpubTools.EpubMeta.Opts
import EpubTools.EpubMeta.Util
importOpf :: Options -> FilePath -> EM ()
importOpf opts zipPath = do
-- The modified file we want to insert into the book
let pathToNewOpf = fromJust . optImport $ opts
-- Make new file into a Zip Entry
tempEntry <- liftIO $ readEntry [] pathToNewOpf
-- Read the zip archive in, we'll need it in several steps
strictBytes <- liftIO $ BS.readFile zipPath
-- The path in the book where new file must go
(pathToOldFile, _) <- getPkgPathXmlFromBS strictBytes
-- Adjust the entry's path
let newOpfEntry = tempEntry { eRelativePath = pathToOldFile }
-- Bytes of existing archive already loaded, make an Archive from that
let oldArchive = toArchive . BL.fromChunks $ [strictBytes]
-- Make an entry from the existing mimetype file
mimeEntry <- maybe
(throwError "Something went wrong: This epub has no mimetype, which shouldn't be possible. Original file unchanged.")
return $ findEntryByPath "mimetype" oldArchive
-- Add the two entries back to the archive in this order to preserve the
-- mimetype as the first one
let newArchive = foldl' (flip id) oldArchive
[addEntryToArchive newOpfEntry, addEntryToArchive mimeEntry]
-- We're ready to write the new zip archive, delete the old one
liftIO $ removeFile zipPath
-- Write the new archive out
liftIO $ writeArchive zipPath newArchive