//
// Copyright (c) 2002
// Ronald Kevin Burton
//
// Z poniższym kodem nie jest związana żadna gwarancja poprawności działania.
// Program został dołączony do książki ".NET CLR. Księga eksperta" w celu
// ilustracji koncepcji i zasad przedstawionych w tej książce. Program może być 
// używany na własne ryzyko.
//
// Przyznaje się prawo do użycia lub kopiowania tego oprogramowania do dowolnego celu
// bez konieczności ponoszenia żadnych opłat pod warunkiem, że powyższe uwagi zostaną 
// zachowane we wszystkich kopiach. Przyznaje się także prawo do modyfikacji kodu
// i dystrybucji zmodyfikowanego kodu pod warunkiem zachowania powyższych uwag
// oraz dołączenia informacji mówiącej o modyfikacji kodu.
//
//
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Diagnostics;

namespace CLRUnleashed
{
	/// <summary>
	/// Podsumowanie dla Encrypt.
	/// </summary>
	public class EncryptForm : System.Windows.Forms.Form
	{
		private byte [] fileKey;
		private byte [] fileIV;
		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.TextBox filePath;
		private System.Windows.Forms.TextBox encryptedPath;
		private System.Windows.Forms.Button browseButton;
		private System.Windows.Forms.TextBox encryptTime;
		private System.Windows.Forms.TextBox decryptTime;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.OpenFileDialog openFileDialog;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.TextBox fileSize;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.TextBox encryptedSize;
		private System.Windows.Forms.Button encryptButton;
		private System.Windows.Forms.Button decryptButton;
		/// <summary>
		/// Wymagana zmienna.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public EncryptForm()
		{
			//
			// Wymagane do obsługi Windows Form Designer
			//
			InitializeComponent();
			encryptButton.Enabled = false;
			decryptButton.Enabled = false;
		}

		/// <summary>
		/// Oczyszczenie używanych zasobów.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Metoda wymagana do obsługi Designera - nie należy modyfikować
		/// zawartości tej metody przy użyciu edytora kodu.
		/// </summary>
		private void InitializeComponent()
		{
			this.label1 = new System.Windows.Forms.Label();
			this.filePath = new System.Windows.Forms.TextBox();
			this.encryptedPath = new System.Windows.Forms.TextBox();
			this.browseButton = new System.Windows.Forms.Button();
			this.encryptTime = new System.Windows.Forms.TextBox();
			this.decryptTime = new System.Windows.Forms.TextBox();
			this.encryptButton = new System.Windows.Forms.Button();
			this.label2 = new System.Windows.Forms.Label();
			this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
			this.fileSize = new System.Windows.Forms.TextBox();
			this.label3 = new System.Windows.Forms.Label();
			this.label4 = new System.Windows.Forms.Label();
			this.encryptedSize = new System.Windows.Forms.TextBox();
			this.decryptButton = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(11, 21);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(68, 30);
			this.label1.TabIndex = 0;
			this.label1.Text = "Ścieżka";
			// 
			// filePath
			// 
			this.filePath.Location = new System.Drawing.Point(90, 10);
			this.filePath.Name = "filePath";
			this.filePath.Size = new System.Drawing.Size(588, 35);
			this.filePath.TabIndex = 1;
			this.filePath.Text = "";
			this.filePath.TextChanged += new System.EventHandler(this.OnTextChanged);
			// 
			// encryptedPath
			// 
			this.encryptedPath.Location = new System.Drawing.Point(90, 62);
			this.encryptedPath.Name = "encryptedPath";
			this.encryptedPath.ReadOnly = true;
			this.encryptedPath.Size = new System.Drawing.Size(588, 35);
			this.encryptedPath.TabIndex = 2;
			this.encryptedPath.Text = "";
			// 
			// browseButton
			// 
			this.browseButton.Location = new System.Drawing.Point(701, 10);
			this.browseButton.Name = "browseButton";
			this.browseButton.Size = new System.Drawing.Size(113, 42);
			this.browseButton.TabIndex = 3;
			this.browseButton.Text = "...";
			this.browseButton.Click += new System.EventHandler(this.OnBrowse);
			// 
			// encryptTime
			// 
			this.encryptTime.Location = new System.Drawing.Point(215, 114);
			this.encryptTime.Name = "encryptTime";
			this.encryptTime.ReadOnly = true;
			this.encryptTime.Size = new System.Drawing.Size(226, 35);
			this.encryptTime.TabIndex = 5;
			this.encryptTime.Text = "";
			// 
			// decryptTime
			// 
			this.decryptTime.Location = new System.Drawing.Point(215, 166);
			this.decryptTime.Name = "decryptTime";
			this.decryptTime.ReadOnly = true;
			this.decryptTime.Size = new System.Drawing.Size(226, 35);
			this.decryptTime.TabIndex = 6;
			this.decryptTime.Text = "";
			// 
			// encryptButton
			// 
			this.encryptButton.Location = new System.Drawing.Point(57, 114);
			this.encryptButton.Name = "encryptButton";
			this.encryptButton.Size = new System.Drawing.Size(135, 42);
			this.encryptButton.TabIndex = 4;
			this.encryptButton.Text = "Szyfruj";
			this.encryptButton.Click += new System.EventHandler(this.OnEncrypt);
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(11, 73);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(68, 29);
			this.label2.TabIndex = 7;
			this.label2.Text = "Cel";
			// 
			// fileSize
			// 
			this.fileSize.Location = new System.Drawing.Point(599, 114);
			this.fileSize.Name = "fileSize";
			this.fileSize.ReadOnly = true;
			this.fileSize.Size = new System.Drawing.Size(226, 35);
			this.fileSize.TabIndex = 8;
			this.fileSize.Text = "";
			// 
			// label3
			// 
			this.label3.Location = new System.Drawing.Point(452, 125);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(136, 29);
			this.label3.TabIndex = 9;
			this.label3.Text = "Bajty wejściowe";
			// 
			// label4
			// 
			this.label4.Location = new System.Drawing.Point(452, 176);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(136, 30);
			this.label4.TabIndex = 10;
			this.label4.Text = "Bajty wyjściowe";
			// 
			// encryptedSize
			// 
			this.encryptedSize.Location = new System.Drawing.Point(599, 166);
			this.encryptedSize.Name = "encryptedSize";
			this.encryptedSize.ReadOnly = true;
			this.encryptedSize.Size = new System.Drawing.Size(226, 35);
			this.encryptedSize.TabIndex = 11;
			this.encryptedSize.Text = "";
			// 
			// decryptButton
			// 
			this.decryptButton.Enabled = false;
			this.decryptButton.Location = new System.Drawing.Point(57, 166);
			this.decryptButton.Name = "decryptButton";
			this.decryptButton.Size = new System.Drawing.Size(135, 42);
			this.decryptButton.TabIndex = 12;
			this.decryptButton.Text = "Odszyfruj";
			this.decryptButton.Click += new System.EventHandler(this.OnDecrypt);
			// 
			// EncryptForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(12, 28);
			this.ClientSize = new System.Drawing.Size(836, 215);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.decryptButton,
																		  this.encryptedSize,
																		  this.label4,
																		  this.label3,
																		  this.fileSize,
																		  this.label2,
																		  this.encryptButton,
																		  this.decryptTime,
																		  this.encryptTime,
																		  this.browseButton,
																		  this.encryptedPath,
																		  this.filePath,
																		  this.label1});
			this.Font = new System.Drawing.Font("Trebuchet MS", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.Name = "EncryptForm";
			this.Text = "Formularz szyfrowania";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// Główny punkt wejścia dla aplikacji.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new EncryptForm());
		}

		private void OnBrowse(object sender, System.EventArgs e)
		{
			DialogResult result = openFileDialog.ShowDialog();
			if(result == DialogResult.OK)
			{
				filePath.Tag = openFileDialog.FileName;
				encryptedPath.Tag = filePath.Tag + ".encrypted";
				FileInfo fileInfo = new FileInfo((string)filePath.Tag);
				filePath.Text = fileInfo.Name;
				FileInfo encryptedInfo = new FileInfo((string)encryptedPath.Tag);
				encryptedPath.Text = encryptedInfo.Name;
				encryptButton.Enabled = true;
				decryptButton.Enabled = false;
			}
			else
			{
				encryptButton.Enabled = false;
				decryptButton.Enabled = false;
			}
		}

		const int fileChunkSize = 200;
		private void OnEncrypt(object sender, System.EventArgs e)
		{
			// Utworzenie strumieni do obsługi plików wejściowych i wyjściowych.
			FileStream fin = new FileStream((string)filePath.Tag, FileMode.Open, FileAccess.Read);
			FileStream fout = new FileStream((string)encryptedPath.Tag, FileMode.OpenOrCreate, FileAccess.Write);
			fout.SetLength(0);
       
			// Utworzenie zmiennych wykorzystywanych w czasie odczytu i zapisu.
			// Poniższa zmienna służy do tymczasowego składowania szyfrowanych danych.
			byte[] bin = new byte[fileChunkSize];
			// Całkowita liczba zapisanych bajtów.
			long rdlen = 0;
			// Całkowita długość pliku wejściowego.
			long totlen = fin.Length;
			// Wielkość porcji bajtów do zapisania.
			int len;
 
			Debug.WriteLine("Szyfrowanie...");
			DateTime start = DateTime.Now;

			// Tworzy domyślną implementację RijndaelManaged.         
			// Jest to algorytm DES z kluczem losowym.
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			fileKey = des.Key;
			fileIV = des.IV;

			// Utworzenie funkcji szyfrującej DES Encryptor dla tego egzemplarza.
			ICryptoTransform desencrypt = des.CreateEncryptor();

			// Utworzenie strumienia CryptoStream, który przekształca strumień pliku poprzez szyfrowanie DES.
			CryptoStream encStream = new CryptoStream(fout,desencrypt,CryptoStreamMode.Write);
 
			// Odczyt pliku wejściowego, szyfrowanie i zapis do pliku wyjściowego.
			while(rdlen < totlen)
			{
				len = fin.Read(bin, 0, fileChunkSize);
				encStream.Write(bin, 0, len);
				rdlen = rdlen + len;
			}
			fileSize.Text = Convert.ToString(rdlen);
			encStream.Close(); 
			fout.Close();
			fin.Close();
			DateTime stop = DateTime.Now;
			TimeSpan elapsed = stop - start;
			encryptTime.Text = string.Format("{0:F}", (double)elapsed.TotalMilliseconds / 1000.0);		
			decryptButton.Enabled = true;
		}

		private void OnDecrypt(object sender, System.EventArgs e)
		{
			// Utworzenie strumieni do obsługi plików wejściowych i wyjściowych.
			FileStream fin = new FileStream((string)encryptedPath.Tag, FileMode.Open, FileAccess.Read);
			FileStream fout = new FileStream((string)filePath.Tag + ".decrypted", FileMode.OpenOrCreate, FileAccess.Write);
       
			// Utworzenie zmiennych wykorzystywanych w czasie odczytu i zapisu.
			// Poniższa zmienna służy do tymczasowego składowania szyfrowanych danych.
			byte[] bin = new byte[fileChunkSize];
			// Całkowita liczba zapisanych bajtów.
			long rdlen = 0;
			// Całkowita długość pliku wejściowego.
			long totlen = fin.Length;
			// Wielkość porcji bajtów do zapisania.
			int len;
 
			DateTime start = DateTime.Now;
			Debug.WriteLine("Odszyfrowywanie...");

			// Tworzy domyślną implementację RijndaelManaged.         
			// Jest to algorytm DES z kluczem losowym.
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			// Utworzenie funkcji szyfrującej DES Encryptor dla tego egzemplarza.
			ICryptoTransform desdecrypt = des.CreateDecryptor(fileKey, fileIV);

			// Utworzenie strumienia CryptoStream, który przekształca strumień pliku poprzez szyfrowanie DES.
			CryptoStream decStream = new CryptoStream(fout, desdecrypt, CryptoStreamMode.Write);
 
			// Odczyt pliku wejściowego, szyfrowanie i zapis do pliku wyjściowego.
			while(rdlen < totlen)
			{
				len = fin.Read(bin, 0, fileChunkSize);
				decStream.Write(bin, 0, len);
				rdlen = rdlen + len;
			}
			encryptedSize.Text = Convert.ToString(rdlen);
			decStream.Close(); 
			fout.Close();
			fin.Close();
			DateTime stop = DateTime.Now;
			TimeSpan elapsed = stop - start;
			decryptTime.Text = string.Format("{0:F}", (double)elapsed.TotalMilliseconds / 1000.0);		
		}

		private void OnTextChanged(object sender, System.EventArgs e)
		{
			TextBox f = sender as TextBox;
			if(f == null) return;
			FileInfo fileInfo = new FileInfo(f.Text);
			if(fileInfo.Exists)
			{
				Trace.WriteLine(fileInfo.FullName + " istnieje");
				filePath.Tag = fileInfo.FullName;
				filePath.Text = fileInfo.Name;
				encryptedPath.Tag = filePath.Tag + ".encrypted";
				FileInfo encryptedInfo = new FileInfo((string)encryptedPath.Tag);
				encryptedPath.Text = encryptedInfo.Name;
				encryptButton.Enabled = true;
			}
			else
			{
				encryptButton.Enabled = false;
				decryptButton.Enabled = false;
				Trace.WriteLine(f.Text + " does not exist");
			}
		}
	}
}
