This is a migrated thread and some comments may be shown as answers.

Encypting multiple entries gives a corrupt zip file

6 Answers 99 Views
ZipLibrary
This is a migrated thread and some comments may be shown as answers.
Nick
Top achievements
Rank 1
Nick asked on 20 Sep 2019, 10:13 AM

When creating a password-protected ZIP archive, if I create a new entry and write to it, and during this process create, write and close a second entry, then the first entry appears to be corrupt when you try to read the file.

For example, the following see the following program:

static void Main(string[] args)
{
    // Create the main ZIP file
    using (var zipStream = File.Create(@"c:\temp\test.zip"))
    {
        var encrypt = new DefaultEncryptionSettings { Password = "nick" };
        using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create,true,null,null,encrypt))
        {
            // Create the 1st entry.
            using (var entry1 = zipArchive.CreateEntry("text1.txt"))
            {
                using (var stream1 = entry1.Open())
                {
                    using (var writer1 = new StreamWriter(stream1))
                    {
                        writer1.WriteLine("Writer 1 line 1");
                        // While writing the 1st entry, create a second entry
                        using (var entry2 = zipArchive.CreateEntry("text2.txt"))
                        {
                            using (var stream2 = entry2.Open())
                            {
                                using (var writer2 = new StreamWriter(stream2))
                                {
                                    writer2.WriteLine("Writer 2 line 1");
                                }
                            }
                        }
                        // Continue writing the 1st entry.
                        writer1.WriteLine("Writer 1 line 2");
                    }
                }
            }
 
        }
    }
}

 

This runs without error. Opening the file using 7-zip, I can read the "text2.txt" entry with no problem with the correct password. However, opening the "text1.txt" file gives an error suggesting the password is wrong.

Program in .NET 4.6, using Telerik.Windows.Zip 2018.3.1010.40.

6 Answers, 1 is accepted

Sort by
0
Nick
Top achievements
Rank 1
answered on 20 Sep 2019, 03:10 PM
Oh … and same behaviour with 2019.3.903.40.

Thanks.
0
Accepted
Martin
Telerik team
answered on 25 Sep 2019, 09:17 AM

Hi Nick,

The ZipArchive class doesn't support nesting of ZipArchiveEntry objectsThere are two options to use more than one StreamWriter in a ZipArchive.

The first is to use them one after another (not nested). I modified your example:

static void Main(string[] args)
{
	// Create the main ZIP file
	using (FileStream zipStream = File.Create("test.zip"))
	{
		var encrypt = new DefaultEncryptionSettings { Password = "nick" };
		using (ZipArchive zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true, null, null, encrypt))
		{
			// Create the 1st entry.
			using (ZipArchiveEntry entry1 = zipArchive.CreateEntry("text1.txt"))
			{
				using (Stream stream1 = entry1.Open())
				{
					using (StreamWriter writer1 = new StreamWriter(stream1))
					{
						writer1.WriteLine("Writer 1 line 1");
						writer1.WriteLine("Writer 1 line 2");
					}
				}
			}

			// Create a second entry after finishing the previous one
			using (ZipArchiveEntry entry2 = zipArchive.CreateEntry("text2.txt"))
			{
				using (Stream stream2 = entry2.Open())
				{
					using (StreamWriter writer2 = new StreamWriter(stream2))
					{
						writer2.WriteLine("Writer 2 line 1");
					}
				}
			}
		}
	}
}

If the specific case is to create the content in a nonconsecutive way, the other option is to make a model where to implement the desired logic/sequence and when all the operations are done, to create the ZipArchive from this model.

I hope this helps. Please, let me know if there is anything else I can assist you with.

Regards,
Martin
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Nick
Top achievements
Rank 1
answered on 25 Sep 2019, 10:36 AM

Thanks for this. Unfortunately, I wnated to avoid your suggested fix, as the real code is using a forward-reader from a database query to write the (1) data, and for some of these items there can be up to 3 additional ZIP entries being created, which I was doing as the read progressed.

So effectively, I'll need to cache something and complete the writing afterwards.

As a suggested feature, it would be nice if the underlying ZIP component threw an exception when a second stream was opened while a first was still in use, to allow this to be caught early.

0
Martin
Telerik team
answered on 27 Sep 2019, 04:30 PM

Hi Nick,

Thank you for the provided information and feedback.

I logged a public item in our backlog to fix this behavior: ZipArchive should throw exception during ZipArchive creation when a second stream for creating an entry is opened while the first is still in use. Please, make sure to cast your vote for the implementation as well as subscribe to the task by clicking the Follow button so you can receive updates about status changes on it.

In appreciation for pointing out this to our attention, I have added Telerik points to your account.

Regards,
Martin
Progress Telerik

Get quickly onboarded and successful with your Telerik and/or Kendo UI products with the Virtual Classroom free technical training, available to all active customers. Learn More.
0
Nick
Top achievements
Rank 1
answered on 24 Sep 2020, 02:26 PM

A follow up question ... does the same logic apply for reading ZIP files, i.e. can you have two ZipArchiveEntries and their streams open for reading on the same ZipArchive (which has been open in read mode)?

If not, can you have two ZipArchives open on the same underlying ZIP stream or file if it is just for reading (so that I can effectively read two entries at the same time)

Thanks.

0
Martin
Telerik team
answered on 29 Sep 2020, 09:21 AM

Hi Nick,

In order to read from the more than one ZipArchiveEntry stream in a nonconsecutive way, I can suggest you copping the zip archive file stream and creating separate ZipArchive instances for every ZipArchiveEntry you want to read from. Check the following code snippet:

using (Stream stream1 = File.Open("test.zip", FileMode.Open))
using (Stream stream2 = new MemoryStream())
{
	stream1.CopyTo(stream2);
	using (ZipArchive archive1 = new ZipArchive(stream1, ZipArchiveMode.Read, true, null))
	using (ZipArchive archive2 = new ZipArchive(stream2, ZipArchiveMode.Read, true, null))
	{
		ZipArchiveEntry entry1 = archive1.Entries.Where(e => e.Name == "text1.txt").FirstOrDefault();
		ZipArchiveEntry entry2 = archive2.Entries.Where(e => e.Name == "text2.txt").FirstOrDefault();

		using (Stream entry1Stream = entry1.Open())
		using (Stream entry2Stream = entry2.Open())
		{
			StreamReader streamReader1 = new StreamReader(entry1Stream);
			StreamReader streamReader2 = new StreamReader(entry2Stream);

			for (int i = 0; i < 4; i++)
			{
				string value1 = streamReader1.ReadLine();
				Console.WriteLine(value1);
				string value2 = streamReader2.ReadLine();
				Console.WriteLine(value2);
			}
			Console.ReadLine();
		}
	}
}

Regards,
Martin
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Tags
ZipLibrary
Asked by
Nick
Top achievements
Rank 1
Answers by
Nick
Top achievements
Rank 1
Martin
Telerik team
Share this question
or