/Tools/ZipIt/ZipIt.cs
C# | 495 lines | 431 code | 40 blank | 24 comment | 29 complexity | 01d08241198ad4577ccc8f3abaabe2c6 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0
- // ZipIt.cs
- //
- // ----------------------------------------------------------------------
- // Copyright (c) 2006-2011 Dino Chiesa. All rights reserved.
- //
- // This example is released under the Microsoft Permissive License of
- // October 2006. See the license.txt file accompanying this release for
- // full details.
- //
- // ----------------------------------------------------------------------
- //
- // This utility zips up a set of files and directories specified on the command line.
- //
- // compile with:
- // csc /debug+ /target:exe /r:Ionic.Zip.dll /out:ZipIt.exe ZipIt.cs
- //
- // Fri, 23 Feb 2007 11:51
- //
-
- using System;
- using System.IO;
- using Ionic.Zip;
-
- namespace Ionic.Zip.Examples
- {
- public class ZipIt
- {
- private static void Usage()
- {
- string UsageMessage =
- "Zipit.exe: zip up a directory, file, or a set of them, into a zipfile.\n" +
- " Depends on Ionic's DotNetZip library. This is version {0} of the utility.\n" +
- "usage:\n ZipIt.exe <ZipFileToCreate> [arguments]\n" +
- "\narguments: \n" +
- " <directory> | <file> - a directory or file to add to the archive.\n" +
- " -64 - use ZIP64 extensions, for large files or large numbers of files.\n" +
- " -aes - use WinZip-compatible AES 256-bit encryption for entries\n" +
- " subsequently added to the archive. Requires a password.\n" +
- " -cp <codepage> - use the specified numeric codepage to encode entry filenames \n" +
- " and comments, instead of the default IBM437 code page.\n" +
- " (cannot be used with -utf8 option)\n" +
- " -C bzip|deflate|none - use BZip2, Deflate, or No compression, for entries subsequently\n"+
- " added to the zip. The default is DEFLATE.\n"+
- " -d <path> - use the given directory path in the archive for\n" +
- " succeeding items added to the archive.\n" +
- " -D <path> - find files in the given directory on disk.\n" +
- " -e[s|r|q|a] - when there is an error reading a file to be zipped, either skip\n" +
- " the file, retry, quit, or ask the user what to do.\n"+
- " -E <selector> - a file selection expression. Examples: \n" +
- " *.txt \n" +
- " (name = *.txt) OR (name = *.xml) \n" +
- " (attrs = H) OR (name != *.xml) \n" +
- " (ctime < 2009/02/28-10:20:00) \n" +
- " (size > 1g) AND (mtime < 2009-12-10) \n" +
- " (ctime > 2009-04-29) AND (size < 10kb) \n" +
- " Filenames can include full paths. You must surround a filename \n" +
- " that includes spaces with single quotes.\n" +
- " -j- - do not traverse NTFS junctions\n" +
- " -j+ - traverse NTFS junctions (default)\n" +
- " -L <level> - compression level, 0..9 (Default is 6).\n" +
- " This applies only if using DEFLATE compression, the default.\n" +
- " -p <password> - apply the specified password for all succeeding files added.\n" +
- " use \"\" to reset the password to nil.\n" +
- " -progress - emit progress reports (good when creating large zips)\n" +
- " -r- - don't recurse directories (default).\n" +
- " -r+ - recurse directories.\n" +
- " -s <entry> 'string' - insert an entry of the given name into the \n" +
- " archive, with the given string as its content.\n" +
- " -sfx [w|c] - create a self-extracting archive, either a Windows or console app.\n" +
- " (cannot be used with -split)\n"+
- " -split <maxsize> - produce a split zip, with the specified maximum size. You can\n" +
- " optionally use kb or mb as a suffix to the size. \n" +
- " (-split cannot be used with -sfx).\n" +
- " -Tw+ - store Windows-format extended times (default).\n" +
- " -Tw- - don't store Windows-format extended times.\n" +
- " -Tu+ - store Unix-format extended times.\n" +
- " -Tu- - don't store Unix-format extended times (default).\n" +
- " -UTnow - use the same date/time, NOW, for all entries. \n" +
- " -UTnewest - use the same date/time, same as newest entry, for all entries. \n" +
- " -UToldest - use the same date/time, equal to oldest entry, for all entries. \n" +
- " -UT <datetime> - use the same date/time, as specified, for all entries. \n" +
- " -utf8 - use UTF-8 encoding for entry filenames and comments,\n" +
- " instead of the the default IBM437 code page.\n" +
- " (cannot be used with -cp option)\n" +
- " -zc <comment> - use the given comment for the archive.\n";
-
- Console.WriteLine(UsageMessage,
- System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
- Environment.Exit(1);
- }
-
-
- static bool justHadByteUpdate= false;
- static bool isCanceled= false;
- static bool wantProgressReports = false;
-
- private static void SaveProgress(object sender, SaveProgressEventArgs e)
- {
- if (isCanceled)
- {
- e.Cancel = true;
- return;
- }
- if (!wantProgressReports) return;
-
- switch(e.EventType)
- {
- case ZipProgressEventType.Saving_Started:
- Console.WriteLine("Saving: {0}", e.ArchiveName);
- break;
-
- case ZipProgressEventType.Saving_Completed:
- justHadByteUpdate= false;
- Console.WriteLine();
- Console.WriteLine("Done: {0}", e.ArchiveName);
- break;
-
- case ZipProgressEventType.Saving_BeforeWriteEntry:
- if (justHadByteUpdate)
- Console.WriteLine();
- Console.WriteLine(" Writing: {0} ({1}/{2})",
- e.CurrentEntry.FileName, e.EntriesSaved+1, e.EntriesTotal);
- justHadByteUpdate= false;
- break;
-
- case ZipProgressEventType.Saving_AfterWriteEntry:
- break;
-
- case ZipProgressEventType.Saving_EntryBytesRead:
- if (justHadByteUpdate)
- Console.SetCursorPosition(0, Console.CursorTop);
- Console.Write(" {0}/{1} ({2:N0}%)", e.BytesTransferred, e.TotalBytesToTransfer,
- e.BytesTransferred / (0.01 * e.TotalBytesToTransfer ));
- justHadByteUpdate= true;
- break;
- }
- }
-
-
- // Ask the user what he wants to do
- public static void ZipError(object sender, ZipErrorEventArgs e)
- {
- Console.WriteLine("Error reading {0}...", e.FileName);
- Console.WriteLine(" Exception: {0}...", e.Exception);
- ZipEntry entry = e.CurrentEntry;
- string response = null;
- do
- {
- Console.Write("Retry, Skip, or Quit ? (R/S/Q) ");
- response = Console.ReadLine();
- Console.WriteLine();
-
- } while (response != null &&
- response[0]!='S' && response[0]!='s' &&
- response[0]!='R' && response[0]!='r' &&
- response[0]!='Q' && response[0]!='q');
-
-
- e.Cancel = (response[0]=='Q' || response[0]=='q');
-
- if (response[0]=='S' || response[0]=='s')
- entry.ZipErrorAction = ZipErrorAction.Skip;
- else if (response[0]=='R' || response[0]=='r')
- entry.ZipErrorAction = ZipErrorAction.Retry;
- }
-
-
-
- static void CtrlC_Handler(object sender, ConsoleCancelEventArgs args)
- {
- isCanceled = true;
- Console.WriteLine("\nCtrl-C");
- //cleanupCompleted.WaitOne();
- // prevent the process from exiting until cleanup is done:
- args.Cancel = true;
- }
-
-
- public static void Main(String[] args)
- {
- bool saveToStdout = false;
- if (args.Length < 2) Usage();
-
- if (args[0]=="-")
- {
- saveToStdout = true;
- }
- else if (File.Exists(args[0]))
- {
- System.Console.WriteLine("That zip file ({0}) already exists.", args[0]);
- }
-
-
- // Because the comments and filenames on zip entries may be UTF-8
- // System.Console.OutputEncoding = new System.Text.UTF8Encoding();
-
- Console.CancelKeyPress += CtrlC_Handler;
-
- try
- {
- Nullable<SelfExtractorFlavor> flavor = null;
- int codePage = 0;
- ZipEntry e = null;
- int _UseUniformTimestamp = 0;
- DateTime _fixedTimestamp= System.DateTime.Now;
- string entryDirectoryPathInArchive = "";
- string directoryOnDisk = null;
- bool recurseDirectories = false;
- bool wantRecurse = false;
- string actualItem;
-
- // read/update an existing zip, or create a new one.
- using (ZipFile zip = new ZipFile(args[0]))
- {
- zip.StatusMessageTextWriter = System.Console.Out;
- zip.SaveProgress += SaveProgress;
- for (int i = 1; i < args.Length; i++)
- {
- switch (args[i])
- {
- case "-es":
- zip.ZipErrorAction = ZipErrorAction.Skip;
- break;
-
- case "-er":
- zip.ZipErrorAction = ZipErrorAction.Retry;
- break;
-
- case "-eq":
- zip.ZipErrorAction = ZipErrorAction.Throw;
- break;
-
- case "-ea":
- zip.ZipError += ZipError;
- break;
-
- case "-64":
- zip.UseZip64WhenSaving = Zip64Option.Always;
- break;
-
- case "-aes":
- zip.Encryption = EncryptionAlgorithm.WinZipAes256;
- break;
-
- case "-C":
- i++;
- if (args.Length <= i) Usage();
- switch(args[i].ToLower())
- {
- case "b":
- case "bzip":
- case "bzip2":
- zip.CompressionMethod = CompressionMethod.BZip2;
- break;
- case "d":
- case "deflate":
- zip.CompressionMethod = CompressionMethod.Deflate;
- break;
- case "n":
- case "none":
- zip.CompressionMethod = CompressionMethod.None;
- break;
- default:
- Usage();
- break;
- }
- break;
-
- case "-cp":
- i++;
- if (args.Length <= i) Usage();
- System.Int32.TryParse(args[i], out codePage);
- if (codePage != 0)
- {
- zip.AlternateEncoding = System.Text.Encoding.GetEncoding(codePage);
- zip.AlternateEncodingUsage = ZipOption.Always;
- }
- break;
-
- case "-d":
- i++;
- if (args.Length <= i) Usage();
- entryDirectoryPathInArchive = args[i];
- break;
-
- case "-D":
- i++;
- if (args.Length <= i) Usage();
- directoryOnDisk = args[i];
- break;
-
- case "-E":
- i++;
- if (args.Length <= i) Usage();
- wantRecurse = recurseDirectories || args[i].Contains("\\");
- // Console.WriteLine("spec({0})", args[i]);
- // Console.WriteLine("dir({0})", directoryOnDisk);
- // Console.WriteLine("dirInArc({0})", entryDirectoryPathInArchive);
- // Console.WriteLine("recurse({0})", recurseDirectories);
- zip.UpdateSelectedFiles(args[i],
- directoryOnDisk,
- entryDirectoryPathInArchive,
- wantRecurse);
- break;
-
- case "-j-":
- zip.AddDirectoryWillTraverseReparsePoints = false;
- break;
-
- case "-j+":
- zip.AddDirectoryWillTraverseReparsePoints = true;
- break;
-
- case "-L":
- i++;
- if (args.Length <= i) Usage();
- zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)
- System.Int32.Parse(args[i]);
- break;
-
- case "-p":
- i++;
- if (args.Length <= i) Usage();
- zip.Password = (args[i] == "") ? null : args[i];
- break;
-
- case "-progress":
- wantProgressReports = true;
- break;
-
- case "-r-":
- recurseDirectories = false;
- break;
-
- case "-r+":
- recurseDirectories = true;
- break;
-
- case "-s":
- i++;
- if (args.Length <= i) Usage();
- string entryName = args[i];
- i++;
- if (args.Length <= i) Usage();
- string content = args[i];
- e = zip.AddEntry(Path.Combine(entryDirectoryPathInArchive, entryName), content);
- // if (entryComment != null)
- // {
- // e.Comment = entryComment;
- // entryComment = null;
- // }
- break;
-
- case "-sfx":
- i++;
- if (args.Length <= i) Usage();
- if (args[i] != "w" && args[i] != "c") Usage();
- flavor = new Nullable<SelfExtractorFlavor>
- ((args[i] == "w") ? SelfExtractorFlavor.WinFormsApplication : SelfExtractorFlavor.ConsoleApplication);
- break;
-
- case "-split":
- i++;
- if (args.Length <= i) Usage();
- if (args[i].EndsWith("K") || args[i].EndsWith("k"))
- zip.MaxOutputSegmentSize = Int32.Parse(args[i].Substring(0, args[i].Length - 1)) * 1024;
- else if (args[i].EndsWith("M") || args[i].EndsWith("m"))
- zip.MaxOutputSegmentSize = Int32.Parse(args[i].Substring(0, args[i].Length - 1)) * 1024 * 1024;
- else
- zip.MaxOutputSegmentSize = Int32.Parse(args[i]);
- break;
-
- case "-Tw+":
- zip.EmitTimesInWindowsFormatWhenSaving = true;
- break;
-
- case "-Tw-":
- zip.EmitTimesInWindowsFormatWhenSaving = false;
- break;
-
- case "-Tu+":
- zip.EmitTimesInUnixFormatWhenSaving = true;
- break;
-
- case "-Tu-":
- zip.EmitTimesInUnixFormatWhenSaving = false;
- break;
-
- case "-UTnow":
- _UseUniformTimestamp = 1;
- _fixedTimestamp = System.DateTime.UtcNow;
- break;
-
- case "-UTnewest":
- _UseUniformTimestamp = 2;
- break;
-
- case "-UToldest":
- _UseUniformTimestamp = 3;
- break;
-
- case "-UT":
- i++;
- if (args.Length <= i) Usage();
- _UseUniformTimestamp = 4;
- try
- {
- _fixedTimestamp= System.DateTime.Parse(args[i]);
- }
- catch
- {
- throw new ArgumentException("-UT");
- }
- break;
-
- case "-utf8":
- zip.AlternateEncoding = System.Text.Encoding.UTF8;
- zip.AlternateEncodingUsage = ZipOption.Always;
- break;
-
- #if NOT
- case "-c":
- i++;
- if (args.Length <= i) Usage();
- entryComment = args[i]; // for the next entry
- break;
- #endif
-
- case "-zc":
- i++;
- if (args.Length <= i) Usage();
- zip.Comment = args[i];
- break;
-
- default:
- // UpdateItem will add Files or Dirs,
- // recurses subdirectories
- actualItem = Path.Combine(directoryOnDisk ?? ".", args[i]);
- zip.UpdateItem(actualItem, entryDirectoryPathInArchive);
- break;
- }
- }
-
- if (_UseUniformTimestamp > 0)
- {
- if (_UseUniformTimestamp==2)
- {
- // newest
- _fixedTimestamp = new System.DateTime(1601,1,1,0,0,0);
- foreach(var entry in zip)
- {
- if (entry.LastModified > _fixedTimestamp)
- _fixedTimestamp = entry.LastModified;
- }
- }
- else if (_UseUniformTimestamp==3)
- {
- // oldest
- foreach(var entry in zip)
- {
- if (entry.LastModified < _fixedTimestamp)
- _fixedTimestamp = entry.LastModified;
- }
- }
-
- foreach(var entry in zip)
- {
- entry.LastModified = _fixedTimestamp;
- }
- }
-
- if (!flavor.HasValue)
- {
- if (saveToStdout)
- zip.Save(Console.OpenStandardOutput());
- else
- zip.Save();
- }
- else
- {
- if (saveToStdout)
- throw new Exception("Cannot save SFX to stdout, sorry! See http://dotnetzip.codeplex.com/WorkItem/View.aspx?WorkItemId=7246");
- zip.SaveSelfExtractor(args[0], flavor.Value);
-
- }
-
- }
- }
- catch (System.Exception ex1)
- {
- System.Console.WriteLine("Exception: " + ex1);
- }
- }
- }
- }