1
0
Fork 0

Added a simple GUI front-end for Windows platform.

This commit is contained in:
LoRd_MuldeR 2021-04-24 02:59:39 +02:00
parent 7f643ad566
commit 502e92ee09
Signed by: mulder
GPG Key ID: 2B5913365F57E03F
51 changed files with 3311 additions and 67 deletions

View File

@ -7,6 +7,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SlunkCrypt", "frontend\Slun
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libSlunkCrypt", "libslunkcrypt\libSlunkCrypt.vcxproj", "{A4A3879C-BD2C-4304-AF66-7349CEF7E4C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SlunkCryptGUI", "gui\SlunkCryptGUI.csproj", "{568F3936-B520-4371-981C-E7A4DA781737}"
ProjectSection(ProjectDependencies) = postProject
{86D28793-713E-4CEC-9686-335514AC5EF0} = {86D28793-713E-4CEC-9686-335514AC5EF0}
{A4A3879C-BD2C-4304-AF66-7349CEF7E4C0} = {A4A3879C-BD2C-4304-AF66-7349CEF7E4C0}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -59,6 +65,26 @@ Global
{A4A3879C-BD2C-4304-AF66-7349CEF7E4C0}.Release|x64.Build.0 = Release|x64
{A4A3879C-BD2C-4304-AF66-7349CEF7E4C0}.Release|x86.ActiveCfg = Release|Win32
{A4A3879C-BD2C-4304-AF66-7349CEF7E4C0}.Release|x86.Build.0 = Release|Win32
{568F3936-B520-4371-981C-E7A4DA781737}.Debug|x64.ActiveCfg = Debug|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Debug|x64.Build.0 = Debug|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Debug|x86.ActiveCfg = Debug|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Debug|x86.Build.0 = Debug|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_DLL|x64.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_DLL|x64.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_DLL|x86.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_DLL|x86.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_SSE2|x64.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_SSE2|x64.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_SSE2|x86.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_SSE2|x86.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_WithDbgInfo|x64.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_WithDbgInfo|x64.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_WithDbgInfo|x86.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release_WithDbgInfo|x86.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release|x64.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release|x64.Build.0 = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release|x86.ActiveCfg = Release|Any CPU
{568F3936-B520-4371-981C-E7A4DA781737}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@ -195,63 +195,63 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_SSE2|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_WithDbgInfo|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_SSE2|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_WithDbgInfo|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-cli-$(PlatformShortName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>

BIN
frontend/res/crypto.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -21,6 +21,12 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
101 ICON "crypto.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version

View File

@ -245,13 +245,16 @@ int MAIN(const int argc, CHR *const argv[])
goto clean_up;
}
if (passphrase_len < RCMD_PWDLEN_LENGTH)
if (slunk_mode == MODE_ENCR)
{
FPRINTF(stderr, T("Warning: Using a *short* passphrase; a length of %u characters or more is recommended!\n\n"), (unsigned)RCMD_PWDLEN_LENGTH);
}
else if (weak_passphrase(passphrase_buffer))
{
FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and other characters is recommended!\n\n"), stderr);
if (passphrase_len < RCMD_PWDLEN_LENGTH)
{
FPRINTF(stderr, T("Warning: Using a *short* passphrase; a length of %u characters or more is recommended!\n\n"), (unsigned)RCMD_PWDLEN_LENGTH);
}
else if (weak_passphrase(passphrase_buffer))
{
FPUTS(T("Warning: Using a *weak* passphrase; a mix of upper-case letters, lower-case letters, digits and other characters is recommended!\n\n"), stderr);
}
}
fflush(stderr);

6
gui/App.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

92
gui/App.xaml Normal file
View File

@ -0,0 +1,92 @@
<Application x:Class="com.muldersoft.slunkcrypt.gui.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="SlunkCryptGUI.xaml">
<Application.Resources>
<Style TargetType="{x:Type FrameworkElement}" x:Key="DisableWhileBusy">
<Setter Property="IsEnabled" Value="true"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBusy, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="true">
<Setter Property="IsEnabled" Value="false"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="EnableWhileBusy">
<Setter Property="IsEnabled" Value="false"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBusy, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="true">
<Setter Property="IsEnabled" Value="true"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="HitInvisibleWhileBusy">
<Setter Property="IsEnabled" Value="true"/>
<EventSetter Event="PreviewDragEnter" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewDragOver" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewDrop" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewGotKeyboardFocus" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewKeyDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewKeyUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseLeftButtonUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseRightButtonDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseRightButtonUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewMouseWheel" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusButtonDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusButtonUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusInRange" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusSystemGesture" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewStylusUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewTextInput" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewTouchDown" Handler="FrameworkElement_PreviewUserInputEvent"/>
<EventSetter Event="PreviewTouchUp" Handler="FrameworkElement_PreviewUserInputEvent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsBusy, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="true">
<Setter Property="IsHitTestVisible" Value="false"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="WaitCursorWhileBusy">
<Style.Triggers>
<DataTrigger Binding="{Binding IsBusy, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Value="true">
<Setter Property="Cursor" Value="Wait"/>
<Setter Property="ForceCursor" Value="true"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type TextBlock}" x:Key="HighlightIfSelected">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType=TabItem}}" Value="true">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HotTrackBrushKey}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Image}" x:Key="GrayOutIfDisabled">
<Setter Property="Opacity" Value="1.0"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" Value="0.5"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type FrameworkElement}" x:Key="HideIfNotEmpty">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Count}" Value="0">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type ListViewItem}" x:Key="ItemToolTips">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Content="{Binding Chars}"/>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>

40
gui/App.xaml.cs Normal file
View File

@ -0,0 +1,40 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Windows;
namespace com.muldersoft.slunkcrypt.gui
{
public partial class App : Application
{
public App()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionHandler);
}
private static void ExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception exception;
if (!ReferenceEquals(exception = args.ExceptionObject as Exception, null))
{
MessageBox.Show("Unhandeled exception error:\n\n" + exception.Message, exception.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
}
Environment.Exit(-1);
}
protected void FrameworkElement_PreviewUserInputEvent(object sender, RoutedEventArgs e)
{
FrameworkElement element = sender as FrameworkElement;
if (!ReferenceEquals(element, null))
{
if (!element.IsHitTestVisible)
{
e.Handled = true;
}
}
}
}
}

View File

@ -0,0 +1,10 @@
<UserControl x:Class="com.muldersoft.slunkcrypt.gui.ctrls.Hyperlink"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="300">
<TextBlock Foreground="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" FontWeight="SemiBold" TextDecorations="Underline" Cursor="Hand" MouseLeftButtonDown="Label_MouseLeftButtonDown" MouseLeftButtonUp="Label_MouseLeftButtonUp" Name="Label_Hyperlink"/>
</UserControl>

View File

@ -0,0 +1,83 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace com.muldersoft.slunkcrypt.gui.ctrls
{
public partial class Hyperlink : UserControl
{
public event MouseButtonEventHandler Click;
public Hyperlink()
{
InitializeComponent();
}
public string LinkText
{
get
{
return Label_Hyperlink.Text;
}
set
{
Label_Hyperlink.Text = value;
}
}
public FontFamily LinkFontFamily
{
get
{
return Label_Hyperlink.FontFamily;
}
set
{
Label_Hyperlink.FontFamily = value;
}
}
public double LinkFontSize
{
get
{
return Label_Hyperlink.FontSize;
}
set
{
Label_Hyperlink.FontSize = value;
}
}
private void Label_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
UIElement inputElement;
if (!ReferenceEquals(inputElement = sender as UIElement, null))
{
inputElement.CaptureMouse();
}
}
private void Label_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
UIElement inputElement;
if (!ReferenceEquals(inputElement = sender as UIElement, null))
{
if (inputElement.IsMouseCaptured)
{
inputElement.ReleaseMouseCapture();
if (!ReferenceEquals(VisualTreeHelper.HitTest(inputElement, e.GetPosition(inputElement)), null))
{
Click?.Invoke(this, e);
}
}
}
}
}
}

View File

@ -0,0 +1,21 @@
<UserControl x:Class="com.muldersoft.slunkcrypt.gui.ctrls.ImageToggleButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:utils="clr-namespace:com.muldersoft.slunkcrypt.gui.utils"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<utils:VisibilityConverter x:Key="VisibilityConverter1"/>
<utils:VisibilityConverter x:Key="VisibilityConverter2" Inverse="True"/>
</UserControl.Resources>
<ToggleButton x:Name="Toggle">
<Grid>
<Image Margin="4,0,4,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None" Visibility="{Binding IsChecked, RelativeSource={RelativeSource FindAncestor, AncestorType=ToggleButton}, Converter={StaticResource VisibilityConverter2}}" Name="Image_Default"/>
<Image Margin="4,0,4,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None" Visibility="{Binding IsChecked, RelativeSource={RelativeSource FindAncestor, AncestorType=ToggleButton}, Converter={StaticResource VisibilityConverter1}}" Name="Image_Checked"/>
</Grid>
</ToggleButton>
</UserControl>

View File

@ -0,0 +1,75 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace com.muldersoft.slunkcrypt.gui.ctrls
{
/// <summary>
/// Interaction logic for ImageToggleButton.xaml
/// </summary>
public partial class ImageToggleButton : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ImageToggleButton()
{
InitializeComponent();
Toggle.Checked += OnCheckedChanged;
Toggle.Unchecked += OnCheckedChanged;
}
public bool IsChecked
{
get
{
return Toggle.IsChecked.GetValueOrDefault();
}
set
{
Toggle.IsChecked = value;
}
}
public ImageSource ImageSourceDefault
{
get
{
return Image_Default.Source;
}
set
{
Image_Default.Source = value;
}
}
public ImageSource ImageSourceChecked
{
get
{
return Image_Checked.Source;
}
set
{
Image_Checked.Source = value;
}
}
private void OnCheckedChanged(object sender, RoutedEventArgs e)
{
NotifyPropertyChanged("IsChecked");
}
private void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
}
}

View File

@ -0,0 +1,22 @@
<UserControl x:Class="com.muldersoft.slunkcrypt.gui.ctrls.PasswordToggleBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="25" d:DesignWidth="300" Focusable="True">
<UserControl.Resources>
<ScaleTransform x:Key="FontStretchExpanded" ScaleX="1.2" />
<Style TargetType="Control" x:Key="ExpanedFontStyle">
<Style.Setters>
<Setter Property="LayoutTransform" Value="{StaticResource FontStretchExpanded}" />
</Style.Setters>
</Style>
</UserControl.Resources>
<Grid>
<PasswordBox Name="Edit_Hidden" MinHeight="{Binding ActualHeight,ElementName=Edit_Normal}" VerticalContentAlignment="Center" Style="{StaticResource ExpanedFontStyle}" KeyDown="Edit_KeyDown" Panel.ZIndex="1"/>
<TextBox DockPanel.Dock="Left" Name="Edit_Normal" MinHeight="{Binding ActualHeight,ElementName=Edit_Hidden}" VerticalContentAlignment="Center" Style="{StaticResource ExpanedFontStyle}" KeyDown="Edit_KeyDown" Panel.ZIndex="0"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,161 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace com.muldersoft.slunkcrypt.gui.ctrls
{
public partial class PasswordToggleBox : UserControl
{
public event KeyEventHandler Entered;
public static readonly DependencyProperty IsRevealedProperty = DependencyProperty.Register("IsRevealed", typeof(bool), typeof(PasswordToggleBox), new PropertyMetadata(false, OnIsRevealedPropertyChanged));
public PasswordToggleBox()
{
InitializeComponent();
}
public Thickness EditPadding
{
get
{
return Edit_Hidden.Padding;
}
set
{
Edit_Hidden.Padding = Edit_Normal.Padding = value;
}
}
public FontFamily EditFontFamily
{
get
{
return Edit_Hidden.FontFamily;
}
set
{
Edit_Normal.FontFamily = Edit_Hidden.FontFamily = value;
}
}
public char PasswordChar
{
get
{
return Edit_Hidden.PasswordChar;
}
set
{
Edit_Hidden.PasswordChar = value;
}
}
public int MaxLength
{
get
{
return Edit_Hidden.MaxLength;
}
set
{
Edit_Normal.MaxLength = Edit_Hidden.MaxLength = value;
}
}
public bool IsRevealed
{
get
{
return (bool) GetValue(IsRevealedProperty);
}
set
{
SetValue(IsRevealedProperty, value);
}
}
public string Password
{
get
{
return IsRevealed ? Edit_Normal.Text : Edit_Hidden.Password;
}
}
public void Clear()
{
Edit_Hidden.Clear();
Edit_Normal.Clear();
}
public void SelectAll()
{
if (IsRevealed)
{
Edit_Normal.SelectAll();
}
else
{
Edit_Hidden.SelectAll();
}
}
private void OnIsRevealedPropertyChanged(bool value)
{
Panel.SetZIndex(Edit_Hidden, value ? 0 : 1);
Panel.SetZIndex(Edit_Normal, value ? 1 : 0);
if (value)
{
Edit_Normal.Text = Edit_Hidden.Password;
Edit_Hidden.Clear();
}
else
{
Edit_Hidden.Password = Edit_Normal.Text;
Edit_Normal.Clear();
};
}
private static void OnIsRevealedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
PasswordToggleBox ptb = d as PasswordToggleBox;
if (!ReferenceEquals(ptb, null))
{
bool? newValue = e.NewValue as bool?;
if (newValue.HasValue)
{
ptb.OnIsRevealedPropertyChanged(newValue.Value);
}
}
}
private void Edit_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
Entered?.Invoke(this, e);
e.Handled = true;
}
}
protected override void OnGotFocus(RoutedEventArgs e)
{
if (IsRevealed)
{
Edit_Normal.Focus();
}
else
{
Edit_Hidden.Focus();
}
e.Handled = true;
}
}
}

View File

@ -0,0 +1,156 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Threading;
using com.muldersoft.slunkcrypt.gui.utils;
namespace com.muldersoft.slunkcrypt.gui.process
{
internal class SlunkCryptRunner : ProcessRunner
{
public enum Mode { Encrypt, Decrypt }
private const string FILENAME_FORMAT = "slunkcrypt-cli-{0}.exe";
private const string COMMAND_ENCRYPT = "-e";
private const string COMMAND_DECRYPT = "-d";
private static readonly Regex RX_PROGRESS = new Regex(@"(\d+)\.(\d)%", RegexOptions.Compiled);
private readonly FileStream m_executableFile;
// =============================================================================
// Exception classes
// =============================================================================
public class ExecutableNotFoundException : FileNotFoundException
{
public ExecutableNotFoundException(string message, string fileName) : base(message, fileName)
{
}
}
// =============================================================================
// Constructor
// =============================================================================
public SlunkCryptRunner(Dispatcher dispatcher, ProcessPriorityClass? priorityClass = null) : base(dispatcher, priorityClass)
{
m_executableFile = GetExecutableFile();
}
// =============================================================================
// Public methods
// =============================================================================
public async Task<int> ExecuteAsync(Mode mode, string inputFile, string outputFile, string password)
{
Dictionary<string, string> environmentVariables = new Dictionary<string, string>();
environmentVariables.Add("SLUNK_PASSPHRASE", password);
string[] arguments = new string[] { GetCommandString(mode), inputFile, outputFile };
return await ExecAsnyc(m_executableFile.Name, arguments, environmentVariables);
}
public override void Dispose()
{
base.Dispose();
try
{
m_executableFile.Dispose();
}
catch { }
}
// =============================================================================
// Internal methods
// =============================================================================
private static FileStream GetExecutableFile()
{
FileStream executableFile = null;
string appBaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
if (Environment.Is64BitOperatingSystem)
{
if (CheckExecutableFile(ref executableFile, appBaseDirectory, "x64"))
{
return executableFile;
}
}
if (CheckExecutableFile(ref executableFile, appBaseDirectory, "x86"))
{
return executableFile;
}
throw new ExecutableNotFoundException("SlunkCrypt executable file not found!", FILENAME_FORMAT);
}
private static bool CheckExecutableFile(ref FileStream executableFile, string appBaseDirectory, string suffix)
{
try
{
executableFile = new FileStream(Path.Combine(appBaseDirectory, String.Format(FILENAME_FORMAT, suffix)), FileMode.Open, FileAccess.Read, FileShare.Read);
Version appVersion = VersionInfo.Version;
FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(executableFile.Name);
if (string.Equals(fileVersion.FileDescription, "SlunkCrypt", StringComparison.OrdinalIgnoreCase) &&
string.Equals(fileVersion.CompanyName, "Muldersoft", StringComparison.OrdinalIgnoreCase) &&
(fileVersion.FileMajorPart == appVersion.Major) && (fileVersion.FileMinorPart == appVersion.Minor))
{
return true;
}
executableFile.Dispose(); /*clean-up*/
}
catch { }
return false;
}
protected override double ParseProgressString(StringBuilder currentLine)
{
Match match;
double progress, result = double.NaN;
do
{
match = RX_PROGRESS.Match(currentLine.ToString());
if (match.Success)
{
if (!double.IsNaN(progress = ParseProgressValue(match)))
{
result = progress;
}
currentLine.Remove(match.Index, match.Length);
}
}
while (match.Success);
return result;
}
private static double ParseProgressValue(Match match)
{
uint intPart, fractPart;
if (uint.TryParse(match.Groups[1].Value, out intPart) && uint.TryParse(match.Groups[2].Value, out fractPart))
{
return ((intPart * 10) + fractPart) / 1000.0;
}
return double.NaN;
}
private string GetCommandString(Mode mode)
{
switch(mode)
{
case Mode.Encrypt:
return COMMAND_ENCRYPT;
case Mode.Decrypt:
return COMMAND_DECRYPT;
default:
throw new ArgumentException("Invalid mode!");
}
}
}
}

View File

@ -0,0 +1,23 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
[assembly: AssemblyTitle("SlunkCrypt GUI")]
[assembly: AssemblyDescription("SlunkCrypt GUI")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Muldersoft")]
[assembly: AssemblyProduct("SlunkCrypt")]
[assembly: AssemblyCopyright("Created by LoRd_MuldeR <MuldeR2@GMX.de>")]
[assembly: AssemblyTrademark("Muldersoft")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.0.0")]

63
gui/Properties/Resources.Designer.cs generated Normal file
View File

@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace com.muldersoft.slunkcrypt.gui.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("com.muldersoft.slunkcrypt.gui.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

26
gui/Properties/Settings.Designer.cs generated Normal file
View File

@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace com.muldersoft.slunkcrypt.gui.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="com.muldersoft.slunkcrypt.gui"/>
<description>SlunkCrypt GUI</description>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

BIN
gui/Resources/Banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

BIN
gui/Resources/Browse.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

BIN
gui/Resources/Cancel.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

BIN
gui/Resources/Exit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 B

BIN
gui/Resources/Eye.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
gui/Resources/Eye_1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
gui/Resources/Eye_2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,45 @@
The work in the Hack project is Copyright 2018 Source Foundry Authors and licensed under the MIT License
The work in the DejaVu project was committed to the public domain.
Bitstream Vera Sans Mono Copyright 2003 Bitstream Inc. and licensed under the Bitstream Vera License with Reserved Font Names "Bitstream" and "Vera"
### MIT License
Copyright (c) 2018 Source Foundry Authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
### BITSTREAM VERA LICENSE
Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a trademark of Bitstream, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of the fonts accompanying this license ("Fonts") and associated documentation files (the "Font Software"), to reproduce and distribute the Font Software, including without limitation the rights to use, copy, merge, publish, distribute, and/or sell copies of the Font Software, and to permit persons to whom the Font Software is furnished to do so, subject to the following conditions:
The above copyright and trademark notices and this permission notice shall be included in all copies of one or more of the Font Software typefaces.
The Font Software may be modified, altered, or added to, and in particular the designs of glyphs or characters in the Fonts may be modified and additional glyphs or characters may be added to the Fonts, only if the fonts are renamed to names not containing either the words "Bitstream" or the word "Vera".
This License becomes null and void to the extent applicable to Fonts or Font Software that has been modified and is distributed under the "Bitstream Vera" names.
The Font Software may be sold as part of a larger software package but no copy of one or more of the Font Software typefaces may be sold by itself.
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
Except as contained in this notice, the names of Gnome, the Gnome Foundation, and Bitstream Inc., shall not be used in advertising or otherwise to promote the sale, use or other dealings in this Font Software without prior written authorization from the Gnome Foundation or Bitstream Inc., respectively. For further information, contact: fonts at gnome dot org.

BIN
gui/Resources/Info.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

BIN
gui/Resources/Start.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

BIN
gui/Resources/Stop.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 345 B

186
gui/SlunkCryptGUI.csproj Normal file
View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{568F3936-B520-4371-981C-E7A4DA781737}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>com.muldersoft.slunkcrypt.gui</RootNamespace>
<AssemblyName>slunkcrypt-gui</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>$(SolutionDir)bin\Debug\</OutputPath>
<IntermediateOutputPath>$(SolutionDir)obj\Debug\SlunkCryptGUI\</IntermediateOutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>$(SolutionDir)bin\Release\</OutputPath>
<IntermediateOutputPath>$(SolutionDir)obj\Release\SlunkCryptGUI\</IntermediateOutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup>
<StartupObject>com.muldersoft.slunkcrypt.gui.App</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\Application.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<RunPostBuildEvent>OnOutputUpdated</RunPostBuildEvent>
</PropertyGroup>
<PropertyGroup />
<PropertyGroup />
<PropertyGroup>
<ApplicationManifest>Resources\Application.manifest</ApplicationManifest>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Controls\Hyperlink.xaml.cs">
<DependentUpon>Hyperlink.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\ImageToggleButton.xaml.cs">
<DependentUpon>ImageToggleButton.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\PasswordToggleBox.xaml.cs">
<DependentUpon>PasswordToggleBox.xaml</DependentUpon>
</Compile>
<Compile Include="Process\SlunkCryptRunner.cs" />
<Compile Include="Utilities\BusyManager.cs" />
<Compile Include="Utilities\PathUtils.cs" />
<Compile Include="Utilities\SystemMenu.cs" />
<Compile Include="Utilities\VisibilityConverter.cs" />
<Compile Include="Utilities\FontSizeConverter.cs" />
<Compile Include="Utilities\ProcessRunner.cs" />
<Compile Include="Utilities\VersionInfo.cs" />
<Page Include="Controls\Hyperlink.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\ImageToggleButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\PasswordToggleBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SlunkCryptGUI.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="SlunkCryptGUI.xaml.cs">
<DependentUpon>SlunkCryptGUI.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<AppDesigner Include="Properties\" />
<None Include="Resources\Application.manifest" />
<Resource Include="Resources\Fonts\Hack-Bold.ttf" />
<Resource Include="Resources\Fonts\Hack-BoldItalic.ttf" />
<Resource Include="Resources\Fonts\Hack-Italic.ttf" />
<Resource Include="Resources\Fonts\Hack-Regular.ttf" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Banner.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Application.ico" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Cancel.png" />
<Resource Include="Resources\Exit.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Info.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Start.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Browse.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Eye_1.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Eye_2.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Tab_Encrypt.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Tab_Decrypt.png" />
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\Tab_LogFile.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

185
gui/SlunkCryptGUI.xaml Normal file
View File

@ -0,0 +1,185 @@
<Window x:Class="com.muldersoft.slunkcrypt.gui.SlunkCryptGUI"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:com.muldersoft.slunkcrypt.gui"
xmlns:utils="clr-namespace:com.muldersoft.slunkcrypt.gui.utils"
xmlns:ctrls="clr-namespace:com.muldersoft.slunkcrypt.gui.ctrls"
mc:Ignorable="d"
Title="SlunkCrypt GUI"
Icon="pack://application:,,,/slunkcrypt-gui;component/Resources/Application.ico"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
ResizeMode="NoResize"
WindowStyle="ThreeDBorderWindow"
UseLayoutRounding="True"
AllowDrop="True"
Loaded="Window_Loaded" Closing="Window_Closing"
PreviewDragEnter="Window_PreviewDragEnter" PreviewDragOver="Window_PreviewDragEnter" PreviewDragLeave="Window_PreviewDragLeave" PreviewDrop="Window_PreviewDrop"
PreviewKeyDown="Window_PreviewKeyDown">
<Window.Resources>
<BitmapImage x:Key="ImageSource_Banner" UriSource="Resources/Banner.png"/>
<BitmapImage x:Key="ImageSource_Browse" UriSource="Resources/Browse.png"/>
<BitmapImage x:Key="ImageSource_Cancel" UriSource="Resources/Cancel.png"/>
<BitmapImage x:Key="ImageSource_Exit" UriSource="Resources/Exit.png"/>
<BitmapImage x:Key="ImageSource_Eye1" UriSource="Resources/Eye_1.png"/>
<BitmapImage x:Key="ImageSource_Eye2" UriSource="Resources/Eye_2.png"/>
<BitmapImage x:Key="ImageSource_Info" UriSource="Resources/Info.png"/>
<BitmapImage x:Key="ImageSource_Start" UriSource="Resources/Start.png"/>
<BitmapImage x:Key="ImageSource_TabHd1" UriSource="Resources/Tab_Encrypt.png"/>
<BitmapImage x:Key="ImageSource_TabHd2" UriSource="Resources/Tab_Decrypt.png"/>
<BitmapImage x:Key="ImageSource_TabHd3" UriSource="Resources/Tab_LogFile.png"/>
<FontFamily x:Key="Monospace">pack://application:,,,/Resources/Fonts/#Hack</FontFamily>
<utils:FontSizeConverter x:Key="SlightlySmallFont" Ratio="0.875"/>
<utils:FontSizeConverter x:Key="SlightlyLargerFont" Ratio="1.125"/>
<utils:VisibilityConverter x:Key="VisibilityConverter" Collapse="False"/>
</Window.Resources>
<Window.TaskbarItemInfo>
<TaskbarItemInfo/>
</Window.TaskbarItemInfo>
<StackPanel Style="{StaticResource WaitCursorWhileBusy}" Background="Transparent">
<Grid>
<Image Source="{StaticResource ImageSource_Banner}" Stretch="None" MouseLeftButtonDown="Image_MouseLeftButtonDown" Name="Banner"/>
<Canvas x:Name="Canvas" IsHitTestVisible="False" Visibility="{Binding IsBusy, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Converter={StaticResource VisibilityConverter}}" Opacity="0.8"/>
</Grid>
<Separator Margin="0"/>
<StackPanel>
<StackPanel Margin="12,16,12,12">
<TextBlock FontWeight="SemiBold" Text="Process has not been started yet. Please click the &quot;Start&quot; button to begin!" FontSize="{Binding FontSize, Converter={StaticResource SlightlyLargerFont}, RelativeSource={RelativeSource FindAncestor, AncestorType=Control}}" Margin="0,0,0,5" Name="Label_Status"/>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ProgressBar Grid.Column="0" Height="25" Name="ProgressBar" Value="0.0" Maximum="1.0"/>
<TextBlock Grid.Column="0" Text="" FontWeight="Bold" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Name="Label_Progress"/>
<Button Grid.Column="1" Style="{StaticResource EnableWhileBusy}" Margin="2,0,0,0" Click="Button_AbortProcess_Click" Name="Button_Abort" ToolTip="Abort!" Focusable="False" IsTabStop="False">
<Image Source="{StaticResource ImageSource_Cancel}" Margin="4,0,4,0" Style="{StaticResource GrayOutIfDisabled}"/>
</Button>
</Grid>
<TabControl x:Name="TabControl" Margin="0,18,0,0" Style="{StaticResource HitInvisibleWhileBusy}" SelectionChanged="TabControl_SelectionChanged">
<TabItem Name="TabItem_Encrypt" Tag="{x:Static local:ModeOfOperation.Encrypt}">
<TabItem.Header>
<StackPanel Orientation="Horizontal" Margin="10,0,10,0">
<Image Source="{StaticResource ImageSource_TabHd1}" Stretch="None"/>
<TextBlock Text="Encrypt" FontWeight="Bold" Style="{StaticResource HighlightIfSelected}" Margin="5,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</TabItem.Header>
<StackPanel Margin="12,4,12,12">
<TextBlock FontWeight="SemiBold" Text="Input Plaintext File:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<Button DockPanel.Dock="Right" Padding="7,0,7,0" Margin="3,0,0,0" Click="Button_Encrypt_InputFile_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Browse}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,3,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None"/>
<TextBlock Text="Browse..." VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<TextBox DockPanel.Dock="Left" Padding="3" Name="Edit_Encrypt_InputFile" Tag="{Binding ElementName=Edit_Encrypt_OutputFile}" KeyDown="Edit_FileName_KeyDown" LostFocus="Edit_FileName_LostFocus" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PATH}"/>
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Output Ciphertext File:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<Button DockPanel.Dock="Right" Padding="7,0,7,0" Margin="3,0,0,0" Click="Button_Encrypt_OutputFile_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Browse}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,3,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None"/>
<TextBlock Text="Browse..." VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<TextBox DockPanel.Dock="Left" Padding="3" Name="Edit_Encrypt_OutputFile" Tag="{Binding ElementName=Edit_Encrypt_Password}" KeyDown="Edit_FileName_KeyDown" LostFocus="Edit_FileName_LostFocus" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PATH}"/>
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Encrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}"/>
<ctrls:PasswordToggleBox DockPanel.Dock="Left" EditPadding="3,5,3,5" x:Name="Edit_Encrypt_Password" EditFontFamily="{StaticResource Monospace}" IsRevealed="{Binding IsChecked, ElementName=Button_Encrypt_Toggle}" PasswordChar="*" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PASSWD_LENGTH}" Entered="Edit_Password_Entered"/>
</DockPanel>
</StackPanel>
</TabItem>
<TabItem Name="TabItem_Decrypt" Tag="{x:Static local:ModeOfOperation.Decrypt}">
<TabItem.Header>
<StackPanel Orientation="Horizontal" Margin="10,0,10,0">
<Image Source="{StaticResource ImageSource_TabHd2}" Stretch="None"/>
<TextBlock Text="Decrypt" FontWeight="Bold" Style="{StaticResource HighlightIfSelected}" Margin="5,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</TabItem.Header>
<StackPanel Margin="12,4,12,12">
<TextBlock FontWeight="SemiBold" Text="Input Ciphertext File:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<Button DockPanel.Dock="Right" Padding="7,0,7,0" Margin="3,0,0,0" Click="Button_Decrypt_InputFile_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Browse}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,3,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None"/>
<TextBlock Text="Browse..." VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<TextBox DockPanel.Dock="Left" Padding="3" Name="Edit_Decrypt_InputFile" Tag="{Binding ElementName=Edit_Decrypt_OutputFile}" KeyDown="Edit_FileName_KeyDown" LostFocus="Edit_FileName_LostFocus" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PATH}"/>
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Output Plaintext File:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<Button DockPanel.Dock="Right" Padding="7,0,7,0" Margin="3,0,0,0" Click="Button_Decrypt_OutputFile_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Browse}" VerticalAlignment="Center" HorizontalAlignment="Center" Margin="0,0,3,0" Style="{StaticResource GrayOutIfDisabled}" Stretch="None"/>
<TextBlock Text="Browse..." VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<TextBox DockPanel.Dock="Left" Padding="3" Name="Edit_Decrypt_OutputFile" Tag="{Binding ElementName=Edit_Decrypt_Password}" KeyDown="Edit_FileName_KeyDown" LostFocus="Edit_FileName_LostFocus" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PATH}"/>
</DockPanel>
<TextBlock FontWeight="SemiBold" Text="Passphrase:" Margin="0,10,0,0"/>
<DockPanel Margin="0,5,0,0">
<ctrls:ImageToggleButton DockPanel.Dock="Right" Margin="3,0,0,0" x:Name="Button_Decrypt_Toggle" ImageSourceDefault="{StaticResource ImageSource_Eye1}" ImageSourceChecked="{StaticResource ImageSource_Eye2}"/>
<ctrls:PasswordToggleBox DockPanel.Dock="Left" EditPadding="3,5,3,5" x:Name="Edit_Decrypt_Password" EditFontFamily="{StaticResource Monospace}" IsRevealed="{Binding IsChecked, ElementName=Button_Decrypt_Toggle}" PasswordChar="*" MaxLength="{x:Static local:SlunkCryptGUI.MAX_PASSWD_LENGTH}" Entered="Edit_Password_Entered"/>
</DockPanel>
</StackPanel>
</TabItem>
<TabItem Name="TabItem_LogFile">
<TabItem.Header>
<StackPanel Orientation="Horizontal" Margin="10,0,10,0">
<Image Source="{StaticResource ImageSource_TabHd3}" Stretch="None"/>
<TextBlock Text="Logfile" FontWeight="Bold" Style="{StaticResource HighlightIfSelected}" Margin="5,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</TabItem.Header>
<DockPanel Margin="12">
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<ctrls:Hyperlink LinkText="Copy to Clipboard" Margin="0,3,0,0" Click="Link_CopyToClipboard_Click"/>
<ctrls:Hyperlink LinkText="Clear" Margin="7,3,0,0" Click="Link_ClearLog_Click"/>
</StackPanel>
<Grid>
<ListView DockPanel.Dock="Top" VerticalAlignment="Stretch" FontFamily="Courier New" FontSize="{Binding FontSize, Converter={StaticResource SlightlySmallFont}, RelativeSource={RelativeSource FindAncestor, AncestorType=Control}}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ItemsSource="{Binding LogFile, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" ItemContainerStyle="{StaticResource ItemToolTips}"/>
<TextBlock Text="The log file is empty. Please check back later!" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" Foreground="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" DataContext="{Binding LogFile, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}" Style="{StaticResource HideIfNotEmpty}"/>
</Grid>
</DockPanel>
</TabItem>
</TabControl>
</StackPanel>
<Separator Margin="0,5,0,5"/>
<Grid Name="Grid_ButtonBar" Margin="12" Style="{StaticResource DisableWhileBusy}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Padding="25,4,25,4" Name="Button_Start" MinWidth="125" Click="Button_Start_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Start}" Margin="0,0,5,0" Style="{StaticResource GrayOutIfDisabled}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock FontWeight="Bold" Text="Start" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Column="2" Padding="25,4,25,4" Name="Button_About" Margin="10,0,0,0" MinWidth="125" Click="Button_About_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Info}" Margin="0,0,5,0" Style="{StaticResource GrayOutIfDisabled}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock FontWeight="Bold" Text="About..." VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
<Button Grid.Column="4" Padding="25,4,25,4" Name="Button_Exit" MinWidth="125" Click="Button_Exit_Click">
<StackPanel Orientation="Horizontal">
<Image Source="{StaticResource ImageSource_Exit}" Margin="0,0,5,0" Style="{StaticResource GrayOutIfDisabled}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock FontWeight="Bold" Text="Exit" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center"/>
</StackPanel>
</Button>
</Grid>
</StackPanel>
</StackPanel>
</Window>

949
gui/SlunkCryptGUI.xaml.cs Normal file
View File

@ -0,0 +1,949 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Media;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shell;
using System.Windows.Threading;
using Microsoft.Win32;
using com.muldersoft.slunkcrypt.gui.ctrls;
using com.muldersoft.slunkcrypt.gui.process;
using com.muldersoft.slunkcrypt.gui.utils;
namespace com.muldersoft.slunkcrypt.gui
{
public enum ModeOfOperation { Encrypt, Decrypt }
public partial class SlunkCryptGUI : Window, INotifyBusyChanged
{
private enum Status { Default, Success, Failure }
private delegate Task<bool> SlunkProcessor(string inputFile, string outputFile, string password);
public event PropertyChangedEventHandler PropertyChanged;
public const int MIN_PASSWD_LENGTH = 8, REC_PASSWD_LENGTH = 12, MAX_PASSWD_LENGTH = 256, MAX_PATH = 259;
private readonly Lazy<string> m_about = new Lazy<string>(CreateAboutText);
private readonly Random m_random = new Random();
private readonly ObservableCollection<string> m_logFile = new ObservableCollection<string>();
private readonly string m_defaultStatusText;
private readonly DispatcherTimer m_dispatcherTimer;
private readonly ReadOnlyObservableCollection<string> m_logFileReadOnly;
private volatile ModeOfOperation m_modeOfOperation = (ModeOfOperation)(-1);
private volatile bool m_busyFlag = false, m_checksumError = false, m_processReceived = false, m_checked = false;
private volatile SlunkCryptRunner m_processRunner = null;
private const string ASCII_CHARS = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
// =============================================================================
// Constructor
// =============================================================================
public SlunkCryptGUI()
{
InitializeComponent();
m_defaultStatusText = Label_Status.Text;
m_dispatcherTimer = new DispatcherTimer(DispatcherPriority.ApplicationIdle, Dispatcher);
m_dispatcherTimer.Tick += DispatcherTimer_Tick;
m_dispatcherTimer.Interval = TimeSpan.FromMilliseconds(150);
m_logFileReadOnly = new ReadOnlyObservableCollection<string>(m_logFile);
}
// =============================================================================
// Properties
// =============================================================================
public bool IsBusy
{
get
{
return m_busyFlag;
}
set
{
m_dispatcherTimer.IsEnabled = m_busyFlag = value;
NotifyPropertyChanged("IsBusy");
}
}
public ReadOnlyObservableCollection<string> LogFile
{
get
{
return m_logFileReadOnly;
}
}
// =============================================================================
// Event handlers
// =============================================================================
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
TabControl.MinHeight = TabControl.MaxHeight = TabControl.ActualHeight;
MinWidth = MaxWidth = ActualWidth;
MinHeight = MaxHeight = ActualHeight;
}
private void Button_Encrypt_InputFile_Click(object sender, RoutedEventArgs e)
{
string fileName;
if (!string.IsNullOrEmpty(fileName = BrowseForFile(Edit_Encrypt_InputFile.Text, false)))
{
Edit_Encrypt_InputFile.Text = fileName;
Edit_Encrypt_OutputFile.Text = GenerateEncryptOutputFileName(fileName);
}
}
private void Button_Encrypt_OutputFile_Click(object sender, RoutedEventArgs e)
{
string fileName;
if (!string.IsNullOrEmpty(fileName = BrowseForFile(Edit_Encrypt_OutputFile.Text, true, "Encrypted file (*.enc)|*.enc")))
{
Edit_Encrypt_OutputFile.Text = fileName;
}
}
private void Button_Decrypt_InputFile_Click(object sender, RoutedEventArgs e)
{
string fileName;
if (!string.IsNullOrEmpty(fileName = BrowseForFile(Edit_Decrypt_InputFile.Text, false)))
{
Edit_Decrypt_InputFile.Text = fileName;
Edit_Decrypt_OutputFile.Text = GenerateDecryptOutputFileName(fileName);
}
}
private void Button_Decrypt_OutputFile_Click(object sender, RoutedEventArgs e)
{
string fileName;
if (!string.IsNullOrEmpty(fileName = BrowseForFile(Edit_Decrypt_OutputFile.Text, true, "Decrypted file (*.out)|*.out")))
{
Edit_Decrypt_OutputFile.Text = fileName;
}
}
private async void Button_Start_Click(object sender, RoutedEventArgs e)
{
if (!IsBusy)
{
ResetKeyboardFocus(Button_Start);
switch (GetModeOfOperation(TabControl.SelectedItem))
{
case ModeOfOperation.Encrypt:
Debug.Assert(m_modeOfOperation == ModeOfOperation.Encrypt);
await ValidateInputFile(Edit_Encrypt_InputFile, Edit_Encrypt_OutputFile, Edit_Encrypt_Password, Encrypt, true);
break;
case ModeOfOperation.Decrypt:
Debug.Assert(m_modeOfOperation == ModeOfOperation.Decrypt);
await ValidateInputFile(Edit_Decrypt_InputFile, Edit_Decrypt_OutputFile, Edit_Decrypt_Password, Decrypt, false);
break;
default:
TabControl.SelectedIndex = GetTabIndexOf(m_modeOfOperation);
break;
}
}
}
private void Button_About_Click(object sender, RoutedEventArgs e)
{
if (!IsBusy)
{
MessageBox.Show(this, m_about.Value, "About...", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
private void Button_Exit_Click(object sender, RoutedEventArgs e)
{
if (!IsBusy)
{
Application.Current.Shutdown();
}
}
private void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (object currrentItem in e.AddedItems)
{
ModeOfOperation? modeOfOperation = GetModeOfOperation(currrentItem);
if (modeOfOperation.HasValue)
{
if (m_modeOfOperation != modeOfOperation.Value)
{
SetStatus(m_defaultStatusText);
ClearProgress();
m_modeOfOperation = modeOfOperation.Value;
}
}
break;
}
}
private void Button_AbortProcess_Click(object sender, RoutedEventArgs e)
{
AbortProcess();
}
private void Link_CopyToClipboard_Click(object sender, MouseButtonEventArgs e)
{
if (m_logFile.Count > 0)
{
StringBuilder builder = new StringBuilder();
foreach (string logItem in m_logFile)
{
builder.AppendLine(logItem);
}
Clipboard.SetText(builder.ToString());
SystemSounds.Beep.Play();
}
}
private void Link_ClearLog_Click(object sender, MouseButtonEventArgs e)
{
if (m_logFile.Count > 0)
{
ClearLogFile();
SystemSounds.Beep.Play();
}
}
private void Process_OutputAvailable(string line, bool stderr)
{
AppendLogFile(line);
if (line.IndexOf("Checksum mismatch detected!", StringComparison.OrdinalIgnoreCase) >= 0)
{
m_checksumError = true;
}
}
private void Porcess_ProgressChanged(double progress)
{
if (!m_processReceived)
{
switch (m_modeOfOperation)
{
case ModeOfOperation.Encrypt:
SetStatus("Encrypting file contents. Please be patient, this can take a few moments...");
goto default;
case ModeOfOperation.Decrypt:
SetStatus("Decrypting file contents. Please be patient, this can take a few moments...");
goto default;
default:
m_processReceived = true;
break;
}
}
SetProgress(progress);
}
private void Edit_FileName_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
FrameworkElement source = sender as FrameworkElement;
if (!ReferenceEquals(source, null))
{
FrameworkElement target = source.Tag as FrameworkElement;
if (!ReferenceEquals(target, null))
{
SetFocusAndSelectAll(target);
}
}
e.Handled = true;
}
}
private void Edit_Password_Entered(object sender, KeyEventArgs e)
{
if (!IsBusy)
{
Button_Start_Click(sender, e);
}
}
private void Edit_FileName_LostFocus(object sender, RoutedEventArgs e)
{
TextBox textBox;
if (!ReferenceEquals(textBox = sender as TextBox, null))
{
textBox.Text = PathUtils.CleanUpFilePathString(textBox.Text);
}
}
private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
AbortProcess();
}
}
protected void Window_PreviewDragEnter(object sender, DragEventArgs e)
{
e.Effects = ((!IsBusy) && e.Data.GetDataPresent(DataFormats.FileDrop)) ? DragDropEffects.Copy : DragDropEffects.None;
e.Handled = true;
}
private void Window_PreviewDragLeave(object sender, DragEventArgs e)
{
e.Handled = true;
}
private void Window_PreviewDrop(object sender, DragEventArgs e)
{
if (!IsBusy)
{
string[] droppedFiles = e.Data.GetData(DataFormats.FileDrop) as string[];
if (!ReferenceEquals(droppedFiles, null))
{
foreach (string currentFile in droppedFiles)
{
string fullFilePath = PathUtils.CleanUpFilePathString(currentFile);
if ((!string.IsNullOrEmpty(fullFilePath)) && File.Exists(fullFilePath))
{
TabControl.SelectedIndex = GetTabIndexOf(m_modeOfOperation);
switch (m_modeOfOperation)
{
case ModeOfOperation.Encrypt:
Edit_Encrypt_InputFile .Text = fullFilePath;
Edit_Encrypt_OutputFile.Text = GenerateEncryptOutputFileName(fullFilePath);
break;
case ModeOfOperation.Decrypt:
Edit_Decrypt_InputFile .Text = fullFilePath;
Edit_Decrypt_OutputFile.Text = GenerateDecryptOutputFileName(fullFilePath);
break;
}
break;
}
}
}
}
e.Handled = true;
}
private async void Window_Loaded(object sender, RoutedEventArgs e)
{
await Task.Yield();
new SystemMenu(this).AppendMenu("Enable Expert Mode", SystemMenu_Activated);
CreateIndicatorElements();
}
private void Window_Closing(object sender, CancelEventArgs e)
{
if (IsBusy)
{
SystemSounds.Hand.Play();
e.Cancel = true;
}
}
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
ShuffleIndicatorElements();
}
private void SystemMenu_Activated(SystemMenu sender, uint menuId)
{
if (m_checked = (!m_checked))
{
sender.ModifyMenu(menuId, true);
try
{
Process.Start("https://youtu.be/Is_8bjYVmnA").Dispose();
}
catch { }
}
else
{
sender.ModifyMenu(menuId, false);
}
}
// =============================================================================
// Internal methods
// =============================================================================
private async Task ValidateInputFile(TextBox inputFileEdit, TextBox outputFileEdit, PasswordToggleBox passwordEdit, SlunkProcessor processor, bool checkStrongPasswd)
{
string inputFilePath;
if (string.IsNullOrEmpty(inputFileEdit.Text = inputFilePath = PathUtils.CleanUpFilePathString(inputFileEdit.Text)))
{
MessageBox.Show(this, "Input file must be selected first!", "Input File Missing", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(inputFileEdit);
return;
}
if (PathUtils.IsInvalidPath(inputFilePath))
{
MessageBox.Show(this, "The specified input file path is invalid!", "Input File Invalid", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(inputFileEdit);
return;
}
if (Directory.Exists(inputFilePath))
{
MessageBox.Show(this, "Specified input file appears to be a directory!", "Input File Invalid", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(inputFileEdit);
return;
}
if (!File.Exists(inputFilePath))
{
MessageBox.Show(this, "Specified input file could not be found!", "Input Not Found", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(inputFileEdit);
return;
}
await ValidateOutputFile(inputFilePath, outputFileEdit, passwordEdit, processor, checkStrongPasswd);
}
private async Task ValidateOutputFile(string inputFilePath, TextBox outputFileEdit, PasswordToggleBox passwordEdit, SlunkProcessor processor, bool checkStrongPasswd)
{
string outputFilePath;
if (string.IsNullOrEmpty(outputFileEdit.Text = outputFilePath = PathUtils.CleanUpFilePathString(outputFileEdit.Text)))
{
MessageBox.Show(this, "Output file must be selected first!", "Output File Missing", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(outputFileEdit);
return;
}
if (PathUtils.IsInvalidPath(outputFilePath))
{
MessageBox.Show(this, "The specified output file path is invalid!", "Output File Invalid", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(outputFileEdit);
return;
}
if (Directory.Exists(outputFilePath))
{
MessageBox.Show(this, "Specified output file appears to be a directory!", "Output File Invalid", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(outputFileEdit);
return;
}
if (string.Equals(inputFilePath, outputFilePath, StringComparison.OrdinalIgnoreCase))
{
MessageBox.Show(this, "Input and output file can not be the same!", "File Name Conflict", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(outputFileEdit);
return;
}
if (File.Exists(outputFilePath))
{
if (MessageBox.Show(this, "Specified output file already existst! Overwrite?", "Output File Exists", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) != MessageBoxResult.Yes)
{
SetFocusAndSelectAll(outputFileEdit);
return;
}
}
await ValidateOutputDirectory(inputFilePath, outputFilePath, passwordEdit, processor, checkStrongPasswd);
}
private async Task ValidateOutputDirectory(string inputFilePath, string outputFilePath, PasswordToggleBox passwordEdit, SlunkProcessor processor, bool checkStrongPasswd)
{
string outputDirectory;
if (string.IsNullOrEmpty(outputDirectory = PathUtils.TryGetDirectoryName(outputFilePath)))
{
MessageBox.Show(this, "The output directory could not be determined!", "Output Directory Invalid", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
while (!Directory.Exists(outputDirectory))
{
if (MessageBox.Show(this, "Output directory does not exist yet! Create it now?", "Output Directory Nonexistent", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes) != MessageBoxResult.Yes)
{
return;
}
if (!PathUtils.TryCreateDirectory(outputDirectory))
{
MessageBox.Show(this, "The output directory could not be created!", "Directory Creation Failed", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
}
await ValidatePassword(inputFilePath, outputFilePath, passwordEdit, processor, checkStrongPasswd);
}
private async Task ValidatePassword(string inputFilePath, string outputFilePath, PasswordToggleBox passwordEdit, SlunkProcessor processor, bool checkStrongPasswd)
{
string passwordStr;
if (string.IsNullOrEmpty(passwordStr = passwordEdit.Password) || (passwordStr.Length < MIN_PASSWD_LENGTH))
{
MessageBox.Show(this, String.Format("Passphrase must be at least {0:D} characters in length!", MIN_PASSWD_LENGTH), "Passphrase Missing", MessageBoxButton.OK, MessageBoxImage.Warning);
SetFocusAndSelectAll(passwordEdit);
return;
}
if (checkStrongPasswd)
{
if (passwordStr.Length < REC_PASSWD_LENGTH)
{
if (MessageBox.Show(this, String.Format("Recommended passphrase length is at least {0:D} characters!", REC_PASSWD_LENGTH), "Short Passphrase", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) != MessageBoxResult.OK)
{
SetFocusAndSelectAll(passwordEdit);
return;
}
}
else if (IsWeakPassword(passwordStr))
{
if (MessageBox.Show(this, "Passphrase should contain a mix of upper case characters, lower case characters, digits and other characters!", "Weak Passphrase", MessageBoxButton.OKCancel, MessageBoxImage.Warning, MessageBoxResult.Cancel) != MessageBoxResult.OK)
{
SetFocusAndSelectAll(passwordEdit);
return;
}
}
}
await InvokeProcessor(inputFilePath, outputFilePath, passwordStr, processor);
}
private async Task InvokeProcessor(string inputFile, string outputFile, string password, SlunkProcessor processor)
{
using (BusyManager busyManager = new BusyManager(this))
{
ResetKeyboardFocus(this);
SetProgress(double.PositiveInfinity);
ClearLogFile();
Button_Decrypt_Toggle.IsChecked = Button_Encrypt_Toggle.IsChecked = m_checksumError = m_processReceived = false;
if (!await processor(inputFile, outputFile, password))
{
SetProgress(double.NaN, true);
PathUtils.TryRemoveFile(outputFile);
}
await Task.Yield();
}
}
private async Task<bool> Encrypt(string inputFile, string outputFile, string password)
{
SetStatus("Please wait while the encryption process is initializing...");
int? exitCode = await RunProcess(SlunkCryptRunner.Mode.Encrypt, inputFile, outputFile, password);
if (exitCode.HasValue)
{
if (exitCode.Value == 0)
{
SetProgress(1);
SetStatus("Completed: The file has been encrypted successfully.", Status.Success);
SystemSounds.Asterisk.Play();
}
else
{
SetProgress(1, true);
SetStatus("Error: Failed to enecrypt the file. Please see the log file for details!", Status.Failure);
SystemSounds.Hand.Play();
}
return true;
}
return false;
}
private async Task<bool> Decrypt(string inputFile, string outputFile, string password)
{
SetStatus("Please wait while the decryption process is initializing...");
int? exitCode = await RunProcess(SlunkCryptRunner.Mode.Decrypt, inputFile, outputFile, password);
if (exitCode.HasValue)
{
if (exitCode.Value == 0)
{
SetStatus("Completed: The file has been decrypted successfully (checksum is correct).", Status.Success);
SetProgress(1);
SystemSounds.Asterisk.Play();
}
else
{
if (m_checksumError)
{
SetStatus("Error: Checksum mismatch detected! Wrong passphrase or corrupted file?", Status.Failure);
}
else
{
SetStatus("Error: Failed to decrypt the file. Please see the log file for details!", Status.Failure);
}
SetProgress(1, true);
SystemSounds.Hand.Play();
}
return true;
}
return false;
}
private async Task<int?> RunProcess(SlunkCryptRunner.Mode mode, string inputFile, string outputFile, string password)
{
if (!ReferenceEquals(m_processRunner, null))
{
throw new InvalidOperationException("Process has already been started!");
}
try
{
using (m_processRunner = new SlunkCryptRunner(Dispatcher))
{
m_processRunner.OutputAvailable += Process_OutputAvailable;
m_processRunner.ProgressChanged += Porcess_ProgressChanged;
SetProcessPriority(ProcessPriorityClass.AboveNormal);
return await m_processRunner.ExecuteAsync(mode, inputFile, outputFile, password);
}
}
catch (ProcessRunner.ProcessStartException err)
{
SetStatus(string.Format("Error: The {0} process could not be created! (Error code: {1:D})", GetModeString(m_modeOfOperation), GetWin32ErrorCode(err)), Status.Failure);
MessageBox.Show(this, "Failed to create SlunkCrypt process:\n\n" + err.InnerException?.Message ?? err.Message, "Process Creation Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (SlunkCryptRunner.ExecutableNotFoundException)
{
SetStatus("Error: The required SlunkCrypt executable file could not be found!", Status.Failure);
MessageBox.Show(this, "The SlunkCrypt executable file could not be found.\n\nPlease make sure that the SlunkCrypt CLI executable file is located in the same directory as the GUI program!", "Executable Not Found", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (ProcessRunner.ProcessInterruptedException)
{
SetStatus(string.Format("Aborted: The {0} process was aborted by the user!", GetModeString(m_modeOfOperation)), Status.Failure);
SystemSounds.Hand.Play();
}
finally
{
m_processRunner = null; /*final clean-up*/
}
return null;
}
private void SetStatus(string text, Status status = Status.Default)
{
switch (status)
{
case Status.Success:
Label_Status.Foreground = Brushes.DarkGreen;
break;
case Status.Failure:
Label_Status.Foreground = Brushes.DarkRed;
break;
default:
Label_Status.Foreground = SystemColors.WindowTextBrush;
break;
}
Label_Status.Text = text;
}
private void SetProgress(double progress, bool failed = false)
{
if (!(double.IsNaN(progress) || double.IsInfinity(progress)))
{
ProgressBar.IsIndeterminate = false;
ProgressBar.Value = progress;
TaskbarItemInfo.ProgressState = failed ? TaskbarItemProgressState.Error : TaskbarItemProgressState.Normal;
TaskbarItemInfo.ProgressValue = progress;
Label_Progress.Text = string.Format(CultureInfo.InvariantCulture, "{0:0.0}%", progress * 100.0);
}
else
{
if (double.IsInfinity(progress))
{
ProgressBar.IsIndeterminate = true;
ProgressBar.Value = 0;
TaskbarItemInfo.ProgressState = TaskbarItemProgressState.Indeterminate;
Label_Progress.Text = string.Empty;
}
else
{
ProgressBar.IsIndeterminate = false;
TaskbarItemInfo.ProgressState = failed ? TaskbarItemProgressState.Error : TaskbarItemProgressState.None;
}
}
}
private void ClearProgress()
{
ProgressBar.IsIndeterminate = false;
ProgressBar.Value = 0;
TaskbarItemInfo.ProgressState = TaskbarItemProgressState.None;
Label_Progress.Text = string.Empty;
}
private void AbortProcess()
{
ProcessRunner processRunner;
if (!ReferenceEquals(processRunner = m_processRunner, null))
{
try
{
processRunner.AbortProcess();
}
catch { }
}
}
private string BrowseForFile(string fileName, bool saveDialog, string filterString = null)
{
FileDialog openFileDialog = saveDialog ? new SaveFileDialog() { OverwritePrompt = false } : (FileDialog) new OpenFileDialog();
openFileDialog.Filter = string.IsNullOrEmpty(filterString) ? "All files (*.*)|*.*" : filterString;
if (!string.IsNullOrEmpty(fileName))
{
openFileDialog.FileName = fileName;
}
if (openFileDialog.ShowDialog().GetValueOrDefault(false))
{
return openFileDialog.FileName;
}
return null;
}
private void CreateIndicatorElements()
{
FontFamily hackFont = new FontFamily(new Uri("pack://application:,,,/"), "./Resources/Fonts/#Hack");
DropShadowEffect dropShadowEffect = CreateShadowEffect(Colors.Black, 3.0);
TextBlock reference = CreateTextBlock('0', Brushes.Gold, hackFont, dropShadowEffect);
reference.Measure(new Size(double.MaxValue, double.MaxValue));
Size desiredSize = reference.DesiredSize;
double actualWidth = Canvas.ActualWidth, actualHeight = Canvas.ActualHeight;
int lenX = (int)Math.Ceiling(desiredSize.Width * 1.25);
int lenY = (int)Math.Ceiling(desiredSize.Height * 1.25);
int numX = (int)Math.Floor(actualWidth / lenX);
int numY = (int)Math.Floor(actualHeight / lenY);
int offX = (int)Math.Round((actualWidth - (numX * lenX)) / 2.0);
int offY = (int)Math.Round((actualHeight - (numY * lenY)) / 2.0);
for (int i = 0; i < numX; ++i)
{
for (int j = 0; j < numY; ++j)
{
TextBlock element = CreateTextBlock('0', Brushes.Gold, hackFont, dropShadowEffect);
Canvas.Children.Add(element);
Canvas.SetLeft(element, offX + (i * lenX));
Canvas.SetTop (element, offY + (j * lenY));
}
}
ShuffleIndicatorElements();
}
private void ShuffleIndicatorElements()
{
char[] chars = ASCII_CHARS.ToCharArray();
UIElementCollection children = Canvas.Children;
for (int i = 0; i < children.Count; ++i)
{
TextBlock element;
if (!ReferenceEquals(element = children[i] as TextBlock, null))
{
if (m_random.Next(7) == 0)
{
element.Visibility = Visibility.Visible;
element.Text = char.ToString(chars[m_random.Next(chars.Length)]);
}
else
{
element.Visibility = Visibility.Hidden;
}
}
}
}
private void AppendLogFile(string line)
{
if (!string.IsNullOrEmpty(line))
{
m_logFile.Add(line);
}
}
private int GetTabIndexOf(ModeOfOperation modeOfOperation)
{
ItemCollection collection = TabControl.Items;
for (int index = 0; index < collection.Count; ++index)
{
ModeOfOperation? current = GetModeOfOperation(collection[index]);
if (current.HasValue && (current.Value == modeOfOperation))
{
return index;
}
}
return -1;
}
private void ClearLogFile()
{
m_logFile.Clear();
}
private void NotifyPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
// -----------------------------------------------------------------------------
// Static methods
// -----------------------------------------------------------------------------
private static string CreateAboutText()
{
return new StringBuilder()
.AppendLine("SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>")
.AppendLine(VersionInfo.VersionStr)
.AppendLine("This work has been released under the \u201CCC0 1.0\u201D license!")
.AppendLine()
.AppendLine("Source-code repository:")
.AppendLine("https://gitlab.com/lord_mulder/slunkcrypt/")
.AppendLine()
.AppendLine("Operating System: " + Environment.OSVersion.VersionString)
.AppendLine(".NET Runtime Version: " + Environment.Version)
.AppendLine(string.Format("Processor Count: {0:D}, System Bitness: {1:D}, Process Bitness: {2:D}", Environment.ProcessorCount, Environment.Is64BitOperatingSystem ? 64 : 32, Environment.Is64BitProcess ? 64 : 32))
.AppendLine()
.AppendLine("Using “Silk” icons, by Mark James (famfamfam.com)")
.ToString();
}
private static string GenerateEncryptOutputFileName(string inputFilePath)
{
string directoryPath = Path.GetDirectoryName(inputFilePath), fileName = Path.GetFileNameWithoutExtension(inputFilePath), extension = Path.GetExtension(inputFilePath);
string outputFile = Path.Combine(directoryPath, string.Format("{0}{1}.enc", fileName, extension));
for (int count = 2; File.Exists(outputFile); ++count)
{
outputFile = Path.Combine(directoryPath, string.Format("{0} ({1:D}){2}.enc", fileName, count, extension));
}
return outputFile;
}
private static string GenerateDecryptOutputFileName(string inputFilePath)
{
string directoryPath = Path.GetDirectoryName(inputFilePath), fileName = Path.GetFileNameWithoutExtension(inputFilePath), extension = Path.GetExtension(inputFilePath);
while (extension.Equals(".enc", StringComparison.OrdinalIgnoreCase))
{
extension = Path.GetExtension(fileName);
fileName = Path.GetFileNameWithoutExtension(fileName);
}
if (string.IsNullOrEmpty(extension))
{
extension = ".out";
}
string outputFile = Path.Combine(directoryPath, string.Concat(fileName, extension));
for (int count = 2; File.Exists(outputFile); ++count)
{
outputFile = Path.Combine(directoryPath, String.Format("{0} ({1:D}){2}", fileName, count, extension));
}
return outputFile;
}
private static ModeOfOperation? GetModeOfOperation(object selectedItem)
{
TabItem selectedTabItem = selectedItem as TabItem;
if (!ReferenceEquals(selectedTabItem, null))
{
return selectedTabItem.Tag as ModeOfOperation?;
}
return null;
}
private static string GetModeString(ModeOfOperation modeOfOperation)
{
switch(modeOfOperation)
{
case ModeOfOperation.Encrypt:
return "encryption";
case ModeOfOperation.Decrypt:
return "decryption";
default:
throw new ArgumentException("modeOfOperation");
}
}
private static bool IsWeakPassword(string password)
{
int flags = 0;
foreach (char c in password)
{
if (char.IsLetter(c))
{
flags |= char.IsUpper(c) ? 0x2 : 0x1;
}
else
{
flags |= char.IsDigit(c) ? 0x8 : 0x4;
}
}
return (flags != 0xF);
}
private static void SetFocusAndSelectAll(FrameworkElement element)
{
TextBox textBox;
if (!ReferenceEquals(textBox = element as TextBox, null))
{
textBox.Focus();
textBox.SelectAll();
}
else
{
PasswordToggleBox passwordToggleBox;
if (!ReferenceEquals(passwordToggleBox = element as PasswordToggleBox, null))
{
passwordToggleBox.Focus();
passwordToggleBox.SelectAll();
}
}
}
private static void SetProcessPriority(ProcessPriorityClass priorityClass)
{
try
{
using (Process currentProcess = Process.GetCurrentProcess())
{
currentProcess.PriorityClass = priorityClass;
}
}
catch { }
}
private static int GetWin32ErrorCode(Exception err)
{
while (!ReferenceEquals(err, null))
{
if (err is Win32Exception)
{
return ((Win32Exception)err).NativeErrorCode;
}
err = err.InnerException;
}
return 0;
}
private static TextBlock CreateTextBlock(char c, Brush foreground, FontFamily fontFamily, Effect effect)
{
return new TextBlock()
{
Text = char.ToString(c),
Foreground = foreground,
FontFamily = fontFamily,
Effect = effect
};
}
private static DropShadowEffect CreateShadowEffect(Color color, double blurRadius)
{
return new DropShadowEffect()
{
Color = color,
BlurRadius = blurRadius,
Direction = 0.0,
ShadowDepth = 0.0
};
}
private static void ResetKeyboardFocus(UIElement element)
{
Keyboard.ClearFocus();
element.Focus();
}
private static string TrimToEmpty(string str)
{
return string.IsNullOrEmpty(str) ? string.Empty : str.Trim();
}
}
}

View File

@ -0,0 +1,43 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.ComponentModel;
namespace com.muldersoft.slunkcrypt.gui.utils
{
public interface INotifyBusyChanged : INotifyPropertyChanged
{
bool IsBusy { get; set; }
}
internal sealed class BusyManager : IDisposable
{
private volatile bool m_disposed = false;
private readonly INotifyBusyChanged m_instance;
public BusyManager(INotifyBusyChanged instance)
{
if (ReferenceEquals(m_instance = instance, null))
{
throw new ArgumentNullException();
}
if (m_instance.IsBusy)
{
throw new InvalidOperationException("Instance is busy!");
}
instance.IsBusy = true;
}
public void Dispose()
{
if (!m_disposed)
{
m_disposed = true;
m_instance.IsBusy = false;
}
}
}
}

View File

@ -0,0 +1,27 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Globalization;
using System.Windows.Data;
namespace com.muldersoft.slunkcrypt.gui.utils
{
class FontSizeConverter : IValueConverter
{
public double Ratio { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
double originalFontSize = (double)value;
return originalFontSize * Ratio;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

214
gui/Utilities/PathUtils.cs Normal file
View File

@ -0,0 +1,214 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.IO;
using System.Text;
namespace com.muldersoft.slunkcrypt.gui.utils
{
public static class PathUtils
{
private const char DOUBLE_QUOTE = '"', WILDCARD_ONE = '?', WILDCARD_ANY = '*';
private static readonly Lazy<string> m_homeDirectory = new Lazy<string>(InitHomeDirectory);
// =============================================================================
// Public methods
// =============================================================================
public static bool IsInvalidPath(string filePath)
{
if (!string.IsNullOrEmpty(filePath))
{
if (filePath.IndexOfAny(Path.GetInvalidPathChars()) >= 0)
{
return true;
}
foreach (char c in filePath.Substring(HasDrivePrefix(filePath) ? 2 : 0))
{
if (IsWildcardChar(c) || char.IsControl(c) || (c == Path.VolumeSeparatorChar))
{
return true;
}
}
if (IsDirectoryOrVolumeSeparatorChar(filePath[filePath.Length - 1]))
{
return true;
}
}
return false;
}
public static string CleanUpFilePathString(string filePath)
{
if (!string.IsNullOrEmpty(filePath))
{
filePath = NormalizePathSeparators(RemoveQuotesAndControlChars(filePath));
if (filePath.Length > 0)
{
try
{
if (!Path.IsPathRooted(filePath))
{
filePath = Path.Combine(m_homeDirectory.Value, filePath);
}
}
catch { }
try
{
filePath = Path.GetFullPath(filePath);
}
catch { }
}
}
return filePath;
}
public static string TryGetDirectoryName(string filePath)
{
if (!string.IsNullOrEmpty(filePath))
{
try
{
string directoryName = Path.GetDirectoryName(filePath);
if (!string.IsNullOrEmpty(directoryName))
{
return directoryName;
}
}
catch { }
}
return string.Empty;
}
public static bool TryCreateDirectory(string directoryPath)
{
try
{
Directory.CreateDirectory(directoryPath);
return true;
}
catch { }
return false;
}
public static void TryRemoveFile(string filePath)
{
try
{
File.Delete(filePath);
}
catch { }
}
// =============================================================================
// Internal methods
// =============================================================================
private static string RemoveQuotesAndControlChars(string filePath)
{
if (filePath.Length > 0)
{
StringBuilder sb = new StringBuilder();
foreach (char c in filePath)
{
if ((!char.IsControl(c)) || (c != DOUBLE_QUOTE))
{
sb.Append(c);
}
}
filePath = sb.ToString();
}
return filePath;
}
private static string NormalizePathSeparators(string filePath)
{
if (filePath.Length > 0)
{
StringBuilder sb = new StringBuilder();
char[] separators = new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar, Path.VolumeSeparatorChar };
string pathPrefix;
foreach (string token in SplitPathPrefix(out pathPrefix, filePath.Trim()).Split(separators, StringSplitOptions.RemoveEmptyEntries))
{
string tokenTrimmed = token.Trim();
if (tokenTrimmed.Length > 0)
{
((sb.Length > 0) ? sb.Append(Path.DirectorySeparatorChar) : sb.Append(pathPrefix)).Append(tokenTrimmed);
}
}
filePath = sb.ToString();
}
return filePath;
}
private static string SplitPathPrefix(out string prefix, string filePath)
{
if (HasDrivePrefix(filePath))
{
prefix = new string(new char[] { char.ToUpper(filePath[0]), Path.VolumeSeparatorChar, Path.DirectorySeparatorChar });
return filePath.Substring(2);
}
if (HasUNCPrefix(filePath))
{
prefix = new string(new char[] { Path.DirectorySeparatorChar, Path.DirectorySeparatorChar });
return filePath.Substring(2);
}
prefix = string.Empty;
return filePath;
}
private static string InitHomeDirectory()
{
try
{
return Environment.GetFolderPath(Environment.SpecialFolder.Personal);
}
catch
{
try
{
return Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
}
catch
{
return AppDomain.CurrentDomain.BaseDirectory;
}
}
}
private static bool HasDrivePrefix(string filePath)
{
return (filePath.Length > 1) && IsUsEnglishLetter(filePath[0]) && (filePath[1] == Path.VolumeSeparatorChar);
}
private static bool HasUNCPrefix(string filePath)
{
return (filePath.Length > 1) && IsDirectorySeparatorChar(filePath[0]) && IsDirectorySeparatorChar(filePath[1]);
}
private static bool IsDirectorySeparatorChar(char c)
{
return (c == Path.DirectorySeparatorChar) || (c == Path.AltDirectorySeparatorChar);
}
private static bool IsDirectoryOrVolumeSeparatorChar(char c)
{
return IsDirectorySeparatorChar(c) || (c == Path.VolumeSeparatorChar);
}
private static bool IsUsEnglishLetter(char c)
{
return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
}
private static bool IsWildcardChar(char c)
{
return ((c == WILDCARD_ONE) || (c == WILDCARD_ANY));
}
}
}

View File

@ -0,0 +1,354 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace com.muldersoft.slunkcrypt.gui.utils
{
class ProcessRunner : IDisposable
{
public delegate void OutputLineHandler(string line, bool stream);
public delegate void ProgressChangedHandler(double progress);
public delegate bool ProgressStringHandler(string line, out double progress);
public event OutputLineHandler OutputAvailable;
public event ProgressChangedHandler ProgressChanged;
public const bool STDOUT = false, STDERR = true;
private readonly Process m_process = new Process();
private readonly TaskCompletionSource<int> m_hasExited = new TaskCompletionSource<int>();
private readonly Dispatcher m_dispatcher;
private readonly ProcessPriorityClass? m_priorityClass;
private volatile bool m_running = false, m_aborted = false, m_disposed = false;
// =============================================================================
// Exception classes
// =============================================================================
public class ProcessStartException : IOException
{
public ProcessStartException(string message, Exception innerException) : base(message, innerException)
{
}
}
public class ProcessInterruptedException : IOException
{
public ProcessInterruptedException(string message) : base(message)
{
}
}
// =============================================================================
// Constructor
// =============================================================================
public ProcessRunner(Dispatcher dispatcher, ProcessPriorityClass? priorityClass = null)
{
if (ReferenceEquals(m_dispatcher = dispatcher, null))
{
throw new ArgumentException("Dispatcher must not be null!");
}
if ((m_priorityClass = priorityClass).HasValue && (!Enum.IsDefined(typeof(ProcessPriorityClass), priorityClass.Value)))
{
throw new ArgumentException("The given ProcessPriorityClass is undefined!");
}
m_process.StartInfo.UseShellExecute = false;
m_process.StartInfo.CreateNoWindow = true;
m_process.StartInfo.RedirectStandardOutput = true;
m_process.StartInfo.RedirectStandardError = true;
m_process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
m_process.StartInfo.StandardErrorEncoding = Encoding.UTF8;
m_process.EnableRaisingEvents = true;
m_process.Exited += ProcessExitedEventHandler;
}
~ProcessRunner()
{
Dispose(); /*just to be sure*/
}
// =============================================================================
// Public methods
// =============================================================================
public async Task<int> ExecAsnyc(string executablePath, string[] arguments = null, IReadOnlyDictionary<string, string> environmentVariables = null)
{
m_dispatcher.VerifyAccess();
if (m_disposed)
{
throw new ObjectDisposedException("ProcessRunner");
}
if (m_running)
{
throw new InvalidOperationException("Process is already running!");
}
m_running = true;
try
{
return await DoExecAsnyc(executablePath, arguments, environmentVariables);
}
finally
{
m_running = false;
}
}
public void AbortProcess()
{
if ((!m_disposed) && m_running)
{
m_aborted = true;
KillProcess();
}
}
public virtual void Dispose()
{
if (!m_disposed)
{
m_disposed = true;
GC.SuppressFinalize(this);
KillProcess();
try
{
m_process.Dispose();
}
catch { }
}
}
// =============================================================================
// Protected methods
// =============================================================================
protected virtual double ParseProgressString(StringBuilder currentLine)
{
return double.NaN;
}
// =============================================================================
// Event handlers
// =============================================================================
private void ProcessExitedEventHandler(object sender, EventArgs e)
{
if (m_process.HasExited)
{
m_hasExited.TrySetResult(m_process.ExitCode);
}
}
// =============================================================================
// Internal methods
// =============================================================================
private async Task<int> DoExecAsnyc(string executablePath, string[] arguments, IReadOnlyDictionary<string, string> environmentVariables)
{
try
{
StartProcess(executablePath, arguments, environmentVariables);
}
catch (Exception err)
{
throw new ProcessStartException("Failed to create the process!", err);
}
return await WaitForExit();
}
private void StartProcess(string executablePath, string[] arguments, IReadOnlyDictionary<string, string> environmentVariables)
{
m_process.StartInfo.FileName = executablePath;
m_process.StartInfo.Arguments = CreateArgumentList(arguments);
SetupEnvironment(m_process.StartInfo.EnvironmentVariables, environmentVariables);
m_process.StartInfo.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
m_process.Start();
SetProcessPriority(m_priorityClass);
}
private async Task<int> WaitForExit()
{
Task readStdOutTask = Task.Run(() => ReadProcessOutput(m_process.StandardOutput, STDOUT));
Task readStdErrTask = Task.Run(() => ReadProcessOutput(m_process.StandardError, STDERR));
Task<int> hasExited = m_hasExited.Task;
await Task.WhenAll(readStdOutTask, readStdErrTask, hasExited);
if (m_aborted || m_disposed)
{
NotifyOutputAvailable("\u2192 Process has been aborted !!!", true);
throw new ProcessInterruptedException("Process has been aborted!");
}
NotifyOutputAvailable(string.Format("\u2192 Process terminated normally [Exit status: {0:D}]", hasExited.Result), false);
return hasExited.Result;
}
private void ReadProcessOutput(StreamReader reader, bool stream)
{
using(reader)
{
char[] buffer = new char[1024];
StringBuilder currentLine = new StringBuilder();
while (!reader.EndOfStream)
{
ReadNextChunk(reader, buffer, currentLine, stream);
}
NotifyOutputAvailable(currentLine, stream);
}
}
private void ReadNextChunk(StreamReader reader, char[] buffer, StringBuilder currentLine, bool stderr)
{
int count = reader.Read(buffer, 0, buffer.Length);
if (count > 0)
{
for (int i = 0; i < count; ++i)
{
char c = buffer[i];
if ((c != '\0') && (c != '\n') && (c != '\r') && (c != '\b'))
{
currentLine.Append(c);
}
else
{
CheckForProgressUpdate(currentLine);
NotifyOutputAvailable(currentLine, stderr);
currentLine.Clear();
}
}
CheckForProgressUpdate(currentLine);
}
}
private void CheckForProgressUpdate(StringBuilder currentLine)
{
if (currentLine.Length > 0)
{
double progress = ParseProgressString(currentLine);
if (!(double.IsNaN(progress) || double.IsInfinity(progress)))
{
NotifyProgressChanged(progress);
}
}
}
private void NotifyOutputAvailable(StringBuilder currentLine, bool stream)
{
if (currentLine.Length > 0)
{
String line = currentLine.ToString().Trim();
if (!string.IsNullOrEmpty(line))
{
NotifyOutputAvailable(line, stream);
}
}
}
private void NotifyOutputAvailable(string line, bool stream)
{
if (!ReferenceEquals(OutputAvailable, null))
{
m_dispatcher.InvokeAsync(() => OutputAvailable(line, stream));
}
}
private void NotifyProgressChanged(double progress)
{
if (!ReferenceEquals(ProgressChanged, null))
{
m_dispatcher.InvokeAsync(() => ProgressChanged(Math.Max(0.0, Math.Min(1.0, progress))));
}
}
private static string CreateArgumentList(string[] arguments)
{
StringBuilder argumentList = new StringBuilder();
if (!ReferenceEquals(arguments, null))
{
for (int i = 0; i < arguments.Length; ++i)
{
if (i > 0)
{
argumentList.Append("\x20");
}
argumentList.Append(EscapeArgument(arguments[i]));
}
}
return argumentList.ToString();
}
private static string EscapeArgument(string str)
{
if (RequiresQuotation(str))
{
StringBuilder sb = new StringBuilder().Append('"');
foreach (char c in str)
{
if (c == '"')
{
sb.Append('\\').Append('"');
}
else
{
sb.Append(c);
}
}
return sb.Append('"').ToString();
}
return str;
}
private static bool RequiresQuotation(string str)
{
foreach (char c in str)
{
if (char.IsWhiteSpace(c) || (c == '"'))
{
return true;
}
}
return false;
}
private static void SetupEnvironment(StringDictionary dictionary, IReadOnlyDictionary<string, string> environmentVariables)
{
if (!ReferenceEquals(environmentVariables, null))
{
foreach (KeyValuePair<string, string> entry in environmentVariables)
{
dictionary.Add(entry.Key, entry.Value);
}
}
}
private void KillProcess()
{
try
{
m_process.Kill();
}
catch { }
}
private void SetProcessPriority(ProcessPriorityClass? priorityClass)
{
try
{
if (priorityClass.HasValue)
{
m_process.PriorityClass = priorityClass.Value;
}
}
catch { }
}
}
}

186
gui/Utilities/SystemMenu.cs Normal file
View File

@ -0,0 +1,186 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
namespace com.muldersoft.slunkcrypt.gui.utils
{
using ItemInfo = Tuple<string, SystemMenu.SystemMenuActionHandler>;
class SystemMenu : IDisposable
{
private const int WM_SYSCOMMAND = 0x112;
public delegate void SystemMenuActionHandler(SystemMenu sender, uint menuId);
private readonly HwndSource m_hwndSource;
private readonly Dictionary<uint, ItemInfo> m_menuItems = new Dictionary<uint, ItemInfo>();
private bool m_firstItem = true;
private uint m_nextMenuId = 100;
private volatile bool m_disposed = false;
// =============================================================================
// Constructor
// =============================================================================
public SystemMenu(Window window)
{
if (ReferenceEquals(window, null))
{
throw new ArgumentNullException("Window must not be null!");
}
window.Dispatcher.VerifyAccess();
m_hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(window).Handle);
m_hwndSource.AddHook(WndProcHook);
}
// =============================================================================
// Public methods
// =============================================================================
public uint AppendMenu(string captionStr, SystemMenuActionHandler handler)
{
if (m_disposed)
{
throw new ObjectDisposedException("Already disposed!");
}
if (ReferenceEquals(handler, null))
{
throw new ArgumentNullException("SystemMenuActionHandler must not be null!");
}
m_hwndSource.Dispatcher.VerifyAccess();
IntPtr hSysMenu = GetSystemMenu(m_hwndSource.Handle, false);
if (hSysMenu != IntPtr.Zero)
{
if (m_firstItem)
{
if (AppendMenu(hSysMenu, Native.MenuFlags.MF_SEPARATOR, 0, string.Empty))
{
m_firstItem = false;
}
}
if (AppendMenu(hSysMenu, Native.MenuFlags.MF_STRING, m_nextMenuId, captionStr))
{
uint menuItemId = m_nextMenuId++;
m_menuItems.Add(menuItemId, Tuple.Create(captionStr, handler));
return menuItemId;
}
}
return 0;
}
public bool ModifyMenu(uint menuId, bool isChecked)
{
if (m_disposed)
{
throw new ObjectDisposedException("Already disposed!");
}
m_hwndSource.Dispatcher.VerifyAccess();
ItemInfo itemInfo;
if (m_menuItems.TryGetValue(menuId, out itemInfo))
{
IntPtr hSysMenu = GetSystemMenu(m_hwndSource.Handle, false);
if (hSysMenu != IntPtr.Zero)
{
return ModifyMenu(hSysMenu, menuId, Native.MenuFlags.MF_BYCOMMAND | (isChecked ? Native.MenuFlags.MF_CHECKED : Native.MenuFlags.MF_UNCHECKED), menuId, itemInfo.Item1);
}
return false;
}
else
{
throw new ArgumentException("Menu item ID is unknown!");
}
}
// =============================================================================
// Internal methods
// =============================================================================
private IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_SYSCOMMAND)
{
uint menuId = (uint)wParam.ToInt32();
ItemInfo itemInfo;
if (m_menuItems.TryGetValue(menuId, out itemInfo))
{
itemInfo.Item2(this, menuId);
handled = true;
}
}
return IntPtr.Zero;
}
private IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert)
{
try
{
return Native.GetSystemMenu(hWnd, bRevert);
}
catch
{
return IntPtr.Zero;
}
}
private bool AppendMenu(IntPtr hMenu, Native.MenuFlags uFlags, uint uIDNewItem, string lpNewItem)
{
try
{
return Native.AppendMenu(hMenu, uFlags, new UIntPtr(uIDNewItem), lpNewItem);
}
catch
{
return false;
}
}
private bool ModifyMenu(IntPtr hMenu, uint uPosition, Native.MenuFlags uFlags, uint uIDNewItem, string lpNewItem)
{
return Native.ModifyMenu(hMenu, uPosition, uFlags, new UIntPtr(uIDNewItem), lpNewItem);
}
public void Dispose()
{
if (!m_disposed)
{
m_disposed = true;
m_hwndSource.RemoveHook(WndProcHook);
}
}
// =============================================================================
// Event handlers
// =============================================================================
private class Native
{
[Flags]
public enum MenuFlags : uint
{
MF_STRING = 0x0000,
MF_UNCHECKED = 0x0000,
MF_BYCOMMAND = 0x0000,
MF_CHECKED = 0x0008,
MF_BYPOSITION = 0x0400,
MF_SEPARATOR = 0x0800
}
[DllImport("user32.dll")]
public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern bool AppendMenu(IntPtr hMenu, MenuFlags uFlags, UIntPtr uIDNewItem, string lpNewItem);
[DllImport("user32.dll")]
public static extern bool ModifyMenu(IntPtr hMenu, uint uPosition, MenuFlags uFlags, UIntPtr uIDNewItem, string lpNewItem);
}
}
}

View File

@ -0,0 +1,59 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Reflection;
namespace com.muldersoft.slunkcrypt.gui.utils
{
static class VersionInfo
{
private static readonly Lazy<Version> m_version = new Lazy<Version>(GetAssemblyVersion);
private static readonly Lazy<string> m_versionStr = new Lazy<string>(InitVersionString);
// =============================================================================
// Properties
// =============================================================================
public static Version Version
{
get { return m_version.Value; }
}
public static string VersionStr
{
get { return m_versionStr.Value; }
}
// =============================================================================
// Internal methods
// =============================================================================
private static Version GetAssemblyVersion()
{
try
{
return Assembly.GetExecutingAssembly().GetName().Version;
}
catch
{
return new Version();
}
}
private static string InitVersionString()
{
try
{
DateTime buildDate = new DateTime(2000, 1, 1).Add(new TimeSpan(TimeSpan.TicksPerDay * Version.Build + TimeSpan.TicksPerSecond * 2 * Version.Revision));
return String.Format("Version {0:D}.{1:D}, built on {2}", Version.Major, Version.Minor, buildDate.ToString("yyyy-MM-dd"));
}
catch
{
return "Unknown version";
}
}
}
}

View File

@ -0,0 +1,30 @@
/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de> */
/* This work has been released under the CC0 1.0 Universal license! */
/******************************************************************************/
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace com.muldersoft.slunkcrypt.gui.utils
{
class VisibilityConverter : IValueConverter
{
public bool Inverse { get; set; } = false;
public bool Collapse { get; set; } = true;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((bool)value) ?
(Inverse ? (Collapse ? Visibility.Collapsed : Visibility.Hidden) : Visibility.Visible) :
(Inverse ? Visibility.Visible : (Collapse ? Visibility.Collapsed : Visibility.Hidden)) ;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@ -178,63 +178,63 @@
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_SSE2|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_WithDbgInfo|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-$(PlatformShortName)-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_SSE2|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_WithDbgInfo|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release_DLL|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)bin\$(PlatformShortName)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(PlatformShortName)\$(Configuration)\$(ProjectName)\</IntDir>
<TargetName>slunkcrypt-$(PlatformShortName)-1</TargetName>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)obj\$(Configuration)\$(PlatformShortName)\$(ProjectName)\</IntDir>
<TargetName>libslunkcrypt-1-$(PlatformShortName)</TargetName>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>