Unzip archive with extra data in C# with Ionic.Zip

0

I need to extract data from zip file that contains extra data.

When I opening it with 7-zip, it works fine, but there is warning in properties - "There are some data after the end of payload data"

But when I trying to unzip it with DotNetZip it gives me an error

using (var zip = ZipFile.Read("test.ef4"))
            {
                foreach (var zipEntry in zip)
                {
                    Console.WriteLine(zipEntry.FileName);
                    var MemoryStream = new MemoryStream();
                    zipEntry.OpenReader().CopyTo(MemoryStream);
                    File.WriteAllBytes(zipEntry.FileName, MemoryStream.ToArray());
                }
            }

Exception:
Unhandled Exception: Ionic.Zip.ZipException: Cannot read that as a ZipFile 
---> Ionic.Zip.BadReadException:   Bad signature (0x0C000001) at position 0x00000060

How can I ignore this exception and unzip from file like 7-zip doing?


To reproduce it you can create archive with windows cmd.exe

Create archive.zip and extradata.txt with some random data. Then do this command -

   copy /b archive.zip+extradata.txt
c#
.net-4.0
unzip
dotnetzip
asked on Stack Overflow Sep 30, 2020 by PsiHamster

1 Answer

0

I found solution that worked for me:

All zip files have header like \x50\x4b\x01\x02 or \x50\x4b\x03\x04 in my case. (first \x50\x4b always the same. second half can be different)

So I wrote a code that founds offset of my ZIP file inside bytes. Footer of file is not important for any ziplib in C#

class Program
{
    static void Main(string[] args)
    {
        var content = File.ReadAllBytes("qv.zip");
        content = content.Skip(FirstPattern(content)).ToArray();

        using (var zip = ZipFile.Read(new MemoryStream(content), new ReadOptions() {}))
        {
            foreach (var zipEntry in zip)
            {
                Console.WriteLine(zipEntry.FileName);
                var MemoryStream = new MemoryStream();
                zipEntry.OpenReader().CopyTo(MemoryStream);
                File.WriteAllBytes(zipEntry.FileName, MemoryStream.ToArray());
            }
        }


    }

    private static int FirstPattern(byte[] bytes)
    {
        var header = StringToByteArray("504b0304"); // In my case all broken zip-files had 0304 ending

        for (int i = 0; i < bytes.Length - header.Length; i++)
        {
            var j = 0;
            while(j < header.Length && bytes[i + j] == header[j])
            {
                j++;
            }

            if(j == header.Length
                return i;
        }

        return -1;
    }

    public static byte[] StringToByteArray(string hex)
    {
        int numberChars = hex.Length;
        byte[] bytes = new byte[numberChars / 2];
        for (int i = 0; i < numberChars; i += 2)
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        return bytes;
    }
}
answered on Stack Overflow Oct 11, 2020 by PsiHamster

User contributions licensed under CC BY-SA 3.0