{
  "WorkItem": {
    "AffectedComponent": {
      "Name": "",
      "DisplayName": ""
    },
    "ClosedComment": "fixed in changeset 45299.  First binary 1.9.0.25",
    "ClosedDate": "2009-10-21T16:44:46.463-07:00",
    "CommentCount": 0,
    "Custom": null,
    "Description": "The perfect companion to ZipOutputStream.\n \nAfter initial implementation, boutblock found these problems: \n \n1. GetNextEntry() fails when reaching the first file into a subdirectory (works for files in root folder of the archive). \n \n2. ZipInputStream throws an exception when using AES encryption \n: in WinZipAes.cs -> void ReadAndVerifyMac(System.IO.Stream s) -> if (_StoredMac.Length != CalculatedMac.Length) -> CalculatedMac is null and never set.\n \n3. ZipInputStream throws UnsupportedException when using set_Position against an unseekable stream.",
    "LastUpdatedDate": "2013-05-16T05:32:05.253-07:00",
    "PlannedForRelease": "",
    "ReleaseVisibleToPublic": false,
    "Priority": {
      "Name": "Low",
      "Severity": 50,
      "Id": 1
    },
    "ProjectName": "DotNetZip",
    "ReportedDate": "2009-10-06T21:16:20.48-07:00",
    "Status": {
      "Name": "Closed",
      "Id": 4
    },
    "ReasonClosed": {
      "Name": "Unassigned"
    },
    "Summary": "Implement a ZipInputStream",
    "Type": {
      "Name": "Feature",
      "Id": 1
    },
    "VoteCount": 2,
    "Id": 8926
  },
  "FileAttachments": [
    {
      "FileId": 2370,
      "FileName": "AFCInstall_V2.0.0.0.zip",
      "DownloadUrl": ".\\2370"
    }
  ],
  "Comments": [
    {
      "Message": "First cut at this is in v1.9.0.18.  I haven't completed the tests yet. ",
      "PostedDate": "2009-10-07T23:49:07.003-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-08T11:58:49.2-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Hi,\r\n\r\nSorry, you are quicker than I am ! I've just noticed that you implemented this new ZipInputStream  class a while ago.\r\n\r\nI had just tried it but unfortunately it didn't work : it threw an unsupported exception when using set_Position property against an unseekable stream :-(",
      "PostedDate": "2009-10-13T10:41:44.593-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Ok, I also noticed that it throws an exception when using AES encryption : in WinZipAes.cs -> void ReadAndVerifyMac(System.IO.Stream s) -> if (_StoredMac.Length != CalculatedMac.Length) -> CalculatedMac is null and never set.\r\n\r\nCheers",
      "PostedDate": "2009-10-14T01:52:41.613-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Another one : when calling GetNextEntry() after the last entry it throws from ZipFile.ReadEntry() ",
      "PostedDate": "2009-10-14T10:36:17.52-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Sorry, I was wrong in my last comment, GetNextEntry() fails when reaching the first file into a subdirectory (works for files in root folder of the archive).",
      "PostedDate": "2009-10-14T11:08:56.94-07:00",
      "Id": -2147483648
    },
    {
      "Message": "tests complete in changeset 44607.  There was no change required to the binary, so v1.9.0.18 is still the latest/best for ZipInputStream\r\n\r\n\n\n** Closed by Cheeso 10/8/2009 11:58 AM",
      "PostedDate": "2009-10-14T23:04:17.603-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-14T23:04:18.39-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-14T23:13:41-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-14T23:17:09.98-07:00",
      "Id": -2147483648
    },
    {
      "Message": "very helpful, thanks for the input.  \r\n\r\nI re-opened the workitem based on your input. \r\nI was able to easily reproduce and fix the problem with AES.   (get version 1.9.0.22 to test it)\r\n\r\nThe other two problems you reported, I wasn't able to reproduce. \r\n\r\nI'll need some better information on just what you did to produce these problems. \r\nCan you provide some test code? \r\n",
      "PostedDate": "2009-10-15T01:52:41.64-07:00",
      "Id": -2147483648
    },
    {
      "Message": "I'm glad I may help ! \r\n\r\n1) I generated a zip archive with files at the root level and some others within a subfolder. The first ones at the root are found as ZipEntries using GetNextEntry() on the stream but when reaching the first file located in the folder, it crashes with an exception (Bad CRC) coming from the ZipFile.ReadEntry() method:\r\n\r\nIonic.Zip.BadReadException was caught\r\n  Message=\"  ZipEntry::ReadHeader(): Bad signature (0x08074B50) at position  0x038B2C86\"\r\n  Source=\"Ionic.Zip.Reduced\"\r\n  StackTrace:\r\n       à Ionic.Zip.ZipEntry.ReadHeader(ZipEntry ze, Encoding defaultEncoding)\r\n       à Ionic.Zip.ZipEntry.ReadEntry(ZipContainer zc, Boolean first)\r\n       à Ionic.Zip.ZipInputStream.GetNextEntry()\r\n       à Thales.IO.Compression.ZipTool.UnZipArchive(String inputArchivePath, String outputRootFolderPath, String password, StepHandler StepHandler, Object sender) dans H:\\v_xps_ifsv2\\DEP\\Source\\Thales.IO.Compression.ZipTool\\ZipTool.cs:ligne 249\r\n  InnerException: null\r\n\r\nCode used :\r\n\r\n            long processedSize = 0;\r\n            using (ZipInputStream s = new ZipInputStream(File.OpenRead(inputArchivePath)))\r\n            {\r\n                /*\r\n                // is it password protected ?\r\n                if (String.IsNullOrEmpty(password) == false)\r\n                    s.Password = password;\r\n                */\r\n\r\n                ZipEntry zipEntry;\r\n                byte[] buffer = new byte[2048];\r\n                try\r\n                {\r\n                    while ((zipEntry = s.GetNextEntry()) != null)\r\n                    {\r\n                        // unzip under a target root path\r\n                        string fullPath = Path.Combine(outputRootFolderPath, zipEntry.FileName);\r\n                        string directoryName = Path.GetDirectoryName(fullPath);\r\n                        string fileName = Path.GetFileName(fullPath);\r\n\r\n                        // create directory if it doesn't already exist\r\n                        if (String.IsNullOrEmpty(directoryName) == false\r\n                            && Directory.Exists(directoryName) == false)\r\n                        {\r\n                            Directory.CreateDirectory(directoryName);\r\n\r\n                            DirectoryInfo di = new DirectoryInfo(directoryName);\r\n                            di.CreationTime = zipEntry.CreationTime;\r\n                            di.Attributes = zipEntry.Attributes;\r\n                        }\r\n\r\n                        // overwrite existing file or create new ones\r\n                        if (zipEntry.IsDirectory == false && String.IsNullOrEmpty(fileName) == false)\r\n                        {\r\n                            // callback progress event\r\n                            if (StepHandler != null)\r\n                            {\r\n                                StepHandler(sender, new ProgressEventArgs(totalSize, processedSize, fullPath));\r\n                            }\r\n\r\n                            using (FileStream streamWriter = File.Create(fullPath))\r\n                            {\r\n                                long lastPercentage = 0;\r\n                                bool copying = true;\r\n                                while (copying)\r\n                                {\r\n                                    int bytesRead = s.Read(buffer, 0, buffer.Length);\r\n                                    if (bytesRead > 0)\r\n                                    {\r\n                                        streamWriter.Write(buffer, 0, bytesRead);\r\n                                        processedSize += bytesRead;\r\n\r\n                                        long percent = (processedSize * 100L) / totalSize;\r\n                                        if (percent > lastPercentage)\r\n                                        {\r\n                                            lastPercentage = percent;\r\n\r\n                                            // callback progress event\r\n                                            if (StepHandler != null)\r\n                                            {\r\n                                                StepHandler(sender, new ProgressEventArgs(totalSize, processedSize, fullPath));\r\n                                            }\r\n                                        }\r\n                                    }\r\n                                    else\r\n                                    {\r\n                                        streamWriter.Flush();\r\n                                        copying = false;\r\n                                    }\r\n                                }\r\n                            }\r\n\r\n                            FileInfo fi = new FileInfo(fullPath);\r\n                            fi.CreationTime = zipEntry.CreationTime;\r\n                            fi.Attributes = zipEntry.Attributes;\r\n                        }\r\n\r\n                        // hack\r\n                        if (processedSize == totalSize)\r\n                            break;\r\n                    }\r\n\r\n2) still have to test your last version :-)\r\n\r\n3) My mistake sorry ! I forgot to comment out the Position = 0 of the intermediate MemoryStream I used as a workaround.",
      "PostedDate": "2009-10-15T08:06:45.68-07:00",
      "Id": -2147483648
    },
    {
      "Message": "About 1) I should precise that I can open and unzip the archive using 7zip with no issue.",
      "PostedDate": "2009-10-15T08:11:35.7-07:00",
      "Id": -2147483648
    },
    {
      "Message": "BB, can you try your code with the latest version of the library? \r\nI just ran your code here, and could not reproduce the problem you reported. \r\n\r\nIf you CAN reproduce the problem, can you attach a zipfile that causes the problem, here?  It's possible that I Can't get the problem to occur because I haven't produced the right zip file.  I have directories and subdirectories, but maybe there's something about how you constriuct it.  If you can attach a zip file it would make life easy for me. \r\n\r\nThanks",
      "PostedDate": "2009-10-15T10:02:09.093-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Ok, sure. I'm gonna do that right now. Thx.",
      "PostedDate": "2009-10-16T01:31:44.217-07:00",
      "Id": -2147483648
    },
    {
      "Message": "I couldn't download the last version of your sources from CodePlex. Their file server seems to be down for now.\r\nSo I uploaded a zip file that causes the crash in the mean time along with the source code I use to create it :\r\n\r\nlong processedSize = 0;\r\n            using (ZipOutputStream outputZipStream = new ZipOutputStream(File.Create(outputArchivePath)))\r\n            {\r\n                /*\r\n                if (String.IsNullOrEmpty(password) == false)\r\n                {\r\n                    outputZipStream.Password = password;\r\n                    outputZipStream.Encryption = EncryptionAlgorithm.WinZipAes256;\r\n                }\r\n                */\r\n\r\n                outputZipStream.CompressionLevel = CompressionLevel.BestCompression;\r\n\r\n                ZipEntry zipEntry;\r\n                byte[] buffer = new byte[4096];\r\n                foreach (FileSystemInfo path in pathList)\r\n                {\r\n                    // if a file ends with '\\' its a directory\r\n                    if (path is FileInfo)\r\n                    {\r\n                        FileInfo fi = path as FileInfo;\r\n                        // add new file with relative path rooted above 'inputFolderPath'\r\n                        zipEntry = outputZipStream.PutNextEntry(path.FullName.Remove(0, leftTrimLength));\r\n\r\n                        zipEntry.CreationTime = fi.CreationTime;\r\n                        zipEntry.Attributes = fi.Attributes;\r\n\r\n                        // callback progress event\r\n                        if (StepHandler != null)\r\n                        {\r\n                            StepHandler(sender, new ProgressEventArgs(totalSize, processedSize, fi.FullName));\r\n                        }\r\n\r\n                        using (FileStream fs = fi.OpenRead())\r\n                        {\r\n                            long lastPercentage = 0;\r\n                            bool copying = true;\r\n                            while (copying)\r\n                            {\r\n                                int bytesRead = fs.Read(buffer, 0, buffer.Length);\r\n                                if (bytesRead > 0)\r\n                                {\r\n                                    outputZipStream.Write(buffer, 0, bytesRead);\r\n                                    processedSize += bytesRead;\r\n\r\n                                    long percent = (processedSize * 100L) / totalSize;\r\n                                    if (percent > lastPercentage)\r\n                                    {\r\n                                        lastPercentage = percent;\r\n\r\n                                        // callback progress event\r\n                                        if (StepHandler != null)\r\n                                        {\r\n                                            StepHandler(sender, new ProgressEventArgs(totalSize, processedSize, fi.FullName));\r\n                                        }\r\n                                    }\r\n                                }\r\n                                else\r\n                                {\r\n                                    outputZipStream.Flush();\r\n                                    copying = false;\r\n                                }\r\n                            }\r\n                        }\r\n                    }\r\n                    else\r\n                    {\r\n                        // add new file with relative path rooted above 'inputFolderPath'\r\n                        zipEntry = outputZipStream.PutNextEntry(path.FullName.Remove(0, leftTrimLength) + @\"\\\");\r\n                        zipEntry.CreationTime = path.CreationTime;\r\n                        zipEntry.Attributes = path.Attributes;\r\n                    }\r\n                }\r\n\r\n                // callback progress event\r\n                if (StepHandler != null)\r\n                {\r\n                    StepHandler(sender, new ProgressEventArgs(totalSize, processedSize, outputArchivePath));\r\n                }\r\n            }            \r\n",
      "PostedDate": "2009-10-16T01:43:59.863-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-16T01:44:02.527-07:00",
      "Id": -2147483648
    },
    {
      "Message": "I can confirm now that it behaves the same with the last sources and the zip file I uploaded:\r\n\r\nIonic.Zip.BadReadException was caught\r\n  Message=\"  ZipEntry::ReadHeader(): Bad signature (0x08074B50) at position  0x00001449\"\r\n  Source=\"Ionic.Zip.Reduced\"\r\n  StackTrace:\r\n       à Ionic.Zip.ZipEntry.ReadHeader(ZipEntry ze, Encoding defaultEncoding)\r\n       à Ionic.Zip.ZipEntry.ReadEntry(ZipContainer zc, Boolean first)\r\n       à Ionic.Zip.ZipInputStream.GetNextEntry()\r\n       à Thales.IO.Compression.ZipTool.UnZipArchive(String inputArchivePath, String outputRootFolderPath, String password, StepHandler StepHandler, Object sender) dans H:\\v_xps_ifsv2\\DEP\\Source\\Thales.IO.Compression.ZipTool\\ZipTool.cs:ligne 249\r\n  InnerException: \r\n",
      "PostedDate": "2009-10-16T01:59:24.42-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Hi, have you managed to reproduce the pb ? I'm still stuck with this issue :-(",
      "PostedDate": "2009-10-19T09:01:11.893-07:00",
      "Id": -2147483648
    },
    {
      "Message": "yes, I've reproduced the problem here.  Will let you know...",
      "PostedDate": "2009-10-19T12:22:27.87-07:00",
      "Id": -2147483648
    },
    {
      "Message": "I believe I've fixed the problem.  I need to run the tests now.  The ZIP64 tests can take several hours... And if anything breaks, it's another test run, another several hours.  I will post updates here.",
      "PostedDate": "2009-10-20T10:16:23.783-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Yes, I've fixed it.  The tests have all passed.  I made one other small change, and now I need to run the tests again.  Figure 2 hours for that.  \r\n\r\nA side note - with your scenario, boutblock, it seems to me that the ZipInputstream is much more complicated to use, than the ZipFile class.  You are creating directories, setting attributes and creation time, using StreamWriters to copy the data, and so on - all of this and more is handled for you if you just use the ZipFile class and call ExtractAll() or do a foreach loop on the entries and call Extract() on each one.  And there's a nice ExtractProgress event to help you keep track of progress.  \r\n\r\nWhat you're doing isn't an incorrect use of ZipInputStream, but it is more complicated than just using ZipFile. \r\nIn any case I will post an update of DotNetZip in a few hours, when the tests complete.\r\n",
      "PostedDate": "2009-10-21T09:54:46.267-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2009-10-21T16:44:46.463-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Ok, I'm looking forward for your new version. Thx a lot :-)\r\n\r\nAnd I do agree that my version is more complicated than needed with your library. This code was originally built around the SharpZipLib library before I switch all my code to your handier library. \r\n\r\nI had a look to the extract method of DotNetZip and its progress callback but I was not sure how it worked. As you can see, my version is based on the total size to unzip (not the total nb of files) and it raises a progress on these conditions : when the percentage value changed based on total size/current cumulated size done OR when the current unzipped file name changed.\r\n\r\nCould you clarify how yours is working ?\r\n\r\n\r\n",
      "PostedDate": "2009-10-22T02:14:46.757-07:00",
      "Id": -2147483648
    },
    {
      "Message": "Hi, I tried the last commited sources and it works without a glitch with AES encryption on :-D\r\n\r\nThx again for your time and excellent work. Keep on !",
      "PostedDate": "2009-10-23T03:01:05.977-07:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2013-02-21T18:43:57.513-08:00",
      "Id": -2147483648
    },
    {
      "Message": "",
      "PostedDate": "2013-05-16T05:32:05.253-07:00",
      "Id": -2147483648
    }
  ]
}