Imports ICSharpCode.SharpZipLib.Checksums
Imports ICSharpCode.SharpZipLib.Zip

Imports Stax

Public Class Zip
    Public Shared Sub Pack(ByVal sourceDir As String, ByVal targetFile As String)
        Dim crc32 As New Crc32
        Dim outStream As New ZipOutputStream(File.Create(targetFile))
        outStream.SetLevel(6)

        For Each i As String In FileIO.FileSystem.GetFiles(sourceDir, FileIO.SearchOption.SearchAllSubDirectories)
            Dim strmFile As FileStream = File.OpenRead(i)
            Dim abyBuffer(CInt(strmFile.Length - 1)) As Byte

            strmFile.Read(abyBuffer, 0, abyBuffer.Length)
            Dim ze As ZipEntry = New ZipEntry(i.Replace(sourceDir, ""))

            ze.DateTime = File.GetLastWriteTimeUtc(i)
            ze.Size = strmFile.Length

            strmFile.Close()
            crc32.Reset()
            crc32.Update(abyBuffer)
            ze.Crc = crc32.Value
            outStream.PutNextEntry(ze)
            outStream.Write(abyBuffer, 0, abyBuffer.Length)
        Next

        outStream.Finish()
        outStream.Close()
    End Sub

    Public Shared Sub Unpack(ByVal source As String, ByVal destination As String)
        Dim inStream As New ZipInputStream(File.OpenRead(source))

        Do
            Dim name As String = ""

            Try
                Dim entry As ZipEntry = inStream.GetNextEntry

                If Not entry Is Nothing Then
                    name = entry.Name
                    name = DirPath.FixSeperator(name)
                    name = DirPath.AppendSeparator(destination) + name

                    If Not name.EndsWith(DirPath.Separator) Then
                        Dim dir As String = StringHelp.GetLeftLast(name, "\")

                        If Not Directory.Exists(dir) Then
                            Directory.CreateDirectory(dir)
                        End If
                    End If

                    If Not name.EndsWith("\") Then
                        Dim writer As FileStream = File.Create(name)
                        Dim data As Byte() = New Byte(2048) {}

                        Do
                            Dim size As Integer = inStream.Read(data, 0, data.Length)

                            If size > 0 Then
                                writer.Write(data, 0, size)
                            Else
                                Exit Do
                            End If
                        Loop

                        writer.Close()

                        Dim fi As New FileInfo(name)
                        fi.LastWriteTime = entry.DateTime
                    End If
                Else
                    Exit Do
                End If
            Catch ex As Exception
                Throw New Exception("Filename: " + name + vbCrLf + _
                    vbCrLf + ex.ToString)
            End Try
        Loop

        inStream.Close()
    End Sub
End Class