1 // NativeUnzip.cs created with MonoDevelop
2 // User: alan at 13:11 20/10/2008
4 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
8 using System.Collections.Generic;
10 using System.IO.Packaging;
11 using System.Runtime.InteropServices;
16 static class NativeUnzip
18 enum ZipStringComparison
25 public static void CloseArchive (UnzipHandle handle)
28 handle.SetHandleAsInvalid ();
31 public static void CloseCurrentFile (UnzipHandle handle)
33 if (unzCloseCurrentFile (handle) != 0)
34 throw new Exception ("Could not close the active file");
37 static CompressionOption ConvertCompression (int compressionLevel)
39 switch (compressionLevel)
43 return CompressionOption.SuperFast;
47 return CompressionOption.Fast;
51 return CompressionOption.Normal;
56 return CompressionOption.Maximum;
59 return CompressionOption.NotCompressed;
63 public static long CurrentFilePosition (UnzipHandle handle)
65 return unztell(handle).ToInt64 ();
68 public static long CurrentFileLength32 (UnzipHandle handle)
71 int result = unzGetCurrentFileInfo_32 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0);
72 return result != 0 ? -1 : (long) info.uncompressed_size;
75 public static long CurrentFileLength64 (UnzipHandle handle)
78 int result = unzGetCurrentFileInfo_64 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0);
79 return result != 0 ? -1 : (long) info.uncompressed_size;
82 static string GetCurrentFileName32 (UnzipHandle handle)
85 if (unzGetCurrentFileInfo_32 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0) != 0)
87 var sbName = new StringBuilder ((int) info.size_filename + 1); // +1 to account for extra \0 at the end
88 if (unzGetCurrentFileInfo_32 (handle, out info, sbName, (uint) sbName.Capacity, IntPtr.Zero, 0, null, 0) != 0)
90 return sbName.ToString ();
93 static string GetCurrentFileName64 (UnzipHandle handle)
96 if (unzGetCurrentFileInfo_64 (handle, out info, null, 0, IntPtr.Zero, 0, null, 0) != 0)
98 var sbName = new StringBuilder ((int) info.size_filename + 1); // +1 to account for extra \0 at the end
99 if (unzGetCurrentFileInfo_64 (handle, out info, sbName, (uint) sbName.Capacity, IntPtr.Zero, 0, null, 0) != 0)
101 return sbName.ToString ();
104 public static string[] GetFiles32 (UnzipHandle handle)
106 return GetFiles (handle, GetCurrentFileName32);
109 public static string[] GetFiles64 (UnzipHandle handle)
111 return GetFiles (handle, GetCurrentFileName64);
114 private static string[] GetFiles (UnzipHandle handle, Func<UnzipHandle, string> getCurrentFileName)
116 GoToFirstFile (handle);
117 var files = new List<string> ();
119 while ((name = getCurrentFileName (handle)) != null) {
121 if (!NativeUnzip.GoToNextFile (handle))
125 return files.ToArray ();
128 static void GoToFirstFile (UnzipHandle handle)
130 if (NativeUnzip.unzGoToFirstFile (handle) != 0)
131 throw new Exception ("Zip file is invalid");
134 static bool GoToNextFile (UnzipHandle handle)
136 return unzGoToNextFile(handle) == 0;
139 public static UnzipHandle OpenArchive32 (ZlibFileFuncDef32 fileFuncs)
141 UnzipHandle handle = unzOpen2_32 ("", ref fileFuncs);
142 if (handle.IsInvalid)
143 throw new Exception ("Could not open unzip archive");
147 public static UnzipHandle OpenArchive64 (ZlibFileFuncDef64 fileFuncs)
149 UnzipHandle handle = unzOpen2_64 ("", ref fileFuncs);
150 if (handle.IsInvalid)
151 throw new Exception ("Could not open unzip archive");
155 public static void OpenFile (UnzipHandle handle, string name, out CompressionOption level)
157 if (unzLocateFile (handle, name, (int) ZipStringComparison.CaseInsensitive) != 0)
158 throw new Exception ("The file doesn't exist");
160 int method, compression;
161 // '0' means do not open in raw mode (raw == do not decompress)
162 if (unzOpenCurrentFile2 (handle, out method, out compression, 0) != 0)
163 throw new Exception ("The file could not be opened");
165 level = ConvertCompression (method == 0 ? 0 : compression);
168 public static unsafe int Read (UnzipHandle handle, byte[] buffer, int offset, int count)
170 if ((buffer.Length - offset) > count)
171 throw new ArgumentOutOfRangeException ("count", "Buffer is too small to read that amount of data");
173 fixed (byte * b = &buffer[offset])
174 return unzReadCurrentFile (handle, b, (uint)count);
177 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
178 static extern int unzCloseCurrentFile (UnzipHandle handle);
180 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
181 static extern IntPtr unztell (UnzipHandle handle);
183 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
184 static extern int unzGoToFirstFile (UnzipHandle handle);
186 [DllImport ("MonoPosixHelper", EntryPoint="unzOpen2", CallingConvention=CallingConvention.Cdecl)]
187 static extern UnzipHandle unzOpen2_32 (string path,
188 ref ZlibFileFuncDef32 pzlib_filefunc_def);
190 [DllImport ("MonoPosixHelper", EntryPoint="unzOpen2", CallingConvention=CallingConvention.Cdecl)]
191 static extern UnzipHandle unzOpen2_64 (string path,
192 ref ZlibFileFuncDef64 pzlib_filefunc_def);
194 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
195 static extern int unzGoToNextFile (UnzipHandle handle);
197 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
198 static extern int unzLocateFile (UnzipHandle handle,
200 int iCaseSensitivity);
202 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
203 static extern int unzOpenCurrentFile2 (UnzipHandle handle,
208 [DllImport ("MonoPosixHelper", EntryPoint="unzGetCurrentFileInfo", CallingConvention=CallingConvention.Cdecl)]
209 static extern int unzGetCurrentFileInfo_32 (UnzipHandle handle,
210 out UnzipFileInfo32 pfile_info,
211 StringBuilder szFileName,
212 uint fileNameBufferSize, // uLong
213 IntPtr extraField, // void *
214 uint extraFieldBufferSize, // uLong
215 StringBuilder szComment,
216 uint commentBufferSize); // uLong
218 [DllImport ("MonoPosixHelper", EntryPoint="unzGetCurrentFileInfo", CallingConvention=CallingConvention.Cdecl)]
219 static extern int unzGetCurrentFileInfo_64 (UnzipHandle handle,
220 out UnzipFileInfo64 pfile_info,
221 StringBuilder szFileName,
222 ulong fileNameBufferSize, // uLong
223 IntPtr extraField, // void *
224 ulong extraFieldBufferSize, // uLong
225 StringBuilder szComment,
226 ulong commentBufferSize); // uLong
228 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
229 static unsafe extern int unzReadCurrentFile (UnzipHandle handle,
233 //[DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
234 //static extern int unzSetOffset (UnzipHandle handle, IntPtr pos); // uLong
236 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
237 static extern int unzClose (UnzipHandle handle);