00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 using System;
00038 using System.IO;
00039 using ICSharpCode.SharpZipLib.Core;
00040
00041 namespace ICSharpCode.SharpZipLib.Zip
00042 {
00046 public class FastZipEvents
00047 {
00051 public ProcessDirectoryDelegate ProcessDirectory;
00052
00056 public ProcessFileDelegate ProcessFile;
00057
00061 public DirectoryFailureDelegate DirectoryFailure;
00062
00066 public FileFailureDelegate FileFailure;
00067
00073 public void OnDirectoryFailure(string directory, Exception e)
00074 {
00075 if ( DirectoryFailure != null ) {
00076 ScanFailureEventArgs args = new ScanFailureEventArgs(directory, e);
00077 DirectoryFailure(this, args);
00078 }
00079 }
00080
00086 public void OnFileFailure(string file, Exception e)
00087 {
00088 if ( FileFailure != null ) {
00089 ScanFailureEventArgs args = new ScanFailureEventArgs(file, e);
00090 FileFailure(this, args);
00091 }
00092 }
00093
00098 public void OnProcessFile(string file)
00099 {
00100 if ( ProcessFile != null ) {
00101 ScanEventArgs args = new ScanEventArgs(file);
00102 ProcessFile(this, args);
00103 }
00104 }
00105
00111 public void OnProcessDirectory(string directory, bool hasMatchingFiles)
00112 {
00113 if ( ProcessDirectory != null ) {
00114 DirectoryEventArgs args = new DirectoryEventArgs(directory, hasMatchingFiles);
00115 ProcessDirectory(this, args);
00116 }
00117 }
00118
00119 }
00120
00125 public class FastZip
00126 {
00130 public FastZip()
00131 {
00132 this.events = null;
00133 }
00134
00139 public FastZip(FastZipEvents events)
00140 {
00141 this.events = events;
00142 }
00143
00147 public enum Overwrite {
00151 Prompt,
00155 Never,
00159 Always
00160 }
00161
00165 public bool CreateEmptyDirectories
00166 {
00167 get { return createEmptyDirectories; }
00168 set { createEmptyDirectories = value; }
00169 }
00170
00174 public delegate bool ConfirmOverwriteDelegate(string fileName);
00175
00184 public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter, string directoryFilter)
00185 {
00186 NameTransform = new ZipNameTransform(true, sourceDirectory);
00187 this.sourceDirectory = sourceDirectory;
00188
00189 outputStream = new ZipOutputStream(File.Create(zipFileName));
00190 try {
00191 FileSystemScanner scanner = new FileSystemScanner(fileFilter, directoryFilter);
00192 scanner.ProcessFile += new ProcessFileDelegate(ProcessFile);
00193 if ( this.CreateEmptyDirectories ) {
00194 scanner.ProcessDirectory += new ProcessDirectoryDelegate(ProcessDirectory);
00195 }
00196 scanner.Scan(sourceDirectory, recurse);
00197 }
00198 finally {
00199 outputStream.Close();
00200 }
00201 }
00202
00210 public void CreateZip(string zipFileName, string sourceDirectory, bool recurse, string fileFilter)
00211 {
00212 CreateZip(zipFileName, sourceDirectory, recurse, fileFilter, null);
00213 }
00214
00221 public void ExtractZip(string zipFileName, string targetDirectory, string fileFilter)
00222 {
00223 ExtractZip(zipFileName, targetDirectory, Overwrite.Always, null, fileFilter, null);
00224 }
00225
00235 public void ExtractZip(string zipFileName, string targetDirectory,
00236 Overwrite overwrite, ConfirmOverwriteDelegate confirmDelegate,
00237 string fileFilter, string directoryFilter)
00238 {
00239 if ((overwrite == Overwrite.Prompt) && (confirmDelegate == null)) {
00240 throw new ArgumentNullException("confirmDelegate");
00241 }
00242 this.overwrite = overwrite;
00243 this.confirmDelegate = confirmDelegate;
00244 this.targetDirectory = targetDirectory;
00245 this.fileFilter = new NameFilter(fileFilter);
00246 this.directoryFilter = new NameFilter(directoryFilter);
00247
00248 inputStream = new ZipInputStream(File.OpenRead(zipFileName));
00249
00250 try {
00251
00252 if (password != null) {
00253 inputStream.Password = password;
00254 }
00255
00256 ZipEntry entry;
00257 while ( (entry = inputStream.GetNextEntry()) != null ) {
00258 if ( this.directoryFilter.IsMatch(Path.GetDirectoryName(entry.Name)) && this.fileFilter.IsMatch(entry.Name) ) {
00259 ExtractEntry(entry);
00260 }
00261 }
00262 }
00263 finally {
00264 inputStream.Close();
00265 }
00266 }
00267
00268 void ProcessDirectory(object sender, DirectoryEventArgs e)
00269 {
00270 if ( !e.HasMatchingFiles && createEmptyDirectories ) {
00271 if ( events != null ) {
00272 events.OnProcessDirectory(e.Name, e.HasMatchingFiles);
00273 }
00274
00275 if (e.Name != sourceDirectory) {
00276 string cleanedName = nameTransform.TransformDirectory(e.Name);
00277 ZipEntry entry = new ZipEntry(cleanedName);
00278 outputStream.PutNextEntry(entry);
00279 }
00280 }
00281 }
00282
00283 void ProcessFile(object sender, ScanEventArgs e)
00284 {
00285 if ( events != null ) {
00286 events.OnProcessFile(e.Name);
00287 }
00288 string cleanedName = nameTransform.TransformFile(e.Name);
00289 ZipEntry entry = new ZipEntry(cleanedName);
00290 outputStream.PutNextEntry(entry);
00291 AddFileContents(e.Name);
00292 }
00293
00294 void AddFileContents(string name)
00295 {
00296 if ( buffer == null ) {
00297 buffer = new byte[4096];
00298 }
00299
00300 FileStream stream = File.OpenRead(name);
00301 try {
00302 int length;
00303 do {
00304 length = stream.Read(buffer, 0, buffer.Length);
00305 outputStream.Write(buffer, 0, length);
00306 } while ( length > 0 );
00307 }
00308 finally {
00309 stream.Close();
00310 }
00311 }
00312
00313 void ExtractFileEntry(ZipEntry entry, string targetName)
00314 {
00315 bool proceed = true;
00316 if ((overwrite == Overwrite.Prompt) && (confirmDelegate != null)) {
00317 if (File.Exists(targetName) == true) {
00318 proceed = confirmDelegate(targetName);
00319 }
00320 }
00321
00322 if ( proceed ) {
00323
00324 if ( events != null ) {
00325 events.OnProcessFile(entry.Name);
00326 }
00327
00328 FileStream streamWriter = File.Create(targetName);
00329
00330 try {
00331 if ( buffer == null ) {
00332 buffer = new byte[4096];
00333 }
00334
00335 int size;
00336
00337 do {
00338 size = inputStream.Read(buffer, 0, buffer.Length);
00339 streamWriter.Write(buffer, 0, size);
00340 } while (size > 0);
00341 }
00342 finally {
00343 streamWriter.Close();
00344 }
00345
00346 if (restoreDateTime) {
00347 File.SetLastWriteTime(targetName, entry.DateTime);
00348 }
00349 }
00350 }
00351
00352 bool NameIsValid(string name)
00353 {
00354 return name != null && name.Length > 0 && name.IndexOfAny(Path.InvalidPathChars) < 0;
00355 }
00356
00357 void ExtractEntry(ZipEntry entry)
00358 {
00359 bool doExtraction = NameIsValid(entry.Name);
00360
00361 string dirName = null;
00362 string targetName = null;
00363
00364 if ( doExtraction ) {
00365 string entryFileName;
00366 if (Path.IsPathRooted(entry.Name)) {
00367 string workName = Path.GetPathRoot(entry.Name);
00368 workName = entry.Name.Substring(workName.Length);
00369 entryFileName = Path.Combine(Path.GetDirectoryName(workName), Path.GetFileName(entry.Name));
00370 } else {
00371 entryFileName = entry.Name;
00372 }
00373
00374 targetName = Path.Combine(targetDirectory, entryFileName);
00375 dirName = Path.GetDirectoryName(Path.GetFullPath(targetName));
00376
00377 doExtraction = doExtraction && (entryFileName.Length > 0);
00378 }
00379
00380 if ( doExtraction && !Directory.Exists(dirName) )
00381 {
00382 if ( !entry.IsDirectory || this.CreateEmptyDirectories ) {
00383 try {
00384 Directory.CreateDirectory(dirName);
00385 }
00386 catch {
00387 doExtraction = false;
00388 }
00389 }
00390 }
00391
00392 if ( doExtraction && entry.IsFile ) {
00393 ExtractFileEntry(entry, targetName);
00394 }
00395 }
00396
00400 public ZipNameTransform NameTransform
00401 {
00402 get { return nameTransform; }
00403 set {
00404 if ( value == null ) {
00405 nameTransform = new ZipNameTransform();
00406 }
00407 else {
00408 nameTransform = value;
00409 }
00410 }
00411 }
00412
00413 #region Instance Fields
00414 byte[] buffer;
00415 ZipOutputStream outputStream;
00416 ZipInputStream inputStream;
00417 string password = null;
00418 string targetDirectory;
00419 string sourceDirectory;
00420 NameFilter fileFilter;
00421 NameFilter directoryFilter;
00422 Overwrite overwrite;
00423 ConfirmOverwriteDelegate confirmDelegate;
00424 bool restoreDateTime = false;
00425 bool createEmptyDirectories = false;
00426 FastZipEvents events;
00427 ZipNameTransform nameTransform;
00428 #endregion
00429 }
00430 }