packages feed

zip-archive 0.1.2.1 → 0.1.3

raw patch · 3 files changed

+103/−117 lines, 3 filesdep ~binarydep ~directory

Dependency ranges changed: binary, directory

Files

Codec/Archive/Zip.hs view
@@ -67,12 +67,12 @@ import Text.Printf import System.FilePath import System.Directory ( doesDirectoryExist, getDirectoryContents, createDirectoryIfMissing )-import Control.Monad ( when, unless, zipWithM, liftM )+import Control.Monad ( when, unless, zipWithM ) import System.Directory ( getModificationTime ) import System.IO ( stderr, hPutStrLn ) import qualified Data.Digest.CRC32 as CRC32 import qualified Data.Map as M-+import Control.Applicative #ifndef _WINDOWS import System.Posix.Files ( setFileTimes ) #endif@@ -263,15 +263,6 @@ -------------------------------------------------------------------------------- -- Internal functions for reading and writing zip binary format. --- | Perform a sequence of actions until one returns Nothing;--- return list of results.-many :: Monad m => m (Maybe a) -> m [a]-many p = do-  r <- p-  case r of-       Just x  ->  many p >>= return . (x:)-       Nothing -> return []- -- Note that even on Windows, zip files use "/" internally as path separator. zipifyFilePath :: FilePath -> String zipifyFilePath path =@@ -419,9 +410,10 @@ getArchive = do   locals <- many getLocalFile   files <- many (getFileHeader (M.fromList locals))-  digSig <- lookAheadM getDigitalSignature+  digSig <- Just `fmap` getDigitalSignature <|> return Nothing   endSig <- getWord32le-  unless (endSig == 0x06054b50) $ fail "Did not find end of central directory signature"+  unless (endSig == 0x06054b50)+    $ fail "Did not find end of central directory signature"   skip 2 -- disk number   skip 2 -- disk number of central directory   skip 2 -- num entries on this disk@@ -490,49 +482,47 @@ -- begins with the signature 0x08074b50, then 4 bytes crc-32, 4 bytes -- compressed size, 4 bytes uncompressed size. -getLocalFile :: Get (Maybe (Word32, B.ByteString))+getLocalFile :: Get (Word32, B.ByteString) getLocalFile = do-  sig <- lookAhead getWord32le-  if sig /= 0x04034b50-    then return Nothing-    else do-      offset <- bytesRead-      skip 4  -- signature-      skip 2  -- version-      bitflag <- getWord16le-      skip 2  -- compressionMethod-      skip 2  -- last mod file time-      skip 2  -- last mod file date-      skip 4  -- crc32-      compressedSize <- getWord32le-      when (compressedSize == 0xFFFFFFFF) $-        fail "Can't read ZIP64 archive."-      skip 4  -- uncompressedsize-      fileNameLength <- getWord16le-      extraFieldLength <- getWord16le-      skip (fromIntegral fileNameLength)  -- filename-      skip (fromIntegral extraFieldLength) -- extra field-      compressedData <- if bitflag .&. 0O10 == 0-          then getLazyByteString (fromIntegral compressedSize)-          else -- If bit 3 of general purpose bit flag is set,-               -- then we need to read until we get to the-               -- data descriptor record.  We assume that the-               -- record has signature 0x08074b50; this is not required-               -- by the specification but is common.-               do raw <- many $ do-                           s <- lookAhead getWord32le-                           if s == 0x08074b50-                              then return Nothing-                              else liftM Just getWord8-                  skip 4 -- signature-                  skip 4 -- crc32-                  cs <- getWord32le  -- compressed size-                  skip 4 -- uncompressed size-                  if fromIntegral cs == length raw-                     then return $ B.pack raw-                     else fail "Content size mismatch in data descriptor record" -      return $ Just (fromIntegral offset, compressedData)+  offset <- bytesRead+  getWord32le >>= ensure (== 0x04034b50)+  skip 2  -- version+  bitflag <- getWord16le+  skip 2  -- compressionMethod+  skip 2  -- last mod file time+  skip 2  -- last mod file date+  skip 4  -- crc32+  compressedSize <- getWord32le+  when (compressedSize == 0xFFFFFFFF) $+    fail "Can't read ZIP64 archive."+  skip 4  -- uncompressedsize+  fileNameLength <- getWord16le+  extraFieldLength <- getWord16le+  skip (fromIntegral fileNameLength)  -- filename+  skip (fromIntegral extraFieldLength) -- extra field+  compressedData <- if bitflag .&. 0O10 == 0+      then getLazyByteString (fromIntegral compressedSize)+      else -- If bit 3 of general purpose bit flag is set,+           -- then we need to read until we get to the+           -- data descriptor record.  We assume that the+           -- record has signature 0x08074b50; this is not required+           -- by the specification but is common.+           do raw <- getWordsTilSig 0x08074b50+              skip 4 -- crc32+              cs <- getWord32le  -- compressed size+              skip 4 -- uncompressed size+              if fromIntegral cs == length raw+                 then return $ B.pack raw+                 else fail "Content size mismatch in data descriptor record" +  return (fromIntegral offset, compressedData) +getWordsTilSig :: Word32 -> Get [Word8]+getWordsTilSig sig =+  (getWord32le >>= ensure (== sig) >> return []) <|>+    do w <- getWord8+       ws <- getWordsTilSig sig+       return (w:ws)+ putLocalFile :: Entry -> Put putLocalFile f = do   putWord32le 0x04034b50@@ -579,57 +569,54 @@ -- >    file comment (variable size)  getFileHeader :: M.Map Word32 B.ByteString -- ^ map of (offset, content) pairs returned by getLocalFile-              -> Get (Maybe Entry)+              -> Get Entry getFileHeader locals = do-  sig <- lookAhead getWord32le-  if sig /= 0x02014b50-     then return Nothing-     else do-       skip 4 -- skip past signature-       skip 2 -- version made by-       versionNeededToExtract <- getWord8-       skip 1 -- upper byte indicates OS part of "version needed to extract"-       unless (versionNeededToExtract <= 20) $-         fail "This archive requires zip >= 2.0 to extract."-       skip 2 -- general purpose bit flag-       rawCompressionMethod <- getWord16le-       compressionMethod <- case rawCompressionMethod of-                             0 -> return NoCompression-                             8 -> return Deflate-                             _ -> fail $ "Unknown compression method " ++ show rawCompressionMethod-       lastModFileTime <- getWord16le-       lastModFileDate <- getWord16le-       crc32 <- getWord32le-       compressedSize <- getWord32le-       uncompressedSize <- getWord32le-       fileNameLength <- getWord16le-       extraFieldLength <- getWord16le-       fileCommentLength <- getWord16le-       skip 2 -- disk number start-       internalFileAttributes <- getWord16le-       externalFileAttributes <- getWord32le-       relativeOffset <- getWord32le-       fileName <- getLazyByteString (toEnum $ fromEnum fileNameLength)-       extraField <- getLazyByteString (toEnum $ fromEnum extraFieldLength)-       fileComment <- getLazyByteString (toEnum $ fromEnum fileCommentLength)-       compressedData <- case (M.lookup relativeOffset locals) of-                         Just x  -> return x-                         Nothing -> fail $ "Unable to find data at offset " ++ show relativeOffset-       return $ Just $ Entry-                 { eRelativePath            = toString fileName-                 , eCompressionMethod       = compressionMethod-                 , eLastModified            = msDOSDateTimeToEpochTime $-                                              MSDOSDateTime { msDOSDate = lastModFileDate,-                                                              msDOSTime = lastModFileTime }-                 , eCRC32                   = crc32-                 , eCompressedSize          = compressedSize-                 , eUncompressedSize        = uncompressedSize-                 , eExtraField              = extraField-                 , eFileComment             = fileComment-                 , eInternalFileAttributes  = internalFileAttributes-                 , eExternalFileAttributes  = externalFileAttributes-                 , eCompressedData          = compressedData-                 }+  getWord32le >>= ensure (== 0x02014b50)+  skip 2 -- version made by+  versionNeededToExtract <- getWord8+  skip 1 -- upper byte indicates OS part of "version needed to extract"+  unless (versionNeededToExtract <= 20) $+    fail "This archive requires zip >= 2.0 to extract."+  skip 2 -- general purpose bit flag+  rawCompressionMethod <- getWord16le+  compressionMethod <- case rawCompressionMethod of+                        0 -> return NoCompression+                        8 -> return Deflate+                        _ -> fail $ "Unknown compression method " ++ show rawCompressionMethod+  lastModFileTime <- getWord16le+  lastModFileDate <- getWord16le+  crc32 <- getWord32le+  compressedSize <- getWord32le+  uncompressedSize <- getWord32le+  fileNameLength <- getWord16le+  extraFieldLength <- getWord16le+  fileCommentLength <- getWord16le+  skip 2 -- disk number start+  internalFileAttributes <- getWord16le+  externalFileAttributes <- getWord32le+  relativeOffset <- getWord32le+  fileName <- getLazyByteString (toEnum $ fromEnum fileNameLength)+  extraField <- getLazyByteString (toEnum $ fromEnum extraFieldLength)+  fileComment <- getLazyByteString (toEnum $ fromEnum fileCommentLength)+  compressedData <- case (M.lookup relativeOffset locals) of+                    Just x  -> return x+                    Nothing -> fail $ "Unable to find data at offset " +++                                        show relativeOffset+  return $ Entry+            { eRelativePath            = toString fileName+            , eCompressionMethod       = compressionMethod+            , eLastModified            = msDOSDateTimeToEpochTime $+                                         MSDOSDateTime { msDOSDate = lastModFileDate,+                                                         msDOSTime = lastModFileTime }+            , eCRC32                   = crc32+            , eCompressedSize          = compressedSize+            , eUncompressedSize        = uncompressedSize+            , eExtraField              = extraField+            , eFileComment             = fileComment+            , eInternalFileAttributes  = internalFileAttributes+            , eExternalFileAttributes  = externalFileAttributes+            , eCompressedData          = compressedData+            }  putFileHeader :: Word32        -- ^ offset               -> Entry@@ -666,14 +653,11 @@ -- >     size of data                    2 bytes -- >     signature data (variable size) -getDigitalSignature :: Get (Maybe B.ByteString)+getDigitalSignature :: Get B.ByteString getDigitalSignature = do-  hdrSig <- getWord32le-  if hdrSig /= 0x08064b50-     then return Nothing-     else do-        sigSize <- getWord16le-        getLazyByteString (toEnum $ fromEnum sigSize) >>= return . Just+  getWord32le >>= ensure (== 0x05054b50)+  sigSize <- getWord16le+  getLazyByteString (toEnum $ fromEnum sigSize)  putDigitalSignature :: Maybe B.ByteString -> Put putDigitalSignature Nothing = return ()@@ -681,3 +665,9 @@   putWord32le 0x08064b50   putWord16le $ fromIntegral $ B.length sig   putLazyByteString sig++ensure :: (a -> Bool) -> a -> Get ()+ensure p val =+  if p val+     then return ()+     else fail "ensure not satisfied"
tests/test-zip-archive.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} -- Test suite for Codec.Archive.Zip -- runghc Test.hs @@ -6,9 +5,6 @@ import System.Directory import Test.HUnit.Base import Test.HUnit.Text-#if MIN_VERSION_directory(1,2,0)-import System.Time-#endif import System.Process import qualified Data.ByteString.Lazy as B import Control.Applicative
zip-archive.cabal view
@@ -1,5 +1,5 @@ Name:                zip-archive-Version:             0.1.2.1+Version:             0.1.3 Cabal-Version:       >= 1.10 Build-type:          Simple Synopsis:            Library for creating and modifying zip archives.@@ -29,7 +29,7 @@     Build-depends:   base >= 3 && < 5, pretty, containers   else     Build-depends:   base < 3-  Build-depends:     binary < 0.6, zlib, filepath, bytestring >= 0.9.0, array, mtl, utf8-string >= 0.3.1, old-time, digest >= 0.0.0.1, directory, time+  Build-depends:     binary >= 0.6, zlib, filepath, bytestring >= 0.9.0, array, mtl, utf8-string >= 0.3.1, old-time, digest >= 0.0.0.1, directory, time   Exposed-modules:   Codec.Archive.Zip   Default-Language:  Haskell98   Hs-Source-Dirs:    .