Hello,
After updating existing password-protected zip archives using ZipFile.Add() or ZipFile.Delete() methods they become unusable by #ziplib.
Version of I used is "0.85.4.369"
1) I added the following test routine to the SharpZipLib.Tests.Zip.GeneralHandling (took PartialStreamClosing() as a base)
/// <summary>
/// Added by Serg 5/8/2008
/// </summary>
[Test]
[Category("Zip")]
[Category("CreatesTempFile")]
public void UpdateArchive()
{
string tempFile = GetTempFilePath();
Assert.IsNotNull(tempFile, "No permission to execute this test?");
if (tempFile != null)
{
tempFile = Path.Combine(tempFile, "SharpZipTest.Zip");
MakeZipFile(tempFile, new String[ { "Farriera", "Champagne", "Urban myth" }, 10, "Aha", "123456");
using (ZipFile zipFile = new ZipFile(tempFile))
{
zipFile.Password = "123456";
Assert.IsTrue(zipFile.TestArchive(true));
zipFile.BeginUpdate();
zipFile.Delete("Farriera");
zipFile.CommitUpdate();
Assert.IsTrue(zipFile.TestArchive(true));
zipFile.Close();
}
File.Delete(tempFile);
}
}
2) I added modified routine for archive creation to SharpZipLib.Tests.Zip.ZipBase (sets password and does not use zip64)
/// <summary>
/// Added by Serg 5/8/2008
/// </summary>
protected void MakeZipFile(string name, string[ names, int size, string comment, string password)
{
using (FileStream fs = File.Create(name))
{
using (ZipOutputStream zOut = new ZipOutputStream(fs))
{
zOut.UseZip64 = UseZip64.Off;
zOut.Password = password;
zOut.SetComment(comment);
for (int i = 0; i < names.Length; ++i)
{
zOut.PutNextEntry(new ZipEntry(names[i]));
AddKnownDataToEntry(zOut, size);
}
zOut.Close();
}
fs.Close();
}
}
The test I added fails. If password is set to an empty string (in the test above it's "123456"), test passes.
"Dirty" fix I found is in SharpZipLib.Zip.ZipFile.GetDescriptorSize() function.
This is existing code, fails:
int GetDescriptorSize(ZipUpdate update)
{
int result = 0;
if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
result = ZipConstants.DataDescriptorSize - 4;
if ( update.Entry.LocalHeaderRequiresZip64 ) {
result = ZipConstants.Zip64DataDescriptorSize - 4;
}
}
return result;
}
This is modified code, works:
int GetDescriptorSize(ZipUpdate update)
{
int result = 0;
if ( (update.Entry.Flags & (int)GeneralBitFlags.Descriptor) != 0) {
result = ZipConstants.DataDescriptorSize - 0;
if ( update.Entry.LocalHeaderRequiresZip64 ) {
result = ZipConstants.Zip64DataDescriptorSize - 4;
}
}
return result;
}
Fixing descriptor size seems to help.
I hope the issue makes sense and is clear enough.
I don't have zip format specification to see whether the change I did is legit and that code itself is not explaining
(don't see why data descriptor size is reduced by 4 bytes)
Thanks for attention and best regards,
Serg