Files
UnrealEngine/Engine/Source/ThirdParty/DotNetZip/Tools/WinFormsApp/ZipForm.cs
2025-05-18 13:04:45 +08:00

2155 lines
83 KiB
C#

// ZipForm.cs
// ------------------------------------------------------------------
//
// Copyright (c) 2009-2011 Dino Chiesa
// All rights reserved.
//
// This code module is part of DotNetZip, a zipfile class library.
//
// ------------------------------------------------------------------
//
// This code is licensed under the Microsoft Public License.
// See the file License.txt for the license details.
// More info on: http://dotnetzip.codeplex.com
//
// ------------------------------------------------------------------
//
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows.Forms;
using Ionic.Zip;
namespace Ionic.Zip.Forms
{
public partial class ZipForm : Form
{
delegate void ZipProgress(ZipProgressEventArgs e);
delegate void ButtonClick(object sender, EventArgs e);
HiResTimer _hrt;
public ZipForm()
{
InitializeComponent();
InitializeListboxes();
FixTitle();
FillFormFromRegistry();
AdoptProgressBars();
SetListView2();
SetTextBoxes();
// first run only
if (numRuns == 0)
this.tabControl1.SelectedIndex = 2; // help/about tab
}
// This constructor works to load zips from the command line.
// It also works to allow "open With..." from Windows Explorer.
public ZipForm(string[] args)
: this()
{
if (args != null && args.Length >= 1 && args[0] != null)
_initialFileToLoad = args[0];
}
// in ZipForm.DragDrop.cs
partial void SetDragDrop();
private void SetTextBoxes()
{
this.tbComment.Text= TB_COMMENT_NOTE;
this.tbDefaultExtractDirectory.Text= TB_EXTRACT_DIR_NOTE;
this.tbExeOnUnpack.Text= TB_EXE_ON_UNPACK_NOTE;
// set autocomplete on a few textboxes
this.tbDirectoryToZip.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbDirectoryToZip.AutoCompleteSource = AutoCompleteSource.FileSystemDirectories;
this.tbExtractDir.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbExtractDir.AutoCompleteSource = AutoCompleteSource.FileSystemDirectories;
this.tbZipToOpen.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbZipToOpen.AutoCompleteSource = AutoCompleteSource.FileSystem;
this.tbZipToCreate.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbZipToCreate.AutoCompleteSource = AutoCompleteSource.FileSystem;
this.tbSelectionToExtract.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbSelectionToExtract.AutoCompleteSource = AutoCompleteSource.CustomSource;
this.tbSelectionToExtract.AutoCompleteCustomSource = _selectionCompletions;
this.tbSelectionToZip.AutoCompleteMode = AutoCompleteMode.Suggest;
this.tbSelectionToZip.AutoCompleteSource = AutoCompleteSource.CustomSource;
this.tbSelectionToZip.AutoCompleteCustomSource = _selectionCompletions;
tbExeOnUnpack_TextChanged(null, null);
}
private void SetListView2()
{
// The listview2 is a ListViewEx control, an extension of
// System.Windows.Forms.ListView that allows editing of subitems using arbitrary
// controls. You can have a textbox, a datepicker, or other controls.
// I want the user to be able to modify the directory-in-archive value in the
// list, which is why ListViewEx is interesting.
// I also want a checkbox associated to each list item, but I don't want the
// checkbox attached to the first subitem, as it normally is in a ListView. So I
// put an empty string as the main ListView item (subitem #0), and then the
// filename and directory-in-archive value in the 2nd and 3rd columns (subitems 1
// and 2). This way, the checkbox gets its own column.
// Next twist is I want the checkbox label to be uneditable, which is easy
// by just installing a listView2_BeforeLabelEdit method and always cancelling
// it. (e.CancelEdit = true).
// And then there is a "master checkbox" at the column header that indicates
// whether the state of all checkboxes in the list is the same. With the "check
// change" of any item in the list I want to see if the master should be checked
// or unchecked.
// The final thing is I want the checkbox for each item to change state only if I
// click on the checkbox itself, rather than "anywhere in the item row".
this.listView2.SubItemClicked += new ListViewEx.SubItemEventHandler(listView2_SubItemClicked);
this.listView2.SubItemEndEditing += new ListViewEx.SubItemEndEditingEventHandler(listView2_SubItemEndEditing);
this.listView2.DoubleClickActivation = true;
SetDragDrop();
}
private void AdoptProgressBars()
{
tabControl1_SelectedIndexChanged(null, null);
}
private void FixTitle()
{
this.Text = String.Format("DotNetZip Tool v{0}",
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString());
}
private void InitializeListboxes()
{
InitEncodingsList();
InitFlavorList();
InitZip64List();
InitCompMethodList();
InitCompressionLevelList();
InitEncryptionList();
InitSplitBox();
InitExtractExistingFileList();
}
private void InitSplitBox()
{
string[] values = { "-none-", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb", "512mb", "1gb" };
foreach (var value in values)
this.comboSplit.Items.Add(value);
this.comboSplit.SelectedIndex = 0;
this.comboSplit.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
//this.comboSplit.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
}
private void InitEncryptionList()
{
List<String> _EncryptionNames = new List<string>(Enum.GetNames(typeof(Ionic.Zip.EncryptionAlgorithm)));
foreach (var name in _EncryptionNames)
{
if (name != "Unsupported")
comboEncryption.Items.Add(name);
}
// select the first item:
comboEncryption.SelectedIndex = 0;
this.tbPassword.Text = "";
}
private void InitExtractExistingFileList()
{
List<String> _ExtractActionNames = new List<string>(Enum.GetNames(typeof(Ionic.Zip.ExtractExistingFileAction)));
foreach (var name in _ExtractActionNames)
{
if (!name.StartsWith("Invoke"))
{
if (name.StartsWith("Throw"))
comboExistingFileAction.Items.Add("Stop");
else
comboExistingFileAction.Items.Add(name);
}
}
// select the first item:
comboExistingFileAction.SelectedIndex = 0;
}
private void InitEncodingsList()
{
List<String> _EncodingNames = new List<string>();
var e = System.Text.Encoding.GetEncodings();
foreach (var e1 in e)
{
if (!_EncodingNames.Contains(e1.Name))
if (!_EncodingNames.Contains(e1.Name.ToUpper()))
if (!_EncodingNames.Contains(e1.Name.ToLower()))
if (e1.Name != "IBM437" && e1.Name != "utf-8")
_EncodingNames.Add(e1.Name);
}
_EncodingNames.Sort();
comboEncoding.Items.Add("zip default (IBM437)");
comboEncoding.Items.Add("utf-8");
foreach (var name in _EncodingNames)
{
comboEncoding.Items.Add(name);
}
// select the first item:
comboEncoding.SelectedIndex = 0;
// also set the encoding usage
List<String> _UsageNames = new List<string>(Enum.GetNames(typeof(Ionic.Zip.ZipOption)));
_UsageNames.Sort();
foreach (var name in _UsageNames)
{
if (!name.StartsWith("Default"))
comboEncodingUsage.Items.Add(name);
}
// select the first item:
comboEncodingUsage.SelectedIndex = 0;
}
private void InitCompressionLevelList()
{
List<String> _CompressionLevelNames = new List<string>(Enum.GetNames(typeof(Ionic.Zlib.CompressionLevel)));
_CompressionLevelNames.Sort();
foreach (var name in _CompressionLevelNames)
{
if (!name.StartsWith("Level"))
{
comboCompLevel.Items.Add(name);
}
}
// select the 2nd item, "Default":
comboCompLevel.SelectedIndex = 2;
}
private void InitFlavorList()
{
this.comboFlavor.Items.Add("traditional Zip");
this.comboFlavor.Items.Add("Self-extractor (GUI)");
this.comboFlavor.Items.Add("Self-extractor (CMD)");
// select the first item:
comboFlavor.SelectedIndex = 0;
}
private void InitZip64List()
{
var _Names = new List<string>(Enum.GetNames(typeof(Ionic.Zip.Zip64Option)));
_Names.Sort();
foreach (var name in _Names)
{
if (!name.StartsWith("Default"))
comboZip64.Items.Add(name);
}
// select the first item:
comboZip64.SelectedIndex = 0;
}
private void InitCompMethodList()
{
var _Names = new List<string>(Enum.GetNames(typeof(Ionic.Zip.CompressionMethod)));
_Names.Sort();
foreach (var name in _Names)
{
if (!name.StartsWith("Default"))
comboCompMethod.Items.Add(name);
}
// select DEFLATE:
comboCompMethod.SelectedIndex = 1;
}
private void KickoffZipup()
{
if (String.IsNullOrEmpty(this.tbDirectoryToZip.Text)) return;
if (!System.IO.Directory.Exists(this.tbDirectoryToZip.Text))
{
var dlgResult = MessageBox.Show(String.Format("The directory you have specified ({0}) does not exist.", this.tbZipToCreate.Text),
"Not gonna happen", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
if (this.tbZipToCreate.Text == null || this.tbZipToCreate.Text == "") return;
// check for existence of the zip file:
if (System.IO.File.Exists(this.tbZipToCreate.Text))
{
var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) already exists. Do you want to overwrite this file?", this.tbZipToCreate.Text), "Confirmation is Required", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dlgResult != DialogResult.Yes) return;
System.IO.File.Delete(this.tbZipToCreate.Text);
}
// check for a valid zip file name:
string extension = System.IO.Path.GetExtension(this.tbZipToCreate.Text);
if ((extension != ".exe" && (this.comboFlavor.SelectedIndex == 1 || this.comboFlavor.SelectedIndex == 2)) ||
(extension != ".zip" && this.comboFlavor.SelectedIndex == 0))
{
var dlgResult = MessageBox.Show(String.Format("The file you have specified ({0}) has a non-standard extension ({1}) for this zip flavor. Do you want to continue anyway?",
this.tbZipToCreate.Text, extension), "Hold on there, pardner!", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dlgResult != DialogResult.Yes) return;
System.IO.File.Delete(this.tbZipToCreate.Text);
}
_hrt = new HiResTimer();
_hrt.Start();
_working = true;
_operationCanceled = false;
_nFilesCompleted = 0;
_totalBytesAfterCompress = 0;
_totalBytesBeforeCompress = 0;
PauseUI("Zipping...");
lblStatus.Text = "Zipping...";
var options = new SaveWorkerOptions
{
ZipName = this.tbZipToCreate.Text,
Selection = this.tbSelectionToZip.Text,
TraverseJunctions = this.chkTraverseJunctions.Checked,
Encoding = "ibm437",
//EncodingUsage = ZipOption.Always,
ZipFlavor = this.comboFlavor.SelectedIndex,
Password = this.tbPassword.Text,
WindowsTimes = this.chkWindowsTime.Checked,
UnixTimes = this.chkUnixTime.Checked,
RemoveFilesAfterExe = this.chkRemoveFiles.Checked,
ExtractExistingFile = this.comboExistingFileAction.SelectedIndex,
};
if (this.comboEncoding.SelectedIndex != 0)
options.Encoding = this.comboEncoding.SelectedItem.ToString();
options.Encryption = (EncryptionAlgorithm) Enum.Parse(typeof(EncryptionAlgorithm),
this.comboEncryption.SelectedItem.ToString());
options.CompressionLevel = (Ionic.Zlib.CompressionLevel) Enum.Parse(typeof(Ionic.Zlib.CompressionLevel),
this.comboCompLevel.SelectedItem.ToString());
options.CompressionMethod = (Ionic.Zip.CompressionMethod) Enum.Parse(typeof(Ionic.Zip.CompressionMethod),
this.comboCompMethod.SelectedItem.ToString());
options.EncodingUsage = (Ionic.Zip.ZipOption) Enum.Parse(typeof(Ionic.Zip.ZipOption),
this.comboEncodingUsage.SelectedItem.ToString());
string arg = this.comboSplit.SelectedItem.ToString().ToUpper();
try
{
int multiplier = 1;
int suffixLength = 0;
if (arg.EndsWith("KB"))
{
multiplier = 1024; suffixLength = 2;
}
else if (arg.EndsWith("K"))
{
multiplier = 1024; suffixLength = 1;
}
else if (arg.EndsWith("MB"))
{
multiplier = 1024*1024; suffixLength = 2;
}
else if (arg.EndsWith("M"))
{
multiplier = 1024*1024; suffixLength = 1;
}
else if (arg.EndsWith("GB"))
{
multiplier = 1024*1024*1024; suffixLength = 2;
}
else if (arg.EndsWith("G"))
{
multiplier = 1024*1024*1024; suffixLength = 1;
}
if (suffixLength > 0)
{
options.MaxSegmentSize =
Int32.Parse(arg.Substring(0,arg.Length-suffixLength)) * multiplier;
}
else
options.MaxSegmentSize = Int32.Parse(arg);
}
catch
{
// just reset to "none"
this.comboSplit.SelectedIndex = 0;
options.MaxSegmentSize = 0;
}
options.Zip64 = (Zip64Option)Enum.Parse(typeof(Zip64Option),
this.comboZip64.SelectedItem.ToString());
//this.listView2.Items.ToList();
var entriesList = new System.Collections.ArrayList(this.listView2.Items);
options.Entries = System.Array.ConvertAll((ListViewItem[])entriesList.ToArray(typeof(ListViewItem)), (item) =>
{
return new ItemToAdd
{
LocalFileName = item.SubItems[1].Text,
DirectoryInArchive = item.SubItems[2].Text,
FileNameInArchive = item.SubItems[3].Text,
};
}
);
string compress = (options.CompressionMethod == Ionic.Zip.CompressionMethod.Deflate)
? "Deflate level" + options.CompressionLevel.ToString()
: options.CompressionMethod.ToString();
options.Comment = String.Format("Encoding:{0} || Compression:{1} || Encrypt:{2} || ZIP64:{3}\r\nCreated at {4} || {5}\r\n",
options.Encoding,
compress,
(this.tbPassword.Text == "") ? "None" : options.Encryption.ToString(),
options.Zip64.ToString(),
System.DateTime.Now.ToString("yyyy-MMM-dd HH:mm:ss"),
this.Text);
if (this.tbComment.Text != TB_COMMENT_NOTE)
options.Comment += this.tbComment.Text;
if (this.tbExeOnUnpack.Text != TB_EXE_ON_UNPACK_NOTE)
options.ExeOnUnpack = this.tbExeOnUnpack.Text;
if (this.tbDefaultExtractDirectory.Text != TB_EXTRACT_DIR_NOTE)
options.ExtractDirectory = this.tbDefaultExtractDirectory.Text;
_workerThread = new Thread(this.DoSave);
_workerThread.Name = "Zip Saver thread";
_workerThread.Start(options);
this.Cursor = Cursors.WaitCursor;
}
private string FlavorToString(int p)
{
if (p == 2) return "SFX-CMD";
if (p == 1) return "SFX-GUI";
return "ZIP";
}
private bool _firstFocusInCommentTextBox = true;
private void tbComment_Enter(object sender, EventArgs e)
{
if (_firstFocusInCommentTextBox)
{
tbComment.Text = "";
tbComment.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
tbComment.ForeColor = System.Drawing.SystemColors.WindowText;
_firstFocusInCommentTextBox = false;
}
}
private void tbComment_Leave(object sender, EventArgs e)
{
string TextInTheBox = tbComment.Text;
if ((TextInTheBox == null) || (TextInTheBox == ""))
{
this.tbComment.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.tbComment.ForeColor = System.Drawing.SystemColors.InactiveCaption;
_firstFocusInCommentTextBox = true;
this.tbComment.Text = TB_COMMENT_NOTE;
}
}
private bool _firstFocusInExtractDirTextBox = true;
private void tbDefaultExtractDirectory_Enter(object sender, EventArgs e)
{
if (_firstFocusInExtractDirTextBox)
{
tbDefaultExtractDirectory.Text = "";
tbDefaultExtractDirectory.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
tbDefaultExtractDirectory.ForeColor = System.Drawing.SystemColors.WindowText;
_firstFocusInExtractDirTextBox = false;
}
}
private void tbDefaultExtractDirectory_Leave(object sender, EventArgs e)
{
string TextInTheBox = tbDefaultExtractDirectory.Text;
if ((TextInTheBox == null) || (TextInTheBox == ""))
{
this.tbDefaultExtractDirectory.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.tbDefaultExtractDirectory.ForeColor = System.Drawing.SystemColors.InactiveCaption;
_firstFocusInExtractDirTextBox = true;
this.tbDefaultExtractDirectory.Text = TB_EXTRACT_DIR_NOTE;
}
}
// I want the values in the combobox to be right-aligned.
private int delta = 0;
private void comboBox1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
var rc = new System.Drawing.Rectangle(e.Bounds.X + delta, e.Bounds.Y + delta,
e.Bounds.Width - delta, e.Bounds.Height - delta);
var sf = new System.Drawing.StringFormat
{
Alignment = System.Drawing.StringAlignment.Far
};
string str = (string)comboSplit.Items[e.Index];
if (e.State == (DrawItemState.Selected | DrawItemState.NoAccelerator
| DrawItemState.NoFocusRect) ||
e.State == DrawItemState.Selected)
{
e.Graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.CornflowerBlue), rc);
e.Graphics.DrawString(str, this.comboSplit.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Cyan), rc, sf);
}
else
{
e.Graphics.FillRectangle(new System.Drawing.SolidBrush(System.Drawing.Color.White), rc);
e.Graphics.DrawString(str, this.comboSplit.Font, new System.Drawing.SolidBrush(System.Drawing.Color.Black), rc, sf);
}
}
private bool _firstFocusInExeTextBox = true;
private void tbExeOnUnpack_Enter(object sender, EventArgs e)
{
if (_firstFocusInExeTextBox)
{
tbExeOnUnpack.Text = "";
tbExeOnUnpack.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
tbExeOnUnpack.ForeColor = System.Drawing.SystemColors.WindowText;
_firstFocusInExeTextBox = false;
}
}
private void tbExeOnUnpack_Leave(object sender, EventArgs e)
{
string TextInTheBox = tbExeOnUnpack.Text;
if ((TextInTheBox == null) || (TextInTheBox == ""))
{
this.tbExeOnUnpack.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.tbExeOnUnpack.ForeColor = System.Drawing.SystemColors.InactiveCaption;
_firstFocusInExeTextBox = true;
this.tbExeOnUnpack.Text = TB_EXE_ON_UNPACK_NOTE;
this.label18.Enabled = false;
this.chkRemoveFiles.Enabled = false;
}
else
{
this.label18.Enabled = true;
this.chkRemoveFiles.Enabled = true;
}
}
private void tbExeOnUnpack_TextChanged(object sender, EventArgs e)
{
if (this.tbExeOnUnpack.Text != TB_EXE_ON_UNPACK_NOTE && this.tbExeOnUnpack.Text != "")
{
this.label18.Enabled = true;
this.chkRemoveFiles.Enabled = true;
}
else
{
this.label18.Enabled = false;
this.chkRemoveFiles.Enabled = false;
}
}
private void SetProgressBars()
{
if (this.progressBar1.InvokeRequired)
{
this.progressBar1.Invoke(new MethodInvoker(this.SetProgressBars));
//this.progressBar1.Invoke(new ProgressBarSetup(this.SetProgressBars), new object[] { count });
}
else
{
this.progressBar1.Value = 0;
this.progressBar1.Maximum = _totalEntriesToProcess;
this.progressBar1.Minimum = 0;
this.progressBar1.Step = 1;
this.progressBar2.Value = 0;
this.progressBar2.Minimum = 0;
this.progressBar2.Maximum = 1; // will be set later, for each entry.
this.progressBar2.Step = 1;
}
}
private void DoSave(Object p)
{
SaveWorkerOptions options = p as SaveWorkerOptions;
try
{
using (var zip1 = new ZipFile())
{
zip1.CompressionMethod = options.CompressionMethod;
zip1.CompressionLevel = options.CompressionLevel;
zip1.AlternateEncoding = System.Text.Encoding.GetEncoding(options.Encoding);
zip1.AlternateEncodingUsage = options.EncodingUsage;
zip1.Comment = options.Comment;
zip1.MaxOutputSegmentSize = options.MaxSegmentSize;
zip1.Password = (options.Password != "") ? options.Password : null;
zip1.Encryption = options.Encryption;
zip1.EmitTimesInWindowsFormatWhenSaving = options.WindowsTimes;
zip1.EmitTimesInUnixFormatWhenSaving = options.UnixTimes;
zip1.AddDirectoryWillTraverseReparsePoints = options.TraverseJunctions;
foreach (ItemToAdd item in options.Entries)
{
var e = zip1.AddItem(item.LocalFileName, item.DirectoryInArchive);
// use a different name in the archive if appropriate
if (!String.IsNullOrEmpty(item.FileNameInArchive) && item.FileNameInArchive != System.IO.Path.GetFileName(item.LocalFileName))
e.FileName = item.FileNameInArchive;
}
_totalEntriesToProcess = zip1.EntryFileNames.Count;
SetProgressBars();
zip1.TempFileFolder = System.IO.Path.GetDirectoryName(options.ZipName);
zip1.SaveProgress += this.zip1_SaveProgress;
zip1.UseZip64WhenSaving = options.Zip64;
if (options.ZipFlavor == 2 || options.ZipFlavor == 1)
{
SelfExtractorSaveOptions sfxOptions = new SelfExtractorSaveOptions()
{
Flavor = (options.ZipFlavor == 1)?SelfExtractorFlavor.WinFormsApplication:
SelfExtractorFlavor.ConsoleApplication,
DefaultExtractDirectory = options.ExtractDirectory,
PostExtractCommandLine = options.ExeOnUnpack,
RemoveUnpackedFilesAfterExecute = options.RemoveFilesAfterExe,
ExtractExistingFile = (ExtractExistingFileAction) options.ExtractExistingFile,
};
zip1.SaveSelfExtractor(options.ZipName, sfxOptions);
}
else
zip1.Save(options.ZipName);
}
}
catch (System.Exception exc1)
{
MessageBox.Show(String.Format("Exception while zipping:\n{0}\n\n{1}", exc1.Message, exc1.StackTrace.ToString()));
btnCancel_Click(null, null);
}
}
void zip1_SaveProgress(object sender, SaveProgressEventArgs e)
{
switch (e.EventType)
{
case ZipProgressEventType.Saving_AfterWriteEntry:
StepArchiveProgress(e);
break;
case ZipProgressEventType.Saving_EntryBytesRead:
StepEntryProgress(e);
break;
case ZipProgressEventType.Saving_Completed:
SaveCompleted();
break;
case ZipProgressEventType.Saving_AfterSaveTempArchive:
TempArchiveSaved();
break;
}
if (_operationCanceled)
e.Cancel = true;
}
private void TempArchiveSaved()
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new MethodInvoker(this.TempArchiveSaved));
}
else
{
System.TimeSpan ts = new System.TimeSpan(0, 0, (int)_hrt.Seconds);
lblStatus.Text = String.Format("Temp archive saved ({0})...{1}...",
ts.ToString(),
(this.comboFlavor.SelectedIndex == 0)
? "finishing"
: "compiling SFX");
}
}
private void SaveCompleted()
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new MethodInvoker(this.SaveCompleted));
}
else
{
_hrt.Stop();
System.TimeSpan ts = new System.TimeSpan(0, 0, (int)_hrt.Seconds);
lblStatus.Text = String.Format("Done, Compressed {0} files, {1:N0}% of original, time: {2}",
_nFilesCompleted, (100.00 * _totalBytesAfterCompress) / _totalBytesBeforeCompress,
ts.ToString());
ResetUiState();
}
}
private void StepArchiveProgress(ZipProgressEventArgs e)
{
if (this.progressBar1.InvokeRequired)
{
this.progressBar1.Invoke(new ZipProgress(this.StepArchiveProgress), new object[] { e });
}
else
{
if (!_operationCanceled)
{
_nFilesCompleted++;
this.progressBar1.PerformStep();
_totalBytesAfterCompress += e.CurrentEntry.CompressedSize;
_totalBytesBeforeCompress += e.CurrentEntry.UncompressedSize;
// reset the progress bar for the entry:
this.progressBar2.Value = this.progressBar2.Maximum = 1;
this.Update();
#if NOT_SPEEDY
// Sleep here just to show the progress bar, when the number of files is small,
// or when all done.
// You may not want this for actual use!
if (this.progressBar2.Value == this.progressBar2.Maximum)
Thread.Sleep(350);
else if (_entriesToZip < 10)
Thread.Sleep(350);
else if (_entriesToZip < 20)
Thread.Sleep(200);
else if (_entriesToZip < 30)
Thread.Sleep(100);
else if (_entriesToZip < 45)
Thread.Sleep(80);
else if (_entriesToZip < 75)
Thread.Sleep(40);
// more than 75 entries, don't sleep at all.
#endif
}
}
}
private void StepEntryProgress(ZipProgressEventArgs e)
{
if (this.progressBar2.InvokeRequired)
{
this.progressBar2.Invoke(new ZipProgress(this.StepEntryProgress), new object[] { e });
}
else
{
if (!_operationCanceled)
{
if (this.progressBar2.Maximum == 1)
{
// reset
Int64 entryMax = e.TotalBytesToTransfer;
Int64 absoluteMax = System.Int32.MaxValue;
_progress2MaxFactor = 0;
while (entryMax > absoluteMax)
{
entryMax /= 2;
_progress2MaxFactor++;
}
if ((int)entryMax < 0) entryMax *= -1;
this.progressBar2.Maximum = (int)entryMax;
lblStatus.Text = String.Format("{0} of {1} files...({2})",
_nFilesCompleted + 1, _totalEntriesToProcess, e.CurrentEntry.FileName);
}
// downcast is safe here because we have shifted e.BytesTransferred
int xferred = (int)(e.BytesTransferred >> _progress2MaxFactor);
this.progressBar2.Value = (xferred >= this.progressBar2.Maximum)
? this.progressBar2.Maximum
: xferred;
this.Update();
}
}
}
private void btnDirBrowse_Click(object sender, EventArgs e)
{
var dlg1 = new Ionic.Utils.FolderBrowserDialogEx
{
Description = "Select a folder to zip up:",
ShowNewFolderButton = false,
ShowEditBox = true,
//NewStyle = false,
SelectedPath = this.tbDirectoryToZip.Text,
ShowFullPathInEditBox = true,
};
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;
var result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
this.tbDirectoryToZip.Text = dlg1.SelectedPath;
this.tbDirectoryInArchive.Text = System.IO.Path.GetFileName(this.tbDirectoryToZip.Text);
}
}
private void btnCreateZipBrowse_Click(object sender, EventArgs e)
{
var dlg1 = new SaveFileDialog
{
OverwritePrompt = false,
Title = "Where would you like to save the generated Zip file?",
Filter = "ZIP files|*.zip",
};
try
{
dlg1.FileName = System.IO.Path.GetFileName(this.tbZipToCreate.Text);
}
catch
{
dlg1.FileName = "";
}
try
{
dlg1.InitialDirectory = System.IO.Path.GetDirectoryName(this.tbZipToCreate.Text);
}
catch
{
dlg1.InitialDirectory = "";
}
var result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
this.tbZipToCreate.Text = dlg1.FileName;
}
}
private void btnZipup_Click(object sender, EventArgs e)
{
// Do not start zipping while editing a textbox
// in listView2.
if (!textBox1.Visible)
KickoffZipup();
}
private void btnCancel_Click(object sender, EventArgs e)
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new ButtonClick(this.btnCancel_Click), new object[] { sender, e });
}
else
{
_operationCanceled = true;
lblStatus.Text = "Canceled...";
ResetUiState();
}
}
private void comboFlavor_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.comboFlavor.SelectedIndex == 1 || this.comboFlavor.SelectedIndex == 2)
{
// intelligently change the name of the thing to create
// It's an SFX, swap out ZIP and insert EXE
if (this.tbZipToCreate.Text.ToUpper().EndsWith(".ZIP"))
{
tbZipToCreate.Text = System.Text.RegularExpressions.Regex.Replace(tbZipToCreate.Text, "(?i:)\\.zip$", ".exe");
}
// enable/disable other dependent UI elements
this.label17.Enabled = false;
this.comboSplit.Enabled = false;
this.label15.Enabled = true;
this.tbDefaultExtractDirectory.Enabled = true;
this.label16.Enabled = true;
this.tbExeOnUnpack.Enabled = true;
this.label18.Enabled = true;
this.chkRemoveFiles.Enabled = true;
}
else if (this.comboFlavor.SelectedIndex == 0)
{
// intelligently change the name of the thing to create
// It's a regular ZIP, so swap out EXE and insert ZIP
if (this.tbZipToCreate.Text.ToUpper().EndsWith(".EXE"))
{
tbZipToCreate.Text = System.Text.RegularExpressions.Regex.Replace(tbZipToCreate.Text, "(?i:)\\.exe$", ".zip");
}
// enable/disable other dependent UI elements
this.label17.Enabled = true;
this.comboSplit.Enabled = true;
this.label15.Enabled = false;
this.tbDefaultExtractDirectory.Enabled = false;
this.label16.Enabled = false;
this.tbExeOnUnpack.Enabled = false;
this.label18.Enabled = false;
this.chkRemoveFiles.Enabled = false;
}
}
private void comboEncryption_SelectedIndexChanged(object sender, EventArgs e)
{
//this.tbPassword.Enabled = (this.comboBox3.SelectedItem.ToString() != "None");
if (this.comboEncryption.SelectedIndex == 0)
{
this.label9.Enabled = false;
this.tbPassword.Enabled = false;
this.chkHidePassword.Enabled = false;
}
else
{
this.label9.Enabled = true;
this.tbPassword.Enabled = true;
this.chkHidePassword.Enabled = true;
}
}
private void comboCompMethod_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.comboCompMethod.SelectedIndex == 1) // DEFLATE
{
this.label4.Enabled = true;
this.comboCompLevel.Enabled = true;
}
else
{
this.label4.Enabled = false;
this.comboCompLevel.Enabled = false;
}
}
private void comboEncoding_SelectedIndexChanged(object sender, EventArgs e)
{
this.comboEncodingUsage.Enabled = (this.comboEncoding.SelectedIndex != 0);
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
this.tbPassword.PasswordChar = (this.chkHidePassword.Checked) ? '*' : '\0';
}
private void ResetUiState()
{
this.btnZipUp.Text = "Zip it!";
this.btnZipUp.Enabled = true;
this.btnCancel.Text = "Cancel";
this.btnCancel.Enabled = false;
this.btnExtract.Text = "Extract";
this.btnExtractDirBrowse.Enabled = true;
this.btnZipupDirBrowse.Enabled = true;
this.btnReadZipBrowse.Enabled = true;
this.btnClearItemsToZip.Enabled = true;
this.btnCreateZipBrowse.Enabled = true;
this.progressBar1.Value = 0;
this.progressBar2.Value = 0;
this.Cursor = Cursors.Default;
if (_workerThread != null)
if (!_workerThread.IsAlive)
_workerThread.Join();
_working = false;
}
private void SelectNamedEncoding(string s)
{
_SelectComboBoxItem(this.comboEncoding, s);
}
private void SelectNamedEncodingUsage(string s)
{
_SelectComboBoxItem(this.comboEncodingUsage, s);
}
private void SelectNamedCompressionLevel(string s)
{
_SelectComboBoxItem(this.comboCompLevel, s);
}
private void SelectNamedCompressionMethod(string s)
{
_SelectComboBoxItem(this.comboCompMethod, s);
}
private void SelectNamedEncryption(string s)
{
_SelectComboBoxItem(this.comboEncryption, s);
//tbPassword.Text = "";
comboEncryption_SelectedIndexChanged(null, null);
}
private void _SelectComboBoxItem(ComboBox c, string s)
{
for (int i = 0; i < c.Items.Count; i++)
{
if (c.Items[i].ToString() == s)
{
c.SelectedIndex = i;
break;
}
}
}
private void ZipForm_FormClosing(object sender, FormClosingEventArgs e)
{
SaveFormToRegistry();
}
private void btnZipBrowse_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.InitialDirectory = (System.IO.File.Exists(this.tbZipToOpen.Text) ? System.IO.Path.GetDirectoryName(this.tbZipToOpen.Text) : this.tbZipToOpen.Text);
openFileDialog1.Filter = "zip files|*.zip|EXE files|*.exe|All Files|*.*";
openFileDialog1.FilterIndex = 1;
openFileDialog1.RestoreDirectory = true;
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
this.tbZipToOpen.Text = openFileDialog1.FileName;
if (System.IO.File.Exists(this.tbZipToOpen.Text))
btnOpen_Click(sender, e);
}
}
string _DisplayedZip = null;
private void btnOpen_Click(object sender, EventArgs e)
{
if (!System.IO.File.Exists(this.tbZipToOpen.Text)) return;
DisplayZipFile(this.tbZipToOpen.Text);
}
private void DisplayZipFile(string zipFile)
{
try
{
listView1.Clear();
listView1.BeginUpdate();
string[] columnHeaders = new string[] { "n", "name", "lastmod", "original", "ratio", "compressed", "enc?", "CRC" };
foreach (string label in columnHeaders)
{
SortableColumnHeader ch = new SortableColumnHeader(label);
if (label != "name" && label != "lastmod")
ch.TextAlign = HorizontalAlignment.Right;
listView1.Columns.Add(ch);
}
int n = 1;
var readOptions = new ReadOptions
{
Encoding = (comboEncoding.SelectedIndex > 0)
? System.Text.Encoding.GetEncoding(comboEncoding.SelectedItem.ToString())
: System.Text.Encoding.GetEncoding("IBM437")
};
using (ZipFile zip = ZipFile.Read(zipFile, readOptions))
{
foreach (ZipEntry entry in zip.EntriesSorted)
{
ListViewItem item = new ListViewItem(n.ToString());
n++;
string[] subitems = new string[] {
entry.FileName.Replace("/","\\"),
entry.LastModified.ToString("yyyy-MM-dd HH:mm:ss"),
entry.UncompressedSize.ToString(),
String.Format("{0,5:F0}%", entry.CompressionRatio),
entry.CompressedSize.ToString(),
(entry.UsesEncryption) ? "Y" : "N",
String.Format("{0:X8}", entry.Crc)};
foreach (String s in subitems)
{
ListViewItem.ListViewSubItem subitem = new ListViewItem.ListViewSubItem();
subitem.Text = s;
item.SubItems.Add(subitem);
}
this.listView1.Items.Add(item);
}
}
this.btnExtract.Enabled = true;
_DisplayedZip = zipFile;
this.listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);
this.listView1.EndUpdate();
}
catch (Exception exc1)
{
this.listView1.Clear();
this.listView1.EndUpdate();
MessageBox.Show(String.Format("There was a problem opening that file! [file={0}, problem={1}]",
zipFile, exc1.Message), "Whoops!", MessageBoxButtons.OK);
}
}
private void btnExtractDirBrowse_Click(object sender, EventArgs e)
{
// pop a dialog to ask where to extract
// Configure the "select folder" dialog box
//_folderName = tbDirName.Text;
//_folderName = (System.IO.Directory.Exists(_folderName)) ? _folderName : "";
var dlg1 = new Ionic.Utils.FolderBrowserDialogEx
{
Description = "Select a folder to extract to:",
ShowNewFolderButton = true,
ShowEditBox = true,
//NewStyle = false,
SelectedPath = tbExtractDir.Text,
ShowFullPathInEditBox = true,
};
dlg1.RootFolder = System.Environment.SpecialFolder.MyComputer;
var result = dlg1.ShowDialog();
if (result == DialogResult.OK)
{
this.tbExtractDir.Text = dlg1.SelectedPath;
// actually extract the files
}
}
private void btnExtract_Click(object sender, EventArgs e)
{
if (!System.IO.File.Exists(_DisplayedZip)) return;
KickoffExtract();
}
private void KickoffExtract()
{
if (String.IsNullOrEmpty(this.tbExtractDir.Text)) return;
_hrt = new HiResTimer();
_hrt.Start();
_working = true;
_operationCanceled = false;
_nFilesCompleted = 0;
_totalBytesAfterCompress = 0;
_totalBytesBeforeCompress = 0;
PauseUI(null);
lblStatus.Text = "Extracting...";
var options = new ExtractWorkerOptions
{
ExtractLocation = this.tbExtractDir.Text,
Selection = this.tbSelectionToExtract.Text,
OpenExplorer = this.chkOpenExplorer.Checked,
ExtractExisting = (ExtractExistingFileAction) comboExistingFileAction.SelectedIndex,
};
_workerThread = new Thread(this.DoExtract);
_workerThread.Name = "Zip Extractor thread";
_workerThread.Start(options);
this.Cursor = Cursors.WaitCursor;
}
private void PauseUI(string msg)
{
// this set for Zipping
if (msg != null)
this.btnZipUp.Text = msg;
this.btnZipUp.Enabled = false;
this.btnZipupDirBrowse.Enabled = false;
this.btnCreateZipBrowse.Enabled = false;
this.btnClearItemsToZip.Enabled = false;
this.btnCancel.Enabled = true;
// this for Extract
this.btnExtract.Enabled = false;
this.btnExtract.Text = "working...";
this.btnExtractDirBrowse.Enabled = false;
this.btnCancel.Enabled = true;
this.btnReadZipBrowse.Enabled = false;
}
private void zip_ExtractProgress(object sender, ExtractProgressEventArgs e)
{
if (e.EventType == ZipProgressEventType.Extracting_EntryBytesWritten)
{
StepEntryProgress(e);
}
else if (e.EventType == ZipProgressEventType.Extracting_AfterExtractEntry)
{
StepArchiveProgress(e);
}
if (_setCancel)
e.Cancel = true;
}
private void OnExtractDone()
{
if (this.lblStatus.InvokeRequired)
{
this.lblStatus.Invoke(new MethodInvoker(this.OnExtractDone));
}
else
{
_hrt.Stop();
System.TimeSpan ts = new System.TimeSpan(0, 0, (int)_hrt.Seconds);
lblStatus.Text = String.Format("Done, Extracted {0} files, time: {1}",
_nFilesCompleted,
ts.ToString());
ResetUiState();
// remember the successful selection strings
if (!_selectionCompletions.Contains(this.tbSelectionToZip.Text))
{
if (_selectionCompletions.Count >= _MaxMruListSize)
_selectionCompletions.RemoveAt(0);
_selectionCompletions.Add(this.tbSelectionToZip.Text);
}
}
}
bool _setCancel = false;
private void DoExtract(object p)
{
ExtractWorkerOptions options = p as ExtractWorkerOptions;
bool extractCancelled = false;
_setCancel = false;
string currentPassword = "";
try
{
using (var zip = ZipFile.Read(_DisplayedZip))
{
System.Collections.Generic.ICollection<ZipEntry> collection = null;
if (String.IsNullOrEmpty(options.Selection))
collection = zip.Entries;
else
collection = zip.SelectEntries(options.Selection);
_totalEntriesToProcess = collection.Count;
zip.ExtractProgress += zip_ExtractProgress;
SetProgressBars();
foreach (global::Ionic.Zip.ZipEntry entry in collection)
{
if (_setCancel) { extractCancelled = true; break; }
if (entry.Encryption == global::Ionic.Zip.EncryptionAlgorithm.None)
{
try
{
entry.Extract(options.ExtractLocation, options.ExtractExisting);
}
catch (Exception ex1)
{
string msg = String.Format("Faisled to extract entry {0} -- {1}",
entry.FileName,
ex1.Message.ToString());
DialogResult result =
MessageBox.Show(msg,
String.Format("Error Extracting {0}", entry.FileName),
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
if (result == DialogResult.Cancel)
{
_setCancel = true;
extractCancelled = true;
break;
}
}
}
else
{
bool done = false;
while (!done)
{
if (currentPassword == "")
{
string t = PromptForPassword(entry.FileName);
if (t == "")
{
done = true; // escape ExtractWithPassword loop
continue;
}
currentPassword = t;
}
if (currentPassword == null) // cancel all
{
_setCancel = true;
currentPassword = "";
break;
}
try
{
entry.ExtractWithPassword(options.ExtractLocation, options.ExtractExisting, currentPassword);
done = true;
}
catch (Exception ex2)
{
// Retry here in the case of bad password.
if (ex2 as Ionic.Zip.BadPasswordException != null)
{
currentPassword = "";
continue; // loop around, ask for password again
}
else
{
string msg =
String.Format("Failed to extract the password-encrypted entry {0} -- {1}",
entry.FileName, ex2.Message.ToString());
DialogResult result =
MessageBox.Show(msg,
String.Format("Error Extracting {0}",
entry.FileName),
MessageBoxButtons.OKCancel,
MessageBoxIcon.Exclamation,
MessageBoxDefaultButton.Button1);
done = true; // done with this entry
if (result == DialogResult.Cancel)
{
_setCancel = true;
extractCancelled = true;
break;
}
}
}
} // while
} // else (encryption)
} // foreach
} // using
}
catch (Exception ex1)
{
MessageBox.Show(String.Format("There's been a problem extracting that zip file. {0}", ex1.Message),
"Error Extracting", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
Application.Exit();
}
OnExtractDone();
if (extractCancelled) return;
if (options.OpenExplorer)
{
string w = System.IO.Path.GetDirectoryName(Environment.GetFolderPath(Environment.SpecialFolder.System));
if (w == null) w = "c:\\windows";
try
{
System.Diagnostics.Process.Start(System.IO.Path.Combine(w, "explorer.exe"), options.ExtractLocation);
}
catch { }
}
}
private string PromptForPassword(string entryName)
{
PasswordDialog dlg1 = new PasswordDialog();
dlg1.EntryName = entryName;
// ask for password in a loop until user enters a proper one,
// or clicks skip or cancel.
bool done = false;
do
{
dlg1.ShowDialog();
done = (dlg1.Result != PasswordDialog.PasswordDialogResult.OK ||
dlg1.Password != "");
} while (!done);
if (dlg1.Result == PasswordDialog.PasswordDialogResult.OK)
return dlg1.Password;
else if (dlg1.Result == PasswordDialog.PasswordDialogResult.Skip)
return "";
// cancel
return null;
}
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
// Recycle the progress bars the cancel button, and the status textbox.
// An alternative way to accomplish a similar thing is to visually place
// the progress bars OFF the tabs.
if (this.tabControl1.SelectedIndex == 0)
{
if (this.tabPage2.Controls.Contains(this.progressBar1))
this.tabPage2.Controls.Remove(this.progressBar1);
if (this.tabPage2.Controls.Contains(this.progressBar2))
this.tabPage2.Controls.Remove(this.progressBar2);
if (this.tabPage2.Controls.Contains(this.btnCancel))
this.tabPage2.Controls.Remove(this.btnCancel);
if (this.tabPage2.Controls.Contains(this.lblStatus))
this.tabPage2.Controls.Remove(this.lblStatus);
if (!this.tabPage1.Controls.Contains(this.lblStatus))
this.tabPage1.Controls.Add(this.lblStatus);
if (!this.tabPage1.Controls.Contains(this.progressBar1))
this.tabPage1.Controls.Add(this.progressBar1);
if (!this.tabPage1.Controls.Contains(this.progressBar2))
this.tabPage1.Controls.Add(this.progressBar2);
if (!this.tabPage1.Controls.Contains(this.btnCancel))
this.tabPage1.Controls.Add(this.btnCancel);
// swap the comboBox for Encoding to the selected panel
if (groupBox2.Controls.Contains(comboEncoding))
{
groupBox2.Controls.Remove(comboEncoding);
tabPage1.Controls.Add(comboEncoding);
int xpos = this.tbZipToOpen.Location.X ;
this.comboEncoding.Location = new System.Drawing.Point(xpos, this.tbZipToOpen.Location.Y + this.comboEncoding.Height + 4);
}
this.toolTip1.SetToolTip(this.comboEncoding, "use this encoding to read the file");
}
else if (this.tabControl1.SelectedIndex == 1)
{
if (this.tabPage1.Controls.Contains(this.progressBar1))
this.tabPage1.Controls.Remove(this.progressBar1);
if (this.tabPage1.Controls.Contains(this.progressBar2))
this.tabPage1.Controls.Remove(this.progressBar2);
if (this.tabPage1.Controls.Contains(this.btnCancel))
this.tabPage1.Controls.Remove(this.btnCancel);
if (this.tabPage1.Controls.Contains(this.lblStatus))
this.tabPage1.Controls.Remove(this.lblStatus);
if (!this.tabPage2.Controls.Contains(this.lblStatus))
this.tabPage2.Controls.Add(this.lblStatus);
if (!this.tabPage2.Controls.Contains(this.progressBar1))
this.tabPage2.Controls.Add(this.progressBar1);
if (!this.tabPage2.Controls.Contains(this.progressBar2))
this.tabPage2.Controls.Add(this.progressBar2);
if (!this.tabPage2.Controls.Contains(this.btnCancel))
this.tabPage2.Controls.Add(this.btnCancel);
// swap the comboBox for Encoding to the selected panel
if (tabPage1.Controls.Contains(comboEncoding))
{
tabPage1.Controls.Remove(comboEncoding);
groupBox2.Controls.Add(comboEncoding);
this.comboEncoding.Location = new System.Drawing.Point(104, 85);
this.comboEncoding.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
}
this.toolTip1.SetToolTip(this.comboEncoding, "use this encoding when saving the file");
}
}
private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
// prevent switching TABs if working
if (_working) e.Cancel = true;
}
private void listView1_ColumnClick(object sender, ColumnClickEventArgs e)
{
// Create an instance of the ColHeader class.
SortableColumnHeader clickedCol = (SortableColumnHeader)this.listView1.Columns[e.Column];
// Set the ascending property to sort in the opposite order.
clickedCol.SortAscending = !clickedCol.SortAscending;
// Get the number of items in the list.
int numItems = this.listView1.Items.Count;
// Turn off display while data is repoplulated.
this.listView1.BeginUpdate();
// Populate an ArrayList with a SortWrapper of each list item.
List<ItemWrapper> list = new List<ItemWrapper>();
for (int i = 0; i < numItems; i++)
{
list.Add(new ItemWrapper(this.listView1.Items[i], e.Column));
}
if (e.Column == 0 || e.Column == 3 || e.Column == 5)
list.Sort(new ItemWrapper.NumericComparer(clickedCol.SortAscending));
else
list.Sort(new ItemWrapper.StringComparer(clickedCol.SortAscending));
// Clear the list, and repopulate with the sorted items.
this.listView1.Items.Clear();
for (int i = 0; i < numItems; i++)
this.listView1.Items.Add(list[i].Item);
// Turn display back on.
this.listView1.EndUpdate();
}
private void tbPassword_TextChanged(object sender, EventArgs e)
{
if (this.tbPassword.Text == "")
{
if (_mostRecentEncryption == null && this.comboEncryption.SelectedItem.ToString() != "None")
{
_mostRecentEncryption = this.comboEncryption.SelectedItem.ToString();
SelectNamedEncryption("None");
}
}
else
{
if (_mostRecentEncryption != null && this.comboEncryption.SelectedItem.ToString() == "None")
{
SelectNamedEncryption(_mostRecentEncryption);
}
_mostRecentEncryption = null;
}
}
private void LoadAboutInfo()
{
var a = System.Reflection.Assembly.GetEntryAssembly();
string[] resourceNames = a.GetManifestResourceNames();
if (resourceNames != null && resourceNames.Length > 0)
{
String name = "Ionic.Zip.Forms.About.rtf";
var s = a.GetManifestResourceStream(name);
var bytes = ReadAllBytes(s);
this.richTextBox1.Rtf = System.Text.Encoding.ASCII.GetString(bytes);
s.Close();
}
}
/// <summary>
/// Reads the contents of the stream into a byte array.
/// </summary>
/// <remarks>
/// <para>
/// Like File.ReadAllBytes(), but for a stream.
/// </para>
/// </remarks>
/// <param name="stream">The stream to read.</param>
/// <returns>A byte array containing the contents of the stream.</returns>
/// <exception cref="NotSupportedException">The stream does not support reading.</exception>
/// <exception cref="ObjectDisposedException">Methods were called after the stream was closed.</exception>
/// <exception cref="System.IO.IOException">An I/O error occurs.</exception>
private byte[] ReadAllBytes(System.IO.Stream source)
{
long originalPosition = source.Position;
source.Position = 0;
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = source.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = source.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
source.Position = originalPosition;
}
}
private void ZipForm_Load(object sender, EventArgs e)
{
if (_initialFileToLoad != null)
{
// select the page that opens zip files.
this.tabControl1.SelectedIndex = 0;
//this.tabPage1.Select();
this.tbZipToOpen.Text = _initialFileToLoad;
btnOpen_Click(null, null);
}
LoadAboutInfo();
}
private void tbDirectoryToZip_Leave(object sender, EventArgs e)
{
this.tbDirectoryInArchive.Text = System.IO.Path.GetFileName(this.tbDirectoryToZip.Text);
}
private void richTextBox1_LinkClicked(object sender, LinkClickedEventArgs e)
{
System.Diagnostics.Process.Start(e.LinkText);
}
private void listView_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("FileDrop") && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
{
// Get the data.
var filePaths = (String[])e.Data.GetData("FileDrop");
// allow drop of one file on listView1, drop multiple files on listView2.
if (filePaths.Length == 1 || sender == this.listView2)
//A file is being dragged and it can be copied so provide feedback to the user.
e.Effect = DragDropEffects.Copy;
}
}
private void listView1_DragDrop(object sender, DragEventArgs e)
{
// The data can only be dropped if it is a file list and it can be copied.
if (e.Data.GetDataPresent("FileDrop") && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
{
// Get the data.
var filePaths = (String[])e.Data.GetData("FileDrop");
// The data is an array of file paths.
// If it is a single file and ends in .zip, then we know how to open it
// and display the contents.
// If it is more than one file, then we don't know what to do with it.
if (filePaths.Length == 1)
{
DisplayZipFile(filePaths[0]);
this.tbZipToOpen.Text = filePaths[0];
this.tbExtractDir.Text = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(filePaths[0]), System.IO.Path.GetFileNameWithoutExtension(filePaths[0]) + "_files");
}
}
}
private void listView2_DragDrop(object sender, DragEventArgs e)
{
// The data can only be dropped if it is a file list and it can be copied.
if (e.Data.GetDataPresent("FileDrop") && (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
{
// Get the data.
var filePaths = (String[])e.Data.GetData("FileDrop");
this.listView2.BeginUpdate();
foreach (var f in filePaths)
{
var item = new ListViewItem();
// first subitem is the local filename on disk
var subitem = new ListViewItem.ListViewSubItem();
subitem.Text = f;
item.SubItems.Add(subitem);
// next subitem is the directory name to use in the archive
subitem = new ListViewItem.ListViewSubItem();
//subitem.Text = String.IsNullOrEmpty(_lastDirectory) ? this.tbDirectoryInArchive.Text : _lastDirectory;
subitem.Text = String.IsNullOrEmpty(_lastDirectory)
? System.IO.Path.GetFileName(System.IO.Path.GetDirectoryName(f))
: _lastDirectory;
item.SubItems.Add(subitem);
// additional subitem (to be added): new filename in archive, if any
subitem = new ListViewItem.ListViewSubItem();
item.SubItems.Add(subitem);
this.listView2.Items.Add(item);
}
this.listView2.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
this.listView2.EndUpdate();
}
}
private void listView2_SubItemClicked(object sender, ListViewEx.SubItemEventArgs e)
{
//this.AcceptButton = null;
// Prevent editing the 0th column - it's the checkbox. We want the checkbox
// label to remain "".
if (e.SubItem == 0) return;
this.listView2.StartEditing(this.textBox1, e.Item, e.SubItem);
//this.textBox1.Focus(); // to get the RETURN key? no. this did not work.
}
private void listView2_SubItemEndEditing(object sender, ListViewEx.SubItemEndEditingEventArgs e)
{
if (!e.Cancel)
{
e.DisplayText = textBox1.Text;
//this.AcceptButton = this.btnZipUp;
//this.listView2.Select();
// this.listView2.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
}
//this.listView2.EndEditing(true);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
this.listView2.EndEditing(true);
e.Handled = true;
_lastDirectory = this.textBox1.Text;
}
}
private void button1_Click(object sender, EventArgs e)
{
int nAdded = 0;
PauseUI(null);
try
{
// do file selection, add each item into the list box
var fs = new global::Ionic.FileSelector(this.tbSelectionToZip.Text,this.chkTraverseJunctions.Checked);
var files = fs.SelectFiles(this.tbDirectoryToZip.Text, this.chkRecurse.Checked);
this.listView2.BeginUpdate();
foreach (String f in files)
{
var item = new ListViewItem();
// first subitem is the filename
var subitem = new ListViewItem.ListViewSubItem();
subitem.Text = f;
item.SubItems.Add(subitem);
// second subitem is the directory name in the archive.
subitem = new ListViewItem.ListViewSubItem();
var dirInArchive = this.tbDirectoryInArchive.Text;
var subDir = System.IO.Path.GetDirectoryName(f.Replace(this.tbDirectoryToZip.Text, ""));
subDir = subDir.Substring(1);
subitem.Text = System.IO.Path.Combine(dirInArchive, subDir);
item.SubItems.Add(subitem);
// third subitem is the filename in the archive, if ay
subitem = new ListViewItem.ListViewSubItem();
item.SubItems.Add(subitem);
this.listView2.Items.Add(item);
nAdded++;
}
this.listView2.AutoResizeColumns(ColumnHeaderAutoResizeStyle.HeaderSize);
this.listView2.EndUpdate();
this.lblStatus.Text = String.Format("Added {0} entries; {1} total entries to save.", nAdded, this.listView2.Items.Count);
// remember the successful selection strings
if (!_selectionCompletions.Contains(this.tbSelectionToZip.Text))
{
if (_selectionCompletions.Count >= _MaxMruListSize)
_selectionCompletions.RemoveAt(0);
_selectionCompletions.Add(this.tbSelectionToZip.Text);
}
}
catch
{ }
ResetUiState();
//_disableMasterChecking = false;
}
private void btnClearItemsToZip_Click(object sender, EventArgs e)
{
int rCount=0;
foreach (ListViewItem item in this.listView2.Items)
{
if (item.Checked)
{
this.listView2.Items.Remove(item);
rCount++;
}
}
// After removing all the checked items, all items are now unchecked.
// We can set the mast checkbox to unchecked. But, we have to protect
// against infinite recursion.
_disableMasterChecking = true;
this.checkBox1.Checked = false;
_disableMasterChecking = false;
this.lblStatus.Text = (rCount == 1)
? String.Format("Cleared 1 entry. {1} remaining entries to save.", rCount, this.listView2.Items.Count)
: String.Format("Cleared {0} entries. {1} remaining entries to save.", rCount, this.listView2.Items.Count);
}
bool _disableMasterChecking = false;
private void checkBox1_CheckedChanged_1(object sender, EventArgs e)
{
// prevent infinite recursion.
if (_disableMasterChecking) return;
// if we have a mixed state, then it happened programmatically
if (this.checkBox1.CheckState == CheckState.Indeterminate) return;
_disableListViewCheckedEvent = true;
_disableMasterChecking = true;
// change state of ALL items
foreach (ListViewItem item in this.listView2.Items)
{
item.Checked = this.checkBox1.Checked;
}
_disableMasterChecking = false;
_disableListViewCheckedEvent = false;
}
private bool _disableListViewCheckedEvent;
private void listView2_ItemChecked(object sender, ItemCheckedEventArgs e)
{
// prevent infinite recursion
if (_disableListViewCheckedEvent) return;
System.Drawing.Point p = this.listView2.PointToClient(new System.Drawing.Point(Cursor.Position.X, Cursor.Position.Y));
ListViewItem lvi;
int ix = this.listView2.GetSubItemAt(p.X, p.Y, out lvi);
// lvi is null when the checkchange comes from a non-mouse event, like when
// a new item is being added to the list.
if (lvi == null) return;
// ix is 0 when the checkbox is the thing that was tickled with the mouse.
if (ix == 0)
MaybeSetMasterCheckbox();
else
{
// Revert the checkChange if it was due to a mouse click on a subitem other than the 0th one.
// The Checked property has already been changed (in ListView.WndProc?); we need to undo it.
// In order to avoid an endless recursion, set the disable flag, first.
_disableListViewCheckedEvent = true;
lvi.Checked = !lvi.Checked;
_disableListViewCheckedEvent = false;
}
}
private void MaybeSetMasterCheckbox()
{
if (_disableMasterChecking) return;
bool uniform = true;
// check the state of all the items
for (int i = 1; i < this.listView2.Items.Count; i++)
{
if (this.listView2.Items[i].Checked != this.listView2.Items[i - 1].Checked)
{
uniform = false;
break;
}
}
_disableMasterChecking = true;
if (uniform)
this.checkBox1.CheckState = (this.listView2.Items[0].Checked) ? CheckState.Checked : CheckState.Unchecked;
else
this.checkBox1.CheckState = CheckState.Indeterminate;
_disableMasterChecking = false;
}
private void listView2_BeforeLabelEdit(object sender, LabelEditEventArgs e)
{
// never let the use edit the label associated to the main listview item,
// the label on the item checkbox.
e.CancelEdit = true;
}
private int _progress2MaxFactor;
private int _totalEntriesToProcess;
private bool _working;
private bool _operationCanceled;
private int _nFilesCompleted;
private long _totalBytesBeforeCompress;
private long _totalBytesAfterCompress;
private Thread _workerThread;
private static string TB_COMMENT_NOTE = "-zip file comment here-";
private static string TB_EXTRACT_DIR_NOTE = "-default extract directory-";
private static string TB_EXE_ON_UNPACK_NOTE = "-command line to execute here-";
private String _mostRecentEncryption;
private string _initialFileToLoad;
private string _lastDirectory;
}
// The ColHeader class is a ColumnHeader object with an
// added property for determining an ascending or descending sort.
// True specifies an ascending order, false specifies a descending order.
public class SortableColumnHeader : ColumnHeader
{
public bool SortAscending;
public SortableColumnHeader(string text)
{
this.Text = text;
this.SortAscending = true;
}
}
// An instance of the SortWrapper class is created for
// each item and added to the ArrayList for sorting.
public class ItemWrapper
{
internal ListViewItem Item;
internal int Column;
// A SortWrapper requires the item and the index of the clicked column.
public ItemWrapper(ListViewItem item, int column)
{
Item = item;
Column = column;
}
// Text property for getting the text of an item.
public string Text
{
get { return Item.SubItems[Column].Text; }
}
// Implementation of the IComparer
public class StringComparer : IComparer<ItemWrapper>
{
bool ascending;
// Constructor requires the sort order;
// true if ascending, otherwise descending.
public StringComparer(bool asc)
{
this.ascending = asc;
}
// Implemnentation of the IComparer:Compare
// method for comparing two objects.
public int Compare(ItemWrapper xItem, ItemWrapper yItem)
{
string xText = xItem.Item.SubItems[xItem.Column].Text;
string yText = yItem.Item.SubItems[yItem.Column].Text;
return xText.CompareTo(yText) * (this.ascending ? 1 : -1);
}
}
public class NumericComparer : IComparer<ItemWrapper>
{
bool ascending;
// Constructor requires the sort order;
// true if ascending, otherwise descending.
public NumericComparer(bool asc)
{
this.ascending = asc;
}
// Implementation of the IComparer:Compare
// method for comparing two objects.
public int Compare(ItemWrapper xItem, ItemWrapper yItem)
{
int x = 0, y = 0;
try
{
x = Int32.Parse(xItem.Item.SubItems[xItem.Column].Text);
y = Int32.Parse(yItem.Item.SubItems[yItem.Column].Text);
}
catch
{
try
{
// lop off one char for %
String trimmed = null;
trimmed = xItem.Item.SubItems[xItem.Column].Text;
trimmed = trimmed.Substring(0, trimmed.Length - 1);
x = Int32.Parse(trimmed);
trimmed = xItem.Item.SubItems[yItem.Column].Text;
trimmed = trimmed.Substring(0, trimmed.Length - 1);
y = Int32.Parse(trimmed);
}
catch { }
}
return (x - y) * (this.ascending ? 1 : -1);
}
}
}
public class ExtractWorkerOptions
{
public string ExtractLocation;
public Ionic.Zip.ExtractExistingFileAction ExtractExisting;
public bool OpenExplorer;
public String Selection;
}
public class SaveWorkerOptions
{
public string ZipName;
public string Selection;
public bool TraverseJunctions;
public bool RemoveFilesAfterExe;
public string Encoding;
public Ionic.Zip.ZipOption EncodingUsage;
public string Comment;
public string Password;
public string ExeOnUnpack;
public string ExtractDirectory;
public int ExtractExistingFile;
public int ZipFlavor;
public int MaxSegmentSize;
public Ionic.Zlib.CompressionLevel CompressionLevel;
public Ionic.Zip.CompressionMethod CompressionMethod;
public Ionic.Zip.EncryptionAlgorithm Encryption;
public Zip64Option Zip64;
public bool WindowsTimes;
public bool UnixTimes;
public ItemToAdd[] Entries;
}
public class ItemToAdd
{
public string LocalFileName;
public string DirectoryInArchive;
public string FileNameInArchive;
}
internal class HiResTimer
{
// usage:
//
// hrt= new HiResTimer();
// hrt.Start();
// ... do work ...
// hrt.Stop();
// System.Console.WriteLine("elapsed time: {0:N4}", hrt.Seconds);
//
[System.Runtime.InteropServices.DllImport("KERNEL32")]
private static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);
[System.Runtime.InteropServices.DllImport("KERNEL32")]
private static extern bool QueryPerformanceFrequency(ref long lpFrequency);
private long m_TickCountAtStart = 0;
private long m_TickCountAtStop = 0;
private long m_ElapsedTicks = 0;
public HiResTimer()
{
m_Frequency = 0;
QueryPerformanceFrequency(ref m_Frequency);
}
public void Start()
{
m_TickCountAtStart = 0;
QueryPerformanceCounter(ref m_TickCountAtStart);
}
public void Stop()
{
m_TickCountAtStop = 0;
QueryPerformanceCounter(ref m_TickCountAtStop);
m_ElapsedTicks = m_TickCountAtStop - m_TickCountAtStart;
}
public void Reset()
{
m_TickCountAtStart = 0;
m_TickCountAtStop = 0;
m_ElapsedTicks = 0;
}
public long Elapsed
{
get { return m_ElapsedTicks; }
}
public float Seconds
{
get { return ((float)m_ElapsedTicks / (float)m_Frequency); }
}
private long m_Frequency = 0;
public long Frequency
{
get { return m_Frequency; }
}
}
}