47e277bdbfb05bbd356e31e95698256b54e15ca6
[mono.git] / mcs / class / WindowsBase / ZipSharp / NativeUnzip.cs
1 // NativeUnzip.cs created with MonoDevelop
2 // User: alan at 13:11 20/10/2008
3 //
4 // To change standard headers go to Edit->Preferences->Coding->Standard Headers
5 //
6
7 using System;
8 using System.Collections.Generic;
9 using System.IO;
10 using System.IO.Packaging;
11 using System.Runtime.InteropServices;
12 using System.Text;
13
14 namespace zipsharp
15 {
16         static class NativeUnzip
17         {
18                 enum ZipStringComparison
19                 {
20                         OSDefault = 0,
21                         CaseSensitive = 1,
22                         CaseInsensitive = 2
23                 }
24                 
25                 public static void CloseArchive (UnzipHandle handle)
26                 {
27                         unzClose (handle);
28                         handle.SetHandleAsInvalid ();
29                 }
30
31                 public static void CloseCurrentFile (UnzipHandle handle)
32                 {
33                         if (unzCloseCurrentFile (handle) != 0)
34                                 throw new Exception ("Could not close the active file");
35                 }
36
37                 static CompressionOption ConvertCompression (int compressionLevel)
38                 {
39                         switch (compressionLevel)
40                         {
41                         case 1:
42                         case 2:
43                                 return CompressionOption.SuperFast;
44                                 
45                         case 3:
46                         case 4:
47                                 return CompressionOption.Fast;
48                                 
49                         case 5:
50                         case 6:
51                                 return CompressionOption.Normal;
52                                 
53                         case 7:
54                         case 8:
55                         case 9:
56                                 return CompressionOption.Maximum;
57
58                         default:
59                                 return CompressionOption.NotCompressed;
60                         }
61                 }
62
63                 public static long CurrentFilePosition (UnzipHandle handle)
64                 {
65                         return unztell(handle).ToInt64 ();
66                 }
67
68                 public static long CurrentFileLength (UnzipHandle handle)
69                 {
70                         UnzipFileInfo info;
71                         StringBuilder sbName = new StringBuilder (128);
72                         int result = unzGetCurrentFileInfo (handle, out info, sbName, new IntPtr (sbName.Capacity), IntPtr.Zero, IntPtr.Zero, null,  IntPtr.Zero);
73                         
74                         if (result != 0)
75                                 return -1;
76                         else
77                                 return (long)info.UncompressedSize;
78                 }
79                 
80                 static string GetCurrentFileName (UnzipHandle handle)
81                 {
82                         UnzipFileInfo info;
83                         StringBuilder sbName = new StringBuilder (128);
84                         int result = unzGetCurrentFileInfo (handle, out info, sbName, new IntPtr (sbName.Capacity), IntPtr.Zero, new IntPtr (0), null,  IntPtr.Zero);
85                         
86                         if (result != 0)
87                                 return null;
88                         else
89                                 return sbName.ToString ();
90                 }
91
92                 public static string[] GetFiles (UnzipHandle handle)
93                 {
94                         List<string> files = new List<string> ();
95
96                         GoToFirstFile (handle);
97
98                         string name;
99                         while ((name = GetCurrentFileName(handle)) != null)
100                         {
101                                 files.Add (name);
102                                 if (!NativeUnzip.GoToNextFile (handle))
103                                         break;
104                         }
105                         
106                         return files.ToArray ();
107                 }
108
109                 static void GoToFirstFile (UnzipHandle handle)
110                 {
111                         if (NativeUnzip.unzGoToFirstFile (handle) != 0)
112                                 throw new Exception ("Zip file is invalid");
113                 }
114
115                 static bool GoToNextFile (UnzipHandle handle)
116                 {
117                         return unzGoToNextFile(handle) == 0;
118                 }
119                 
120                 public static UnzipHandle OpenArchive (ZlibFileFuncDef fileFuncs)
121                 {
122                         UnzipHandle handle = unzOpen2 ("", ref fileFuncs);
123                         if (handle.IsInvalid)
124                                 throw new Exception ("Could not open unzip archive");
125                         return handle;
126                 }
127
128                 public static void OpenFile (UnzipHandle handle, string name, out CompressionOption level)
129                 {
130                         if (unzLocateFile (handle, name, (int) ZipStringComparison.CaseInsensitive) != 0)
131                                 throw new Exception ("The file doesn't exist");
132                         
133                         int method, compression;
134                         // '0' means do not open in raw mode (raw == do not decompress)
135                         if (unzOpenCurrentFile2 (handle, out method, out compression, 0) != 0)
136                                 throw new Exception ("The file could not be opened");
137
138                         level = ConvertCompression (method == 0 ? 0 : compression);
139                 }
140
141                 public static unsafe int Read (UnzipHandle handle, byte[] buffer, int offset, int count)
142                 {
143                         if ((buffer.Length - offset) > count)
144                                 throw new ArgumentOutOfRangeException ("count", "Buffer is too small to read that amount of data");
145                         
146                         fixed (byte * b = &buffer[offset])
147                                 return unzReadCurrentFile (handle, b, (uint)count);
148                 }
149
150                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
151                 static extern int unzCloseCurrentFile (UnzipHandle handle);
152
153                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
154                 static extern IntPtr unztell (UnzipHandle handle);
155                 
156                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
157                 static extern int unzGoToFirstFile (UnzipHandle handle);
158
159                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
160                 static extern UnzipHandle unzOpen2 (string path,
161                                                             ref ZlibFileFuncDef pzlib_filefunc_def);
162
163                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
164                 static extern int unzGoToNextFile (UnzipHandle handle);
165
166                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
167                 static extern int unzLocateFile (UnzipHandle handle,
168                                                          string szFileName,
169                                                          int iCaseSensitivity);
170
171                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
172                 static extern int unzOpenCurrentFile2 (UnzipHandle handle,
173                                                        out int method,
174                                                        out int level,
175                                                        int raw);
176
177                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
178                 static extern int unzGetCurrentFileInfo (UnzipHandle handle,
179                                                                  out UnzipFileInfo pfile_info,
180                                                                  StringBuilder szFileName,
181                                                                  IntPtr fileNameBufferSize,   // uLong
182                                                                  IntPtr extraField,           // void *
183                                                                  IntPtr extraFieldBufferSize, // uLong
184                                                                  StringBuilder szComment,
185                                                                  IntPtr commentBufferSize);   // uLong
186
187                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
188                 static unsafe extern int unzReadCurrentFile (UnzipHandle handle,
189                                                               byte* buf, // voidp
190                                                               uint len);
191
192                 //[DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
193                 //static extern int unzSetOffset (UnzipHandle handle, IntPtr pos); // uLong
194                 
195                 [DllImport ("MonoPosixHelper", CallingConvention=CallingConvention.Cdecl)]
196                 static extern int unzClose (UnzipHandle handle);
197         }
198 }