Commits

Sergey Astanin committed d6bdc25

withEncryptedArchive: access encrypted files with the same password for all files

Comments (0)

Files changed (1)

LibZip/Codec/Archive/LibZip.hs

     , Entry
     , ZipStat(..)
     -- * Archive operations
-    , withArchive, getZip
+    , withArchive, withEncryptedArchive, getZip
     , numFiles, fileName, nameLocate, fileNames
     , fileSize, fileSizeIx
     , fileStat, fileStatIx
   c'zip_open path' (combine flags) errp >>= \z ->
   if z == nullPtr
     then peek errp >>= E.throwIO. errFromCInt
-    else do
+    else withOpenArchive z action
+
+
+-- | Top-level wrapper for operations with an open encrypted archive.
+-- 'withEncryptedArchive' opens and closes the file automatically.
+-- On error it throws 'ZipError'.
+withEncryptedArchive :: [OpenFlag]   -- ^ Checks for consistency or existence.
+                     -> String       -- ^ Encryption password.
+                     -> FilePath     -- ^ Filename of the zip archive.
+                     -> Archive a    -- ^ Action to don with the archive.
+                     -> IO a
+withEncryptedArchive flags password path action =
+    withCString password $ \password' ->
+    withCString path $ \path' ->
+    alloca $ \errp ->
+    c'zip_open path' (combine flags) errp >>= \z ->
+    if z == nullPtr
+       then peek errp >>= E.throwIO. errFromCInt
+       else do
+         r <- c'zip_set_default_password z password'
+         if r /= 0
+            then get_error z >>= E.throwIO
+            else withOpenArchive z action
+
+
+withOpenArchive :: Zip -> Archive a -> IO a
+withOpenArchive z action = do
       r <- fst `liftM` runStateT action z
       e <- c'zip_close z
       if e /= 0
         then get_error z >>= E.throwIO
         else return r
 
+
 -- | Get the number of entries in the archive.
 numFiles :: [FileFlag] -> Archive Integer
 numFiles flags  = do