In Development
Last Updated: 26 Aug 2024 11:17 by ADMIN

Invalid content after updating empty password-protected archive.

Workaround: Instead of creating an empty archive, add a dummy file to it that can be removed later.

Completed
Last Updated: 24 Jul 2024 11:48 by ADMIN
Release 2024.1.305 (2024 Q1)
ADMIN
Created by: Deyan
Comments: 3
Category: ZipLibrary
Type: Feature Request
15

Add support for the creation of AES-encrypted archives.

There is a related feature request for the extraction of such archives: ZipLibrary: Add support for extraction of AES-encrypted archives.

Completed
Last Updated: 15 May 2024 06:27 by ADMIN
Release 2024.2.426 (2024 Q2)

The attached gif file illustrates the inability to open the newly added file with the password: 

Sub Main()
	Dim sZipFilePath As String = "..\..\test.zip"
	File.Delete(sZipFilePath)

	CreateArchive(sZipFilePath)
	Dim decryptionSettings As DecryptionSettings = EncryptionSettings.CreateDecryptionSettings()
	AddHandler decryptionSettings.PasswordRequired, AddressOf DecryptionSettings_PasswordRequired
	Dim compressionSettings As CompressionSettings = Nothing
	Dim encoding As Encoding = Nothing
	Using oFS As FileStream = File.Open(sZipFilePath, FileMode.OpenOrCreate)


		Using oArchive As ZipArchive = ZipArchive.Update(oFS, encoding, compressionSettings, decryptionSettings)
			Using entry As ZipArchiveEntry = oArchive.CreateEntry("newText.txt")
				Dim writer As StreamWriter = New StreamWriter(entry.Open())
				writer.WriteLine("Hello world!")
				writer.Flush()
			End Using
		End Using
	End Using
End Sub

Private Sub CreateArchive(sZipFilePath As String)
	Using stream As Stream = File.Open(sZipFilePath, FileMode.Create)
		Dim _encryptionSettings As PasswordEncryptionSettings = EncryptionSettings.CreatePkzipPasswordEncryptionSettings()
		_encryptionSettings.Password = "telerik"
		Dim compressionSettings As CompressionSettings = Nothing
		Dim encoding As Encoding = Nothing

		Using archive As ZipArchive = ZipArchive.Create(stream, encoding, compressionSettings, _encryptionSettings)

			Using entry As ZipArchiveEntry = archive.CreateEntry("text.txt")
				Dim writer As StreamWriter = New StreamWriter(entry.Open())
				writer.WriteLine("Hello world!")
				writer.Flush()
			End Using
		End Using
	End Using
End Sub

Private Sub DecryptionSettings_PasswordRequired(ByVal sender As Object, ByVal e As PasswordRequiredEventArgs)
	e.Password = "telerik"
End Sub

 

Workaround: Until this bug is fixed the obsolete API could be used instead: 

ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Create, true, encoding, compressionSettings, encryptionSettings)
and
ZipArchive oArchive = new ZipArchive(stream, ZipArchiveMode.Update, true, encoding, compressionSettings, decryptionSettings)

Declined
Last Updated: 03 Apr 2024 15:43 by ADMIN

Steps to reproduce:

1.Create a zip archive for a txt file with password protection

2. Try updating the protected file and insert a new text line for example.


As a result,  an error occurs: System.ObjectDisposedException: 'Cannot access a closed Stream.'

 
Imports System.IO
Imports System.Text
Imports Telerik.Windows.Zip

Module Module1

    Sub Main()
        Dim sZipFilePath As String = "..\..\test.zip"
        File.Delete(sZipFilePath)

        CreateArchive(sZipFilePath)

        Dim decryptionSettings As DecryptionSettings = EncryptionSettings.CreateDecryptionSettings()
        AddHandler decryptionSettings.PasswordRequired, AddressOf DecryptionSettings_PasswordRequired
        Dim compressionSettings As CompressionSettings = Nothing
        Dim encoding As Encoding = Nothing
        Using oFS As FileStream = File.Open(sZipFilePath, FileMode.OpenOrCreate)


            Using oArchive As ZipArchive = ZipArchive.Update(oFS, encoding, compressionSettings, decryptionSettings)
                For Each entry As ZipArchiveEntry In oArchive.Entries
                    Using entryStream As Stream = entry.Open()
                        Dim reader As New StreamReader(entryStream)
                        Dim content As String = reader.ReadToEnd()

                        entryStream.Seek(0, SeekOrigin.End)
                        Dim writer As New StreamWriter(entryStream)
                        writer.WriteLine("Updated line.")
                        writer.Flush()
                    End Using
                Next
            End Using
        End Using
    End Sub

    Private Sub CreateArchive(sZipFilePath As String)
        Using stream As Stream = File.Open(sZipFilePath, FileMode.Create)
            Dim encryptionSettings As PasswordEncryptionSettings = encryptionSettings.CreatePkzipPasswordEncryptionSettings()
            encryptionSettings.Password = "MyPassword"
            Dim compressionSettings As CompressionSettings = Nothing
            Dim encoding As Encoding = Nothing

            Using archive As ZipArchive = ZipArchive.Create(stream, encoding, compressionSettings, encryptionSettings)

                Using entry As ZipArchiveEntry = archive.CreateEntry("text.txt")
                    Dim writer As StreamWriter = New StreamWriter(entry.Open())
                    writer.WriteLine("Hello world!")
                    writer.Flush()
                End Using
            End Using
        End Using
    End Sub

    Private Sub DecryptionSettings_PasswordRequired(ByVal sender As Object, ByVal e As PasswordRequiredEventArgs)
        e.Password = "MyPassword"
    End Sub

End Module
Completed
Last Updated: 14 Mar 2024 08:59 by ADMIN
Release 2024.1.305 (2024 Q1)

Steps to reproduce:

1.Create a zip archive for a txt file with password protection

2. Try updating the protected file and insert a new text line for example

The settings used for decrypting the file don't seem to be used encrypting again after the update operation. Here is a sample code snippet for reproducing the error message:

    Sub Main()
        Dim sZipFilePath As String = "..\..\test.zip"
        File.Delete(sZipFilePath)

        CreateArchive(sZipFilePath)

        Dim decryptionSettings As DecryptionSettings = EncryptionSettings.CreateDecryptionSettings()
        AddHandler decryptionSettings.PasswordRequired, AddressOf DecryptionSettings_PasswordRequired
        Dim compressionSettings As CompressionSettings = Nothing
        Dim encoding As Encoding = Nothing
        Using oFS As FileStream = File.Open(sZipFilePath, FileMode.OpenOrCreate)


            Using oArchive As ZipArchive = ZipArchive.Update(oFS, encoding, compressionSettings, decryptionSettings)
                For Each entry As ZipArchiveEntry In oArchive.Entries
                    Using entryStream As Stream = entry.Open()
                        Dim reader As New StreamReader(entryStream)
                        Dim content As String = reader.ReadToEnd()

                        entryStream.Seek(0, SeekOrigin.End)
                        Dim writer As New StreamWriter(entryStream)
                        writer.WriteLine("Updated line.")
                        writer.Flush()
                    End Using
                Next
            End Using
        End Using
    End Sub

    Private Sub CreateArchive(sZipFilePath As String)
        Using stream As Stream = File.Open(sZipFilePath, FileMode.Create)
            Dim encryptionSettings As PasswordEncryptionSettings = encryptionSettings.CreatePkzipPasswordEncryptionSettings()
            encryptionSettings.Password = "MyPassword"
            Dim compressionSettings As CompressionSettings = Nothing
            Dim encoding As Encoding = Nothing

            Using archive As ZipArchive = ZipArchive.Create(stream, encoding, compressionSettings, encryptionSettings)

                Using entry As ZipArchiveEntry = archive.CreateEntry("text.txt")
                    Dim writer As StreamWriter = New StreamWriter(entry.Open())
                    writer.WriteLine("Hello world!")
                    writer.Flush()
                End Using
            End Using
        End Using
    End Sub

    Private Sub DecryptionSettings_PasswordRequired(ByVal sender As Object, ByVal e As PasswordRequiredEventArgs)
        e.Password = "MyPassword"
    End Sub

Completed
Last Updated: 14 Mar 2024 08:59 by ADMIN
Release 2024.1.305 (2024 Q1)

The stream that is internally created by the CreateFromDirectory method remains opened and the user can't close it:

This is error message observed when using the below code snippet:

The process cannot access the file 'C:\Users\dyordano\OneDrive - Progress Software Corporation\MyProjects\1640071ZipFileCreateFromDirectory\myzip.zip' because it is being used by another process.

        static void Main(string[] args)
        {
            string archiveFileName = @"..\..\myzip.zip";
            string sourceDirectoryName = @"..\..\Folder";
            File.Delete(archiveFileName);
            Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);

            using (Stream stream = File.Open(archiveFileName, FileMode.Open))
            {

            }
        }

Workaround: 

        static void Main(string[] args)
        {
            string archiveFileName = @"..\..\myzip.zip";
            string sourceDirectoryName = @"..\..\Folder";
            File.Delete(archiveFileName);

          //  Telerik.Windows.Zip.Extensions.ZipFile.CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);
            CreateFromDirectory(sourceDirectoryName, archiveFileName, Telerik.Windows.Zip.CompressionLevel.Optimal, true);

            using (Stream stream = File.Open(archiveFileName, FileMode.Open))
            {

            }
        }

        private static void CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName, Telerik.Windows.Zip.CompressionLevel compressionLevel, bool includeBaseDirectory)
        {
            Encoding entryNameEncoding = null;
            DeflateSettings compressionSettings = new DeflateSettings()
            {
                CompressionLevel = compressionLevel,
                HeaderType = CompressedStreamHeader.None
            };
            char[] directorySeparatorChar = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };

            sourceDirectoryName = Path.GetFullPath(sourceDirectoryName);
            destinationArchiveFileName = Path.GetFullPath(destinationArchiveFileName);
            FileStream fileStream = File.Open(destinationArchiveFileName, FileMode.CreateNew, FileAccess.Write, FileShare.None); ;
            using (ZipArchive zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create,false,  entryNameEncoding))
            {
                bool empty = true;

                DirectoryInfo directoryInfo = new DirectoryInfo(sourceDirectoryName);
                string fullName = directoryInfo.FullName;
                if (includeBaseDirectory && directoryInfo.Parent != null)
                {
                    fullName = directoryInfo.Parent.FullName;
                }

                foreach (FileSystemInfo fileSystemInfo in directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories))
                {
                    empty = false;

                    int length = fileSystemInfo.FullName.Length - fullName.Length;
                    string entryName = fileSystemInfo.FullName.Substring(fullName.Length, length);
                    entryName = entryName.TrimStart(directorySeparatorChar);

                    DirectoryInfo subfolder = fileSystemInfo as DirectoryInfo;
                    if (subfolder != null)
                    {
                        if (IsDirectoryEmpty(subfolder))
                        {
                            zipArchive.CreateEntry(string.Concat(entryName, Path.DirectorySeparatorChar));
                        }
                    }
                    else
                    {
                        ZipFile.CreateEntryFromFile(zipArchive, fileSystemInfo.FullName, entryName, compressionSettings);
                    }
                }

                if (includeBaseDirectory && empty)
                {
                    zipArchive.CreateEntry(string.Concat(directoryInfo.Name, Path.DirectorySeparatorChar));
                }
            }
        }
        private static bool IsDirectoryEmpty(DirectoryInfo directoryInfo)
        {
            bool empty = true;

            using (IEnumerator<FileSystemInfo> enumerator = directoryInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories).GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    empty = false;
                }
            }

            return empty;
        }

Note: We should ensure that all of the obsolete API that used to use the "leave open" flag don't keep the stream locked.

 

Unplanned
Last Updated: 08 Mar 2024 06:47 by Joe
When extracting zip archives that contain empty folders with 7zip an error message occurs: "Headers Error"

Completed
Last Updated: 24 Jan 2024 09:18 by ADMIN
Release 2024 Q1

Add support for extraction of AES-encrypted archives.

There is a related feature request for the creation of such archives: ZipLibrary: Add support for creation of AES-encrypted archives.

Completed
Last Updated: 03 Nov 2023 06:47 by ADMIN
Release R3 2023 SP1

I'm trying to implement the IXmlSerialization for class SerializableDictionary. When starts the serialization of class to xml, I'm catching the System.NotSupportedException: 'Can't flush final block twice'. The problem occurs when second serializer trying to call Serialize method on same XmlWriter. 

using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, false, null))
    {
        foreach (var item in array)
        {
            using (var entry = archive.CreateEntry($"{item.Name}.reg-ext"))
            {
                XmlInOut<RegulationItem>.SaveToStream(entry.Open(), item);
            }
        }
    }

Could it be bug with the ArchiveEntry Stream?

I've placed a solution into a github repo. Also I tried to replace the stream of entry with the MemoryStream, and it helps. But I would to do it directly, if it's possible. 

The original question.

Unplanned
Last Updated: 09 May 2023 14:28 by Massimo
Created by: Massimo
Comments: 0
Category: ZipLibrary
Type: Feature Request
0
Add events for the beginning and for the end of file extraction.
Unplanned
Last Updated: 09 Mar 2023 09:18 by Remco
Created by: Remco
Comments: 0
Category: ZipLibrary
Type: Feature Request
3
Add support for self-extracting archive
Unplanned
Last Updated: 02 Mar 2023 10:22 by Joe
Umlaut chars in file names not rendered correctly after extract form archive made with Windows, 7-Zip
Unplanned
Last Updated: 09 Aug 2022 09:18 by ADMIN
The following error is thrown when a zip containing duplicate file names is iterated through:
System.ArgumentException: 'An item with the same key has already been added.'
Completed
Last Updated: 20 Oct 2021 12:45 by ADMIN
Release R3 2021 SP1
In some specific cases decompressing a password-protected archive with a Stored compression method throws InvalidArgumentOffsetCount
Unplanned
Last Updated: 11 Oct 2021 15:18 by ADMIN
Writing content into a ZipArchiveEntry using the PdfStreamWriter leads to a wrong offset of the xref table and the objects in it:
MemoryStream ms1 = new MemoryStream();

using (ZipArchive archive = new ZipArchive(ms1, ZipArchiveMode.Create, false, null))
{
	using (PdfFileSource fileSource = new PdfFileSource(File.OpenRead(documentToSplit)))
	{
		string splitDocumentName = "1st page.pdf";
		using (ZipArchiveEntry entry = archive.CreateEntry(splitDocumentName))
		{
			using (PdfStreamWriter writer = new PdfStreamWriter(entry.Open()))
			{
				PdfPageSource page = fileSource.Pages[0];
				writer.WritePage(page);
			}
		}
	}
}

File.WriteAllBytes("exported.zip", ms1.ToArray());


Unplanned
Last Updated: 15 Jun 2021 08:25 by ADMIN
Created by: Paweł Korczak
Comments: 0
Category: ZipLibrary
Type: Feature Request
0
According to the .ZIP File Format SpecificationBZIP2 is an open-source data compression algorithm developed by Julian Seward.
Unplanned
Last Updated: 07 May 2021 09:36 by ADMIN

Currently, an exception is thrown when the file being unzipped already exists in the destination folder. Expose overload of the ExtractToDirectory() method allowing users to overwrite files.

Alternatively, the ZipArchiveEntry.ExtractToFile() method can be used:

using (ZipArchive source = ZipFile.Open(sourceFileName, ZipArchiveMode.Read, null))
{
    foreach (ZipArchiveEntry entry in source.Entries)
    {
        string fullPath = Path.GetFullPath(Path.Combine(destinationDirectory, entry.FullName));

        if (Path.GetFileName(fullPath).Length != 0)
        {
            Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
            // The boolean parameter determines whether an existing file that has the same name as the destination file should be overwritten
            entry.ExtractToFile(fullPath, true);
        }
    }
}

Declined
Last Updated: 23 Oct 2019 06:18 by ADMIN
Created by: Nick
Comments: 1
Category: ZipLibrary
Type: Feature Request
0

Provide a simple method to detect that a password for a ZIP file is not valid.

The current implemention usually throws an exception (which does not definitively identify the password as wrong), but not always. Sometimes it just returns corrupt data.

It would be nice to  either have a typed exception consistently thrown, or a method to specifically check for an invalid password.

Thanks. 

Unplanned
Last Updated: 26 Sep 2019 14:50 by ADMIN
During a ZipArchive creation, when a second stream for creating an entry is opened while the first is still in use the ZipArchive is created with no error message, but the first entry occurs broken (The destination file could not be created).
Unplanned
Last Updated: 03 Dec 2018 12:35 by ADMIN
Telerik.Windows.Zip.InvalidDataException: 'Unknown compression method (0x92)' when initializing a Telerik.Windows.Zip.CompressedStream is thrown for some object streams (read from pdf) due to incorrect transformation header.
1 2