@@ -30,21 +30,21 @@ Functions for producing an ODT file from OpenDocument XML.
31module Text.Pandoc.ODT ( saveOpenDocumentAsODT ) where
31module Text.Pandoc.ODT ( saveOpenDocumentAsODT ) where
32import Text.Pandoc.TH ( binaryContentsOf )
32import Text.Pandoc.TH ( binaryContentsOf )
33−import Data.Maybe ( fromJust, isJust )
33+import Data.Maybe ( fromJust )
34import Data.List ( partition, intersperse )
34import Data.List ( partition, intersperse )
35−import Prelude hiding ( writeFile, readFile )
35+import Prelude hiding ( writeFile, readFile, getContents )
36import System.IO.UTF8
36import System.IO.UTF8
37import System.IO ( stderr )
37import System.IO ( stderr )
38import System.Directory
38import System.Directory
39import System.FilePath ( (</>), takeDirectory, takeFileName, splitDirectories )
39import System.FilePath ( (</>), takeDirectory, takeFileName, splitDirectories )
40−import System.Process ( runCommand, waitForProcess )
40+import System.Process ( runProcess, waitForProcess )
41import System.Exit
41import System.Exit
42import Text.XML.Light
42import Text.XML.Light
43import Text.XML.Light.Cursor
43import Text.XML.Light.Cursor
44import Text.Pandoc.Shared ( withTempDir )
44import Text.Pandoc.Shared ( withTempDir )
45import Network.URI ( isURI )
45import Network.URI ( isURI )
46−import qualified Data.ByteString.Char8 as B ( writeFile, pack )
46+import qualified Data.ByteString as B ( writeFile, pack )
47−import Control.Monad ( unless )
47+import Data.ByteString.Internal ( c2w )
49-- | Produce an ODT file from OpenDocument XML.
49-- | Produce an ODT file from OpenDocument XML.
50saveOpenDocumentAsODT :: FilePath -- ^ Pathname of ODT file to be produced.
50saveOpenDocumentAsODT :: FilePath -- ^ Pathname of ODT file to be produced.
@@ -54,27 +54,26 @@ saveOpenDocumentAsODT :: FilePath -- ^ Pathname of ODT file to be produced.
54saveOpenDocumentAsODT destinationODTPath sourceDirRelative xml = do
54saveOpenDocumentAsODT destinationODTPath sourceDirRelative xml = do
55 let zipCmd = "zip"
55 let zipCmd = "zip"
56 -- check for zip in path:
56 -- check for zip in path:
57− findExecutable zipCmd >>= \v -> unless (isJust v) $ error $ "The '" ++ zipCmd ++
57+ zipPathMaybe <- findExecutable zipCmd
58+ let zipPath = case zipPathMaybe of
59+ Nothing -> error $ "The '" ++ zipCmd ++
58− "' command, which is needed to build an ODT file, was not found.\n" ++
60+ "' command, which is needed to build an ODT file, was not found.\n" ++
59− "It can be obtained from http://www.info-zip.org/Zip.html\n" ++
61+ "It can be obtained from http://www.info-zip.org/Zip.html\n" ++
60− "Debian (and Debian-based) linux: apt-get install zip\n" ++
62+ "Debian (and Debian-based) linux: apt-get install zip\n" ++
61− "Windows: See http://gnuwin32.sourceforge.net/packages/zip.htm"
63+ "Windows: See http://gnuwin32.sourceforge.net/packages/zip.htm"
62 withTempDir "pandoc-odt" $ \tempDir -> do
65 withTempDir "pandoc-odt" $ \tempDir -> do
63 let tempODT = tempDir </> "reference.odt"
66 let tempODT = tempDir </> "reference.odt"
64− B.writeFile tempODT $ B.pack $(binaryContentsOf $ "odt-styles" </> "reference.odt")
67+ B.writeFile tempODT $ B.pack $ map c2w $(binaryContentsOf $ "odt-styles" </> "reference.odt")
65− createDirectory $ tempDir </> "Pictures"
66 xml' <- handlePictures tempODT sourceDirRelative xml
68 xml' <- handlePictures tempODT sourceDirRelative xml
67 writeFile (tempDir </> "content.xml") xml'
69 writeFile (tempDir </> "content.xml") xml'
68− oldDir <- getCurrentDirectory
69− setCurrentDirectory tempDir
70− let zipCmdLine = "zip -9 -q -r " ++ tempODT ++ " " ++ "content.xml Pictures"
70+ ph <- runProcess zipPath ["-9", "-q", "-r", tempODT, "content.xml", "Pictures"]
71+ (Just tempDir) Nothing Nothing Nothing (Just stderr)
71− ec <- runCommand zipCmdLine >>= waitForProcess -- this requires compilation with -threaded
72+ ec <- waitForProcess ph -- requires compilation with -threaded
72− setCurrentDirectory oldDir
73 case ec of
73 case ec of
74 ExitSuccess -> copyFile tempODT destinationODTPath
74 ExitSuccess -> copyFile tempODT destinationODTPath
75 _ -> error "Error creating ODT." >> exitWith ec
75 _ -> error "Error creating ODT." >> exitWith ec
78-- | Find <draw:image ... /> elements and copy the file (xlink:href attribute) into Pictures/ in
77-- | Find <draw:image ... /> elements and copy the file (xlink:href attribute) into Pictures/ in
79-- the zip file. If filename is a URL, attempt to download it. Modify xlink:href attributes
78-- the zip file. If filename is a URL, attempt to download it. Modify xlink:href attributes
80-- to point to the new locations in Pictures/. Return modified XML.
79-- to point to the new locations in Pictures/. Return modified XML.
@@ -128,6 +127,7 @@ handleContent tempODT sourceDirRelative content@(Elem el) = do
128 splitDirectories $ takeDirectory $ attrVal href
127 splitDirectories $ takeDirectory $ attrVal href
129 let newLoc = "Pictures" </> pref ++ "_" ++ (takeFileName $ attrVal href)
128 let newLoc = "Pictures" </> pref ++ "_" ++ (takeFileName $ attrVal href)
130 let tempDir = takeDirectory tempODT
129 let tempDir = takeDirectory tempODT
130+ createDirectoryIfMissing False $ tempDir </> takeDirectory newLoc
131 copyFile oldLoc $ tempDir </> newLoc
131 copyFile oldLoc $ tempDir </> newLoc
132 let newAttrs = (href { attrVal = newLoc }) : rest
132 let newAttrs = (href { attrVal = newLoc }) : rest
133 return $ Elem (el { elAttribs = newAttrs })
133 return $ Elem (el { elAttribs = newAttrs })