diff --git a/HashingTool/App.xaml b/HashingTool/App.xaml index 422c404afc0fed859e81a05023da91775028de36..5f3d51229ea9cca8b8b80f0dfd7f4b23ede717c4 100644 --- a/HashingTool/App.xaml +++ b/HashingTool/App.xaml @@ -2,6 +2,14 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Application.Resources> - + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <ResourceDictionary Source="Resources/Icon_XML_unknown.xaml" /> + <ResourceDictionary Source="Resources/Icon_XML_OK.xaml" /> + <ResourceDictionary Source="Resources/Icon_XML_NOK.xaml" /> + <ResourceDictionary Source="Resources/Icon_OK.xaml" /> + <ResourceDictionary Source="Resources/Icon_NOK.xaml" /> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> </Application.Resources> </Application> \ No newline at end of file diff --git a/HashingTool/HashingTool.csproj b/HashingTool/HashingTool.csproj index 7e8a498dbae3f94dce1afdc96d5ea665847d9c82..39deab7488b28a4a126dfd3db1c9ee3bec9451dd 100644 --- a/HashingTool/HashingTool.csproj +++ b/HashingTool/HashingTool.csproj @@ -63,9 +63,8 @@ <Generator>MSBuild:Compile</Generator> <SubType>Designer</SubType> </ApplicationDefinition> - <Compile Include="Helper\BoolViewConverter.cs" /> + <Compile Include="Helper\CollectionConverter.cs" /> <Compile Include="Helper\IOService.cs" /> - <Compile Include="Model\TestModel.cs" /> <Compile Include="Properties\Annotations.cs" /> <Compile Include="Properties\Version.cs"> <DependentUpon>Version.tt</DependentUpon> @@ -79,13 +78,17 @@ <Compile Include="ViewModel\RelayCommand.cs" /> <Compile Include="ViewModel\HashComponentDataViewModel.cs" /> <Compile Include="ViewModel\VerifyInputDataViewModel.cs" /> - <Compile Include="ViewModel\XMLValidator.cs" /> + <Compile Include="ViewModel\UserControl\XMLFile.cs" /> + <Compile Include="Util\XMLValidator.cs" /> <Compile Include="Views\HashComponentData.xaml.cs"> <DependentUpon>HashComponentData.xaml</DependentUpon> </Compile> <Compile Include="Views\HomeView.xaml.cs"> <DependentUpon>HomeView.xaml</DependentUpon> </Compile> + <Compile Include="Views\UserControl\VectoXMLFileSelector.xaml.cs"> + <DependentUpon>VectoXMLFileSelector.xaml</DependentUpon> + </Compile> <Compile Include="Views\VerifyInputData.xaml.cs"> <DependentUpon>VerifyInputData.xaml</DependentUpon> </Compile> @@ -101,6 +104,26 @@ <DependentUpon>MainWindow.xaml</DependentUpon> <SubType>Code</SubType> </Compile> + <Page Include="Resources\Icon_NOK.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Icon_OK.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Icon_XML_NOK.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Icon_XML_OK.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> + <Page Include="Resources\Icon_XML_unknown.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\HashComponentData.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> @@ -109,6 +132,10 @@ <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> </Page> + <Page Include="Views\UserControl\VectoXMLFileSelector.xaml"> + <SubType>Designer</SubType> + <Generator>MSBuild:Compile</Generator> + </Page> <Page Include="Views\VerifyInputData.xaml"> <SubType>Designer</SubType> <Generator>MSBuild:Compile</Generator> diff --git a/HashingTool/Helper/CollectionConverter.cs b/HashingTool/Helper/CollectionConverter.cs new file mode 100644 index 0000000000000000000000000000000000000000..78f1fd749cc344e51337c5347dc8b32beb7cad67 --- /dev/null +++ b/HashingTool/Helper/CollectionConverter.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections; +using System.Globalization; +using System.Linq; +using System.Windows.Data; + +namespace HashingTool.Helper +{ + public class CollectionConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + var val = value as ICollection; + if (val == null) { + throw new ArgumentException("can only convert collections!"); + } + if (targetType == typeof(object) || targetType == typeof(string)) { + var tmp = new string[val.Count]; + var i = 0; + foreach (var entry in val) { + tmp[i++] = entry.ToString(); + } + return string.Join(", ", tmp); + } + throw new ArgumentException("Unhandled target type"); + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/HashingTool/Helper/IOService.cs b/HashingTool/Helper/IOService.cs new file mode 100644 index 0000000000000000000000000000000000000000..b6880184f26aec06c6e66950c0ba45efe4aeabfc --- /dev/null +++ b/HashingTool/Helper/IOService.cs @@ -0,0 +1,45 @@ +using System.IO; +using Microsoft.Win32; + +namespace HashingTool.Helper +{ + public interface IOService + { + Stream OpenFileDialog(string defaultPath, string defaultExt, string filter, out string location); + + Stream SaveData(string defaultPath, string defaultExt, string filter, out string location); + } + + public class WPFIoService : IOService + { + public Stream OpenFileDialog(string defaultPath, string defaultExt, string filter, out string location) + { + var dlg = new OpenFileDialog { + DefaultExt = defaultExt, + Filter = filter + }; + var result = dlg.ShowDialog(); + if (result != true) { + location = null; + return null; + } + location = dlg.FileName; + return File.OpenRead(dlg.FileName); + } + + public Stream SaveData(string defaultPath, string defaultExt, string filter, out string location) + { + var dlg = new SaveFileDialog() { + DefaultExt = defaultExt, + Filter = filter + }; + var result = dlg.ShowDialog(); + if (result != true) { + location = null; + return null; + } + location = dlg.FileName; + return new FileStream(dlg.FileName, FileMode.Create); + } + } +} diff --git a/HashingTool/Resources/Icon_NOK.xaml b/HashingTool/Resources/Icon_NOK.xaml new file mode 100644 index 0000000000000000000000000000000000000000..f9774db2bf9d348ecbf140f6f660bb680ce6b2b1 --- /dev/null +++ b/HashingTool/Resources/Icon_NOK.xaml @@ -0,0 +1,14 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <Canvas x:Key="Icon_NOK" Name="layer1"> + <Canvas.RenderTransform> + <TranslateTransform X="-66.503906" Y="-580.23275" /> + </Canvas.RenderTransform> + <Canvas Name="flowRoot4806" Opacity="1"> + <Path Name="path4841" Fill="#FFEB0000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 87.37793 608.62141 -1.098633 1.40625 q -8.217774 10.76661 -12.788086 10.76661 -3.427734 0 -6.987305 -5.625 1.230469 0.26367 1.889649 0.26367 5.756836 0 13.095703 -9.44824 l 1.713867 -2.15332 -1.230469 -1.49415 q -8.876953 -10.32714 -8.876953 -14.50195 0 -2.98828 4.833984 -7.60254 2.021485 9.05274 8.4375 17.09473 l 0.966797 1.23047 1.845703 -2.24121 q 9.052735 -11.20606 14.414063 -11.20606 2.63672 0 4.35059 2.59278 0.30761 0.43945 0.8789 1.23046 -6.81152 3.07618 -15.249021 12.43653 l -1.801758 2.02148 1.318359 1.4502 q 7.99805 8.78906 14.76563 8.78906 1.97753 0 3.6914 -0.43945 -2.19726 4.57031 -3.6914 5.97656 -1.4502 1.40625 -3.99903 1.40625 -5.537108 0 -14.414061 -9.71191 l -2.065429 -2.24122 z" /> + </Canvas> + + </Canvas> +</ResourceDictionary> \ No newline at end of file diff --git a/HashingTool/Resources/Icon_OK.xaml b/HashingTool/Resources/Icon_OK.xaml new file mode 100644 index 0000000000000000000000000000000000000000..731e0a8151c14b0a6b21671914b77d4b2f21bf89 --- /dev/null +++ b/HashingTool/Resources/Icon_OK.xaml @@ -0,0 +1,17 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <Canvas x:Key="Icon_OK" Name="layer1"> + <Canvas.RenderTransform> + <TranslateTransform X="-55.706613" Y="-712.36918" /> + </Canvas.RenderTransform> + + <Canvas Name="flowRoot48069" Opacity="1"> + <Canvas.RenderTransform> + <TranslateTransform X="-5.7972934" Y="86.067101" /> + </Canvas.RenderTransform> + <Path Name="path4844" Fill="#FF00A500" StrokeThickness="1" + StrokeLineJoin="Miter" StrokeStartLineCap="Flat" StrokeEndLineCap="Flat" + Data="m 119.33594 626.30208 1.31836 2.28515 q -12.87598 9.09668 -23.862308 23.02735 -10.986328 13.93066 -15.864258 27.29004 l -1.933593 1.27441 q -2.504883 1.62598 -4.306641 3.25195 -0.307617 -1.58203 -1.713867 -5.09765 l -1.010742 -2.50488 q -3.295899 -8.12989 -5.581055 -11.33789 -2.241211 -3.25196 -4.87793 -3.51563 3.559571 -3.25195 6.196289 -3.25195 3.647461 0 7.998047 9.7998 l 1.582031 3.51563 q 7.778321 -13.93067 18.764649 -25.66407 11.030278 -11.73339 23.291018 -19.07226 z" /> + </Canvas> + </Canvas> +</ResourceDictionary> \ No newline at end of file diff --git a/HashingTool/Resources/Icon_XML_NOK.xaml b/HashingTool/Resources/Icon_XML_NOK.xaml new file mode 100644 index 0000000000000000000000000000000000000000..ae1f9ee1e764e5690f908630c1eb32e4d44e0112 --- /dev/null +++ b/HashingTool/Resources/Icon_XML_NOK.xaml @@ -0,0 +1,20 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + <Canvas x:Key="Icon_XML_NOK"> + <Canvas.RenderTransform> + <TranslateTransform X="-59.285156" Y="-215.2361" /> + </Canvas.RenderTransform> + <Canvas Name="flowRoot4136" Opacity="1"> + <Path Name="path4145" Fill="#FFFF0000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 59.285156 243.86892 9.785156 -14.94141 -8.867187 -13.69141 6.757812 0 5.742188 9.19922 5.625 -9.19922 6.699219 0 -8.90625 13.90625 9.785156 14.72657 -6.972656 0 -6.347657 -9.90235 -6.367187 9.90235 -6.933594 0 z" /> + <Path Name="path4147" Fill="#FFFF0000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 88.835937 243.86892 0 -28.63282 8.652344 0 5.195309 19.53125 5.13672 -19.53125 8.67188 0 0 28.63282 -5.3711 0 0 -22.53907 -5.68359 22.53907 -5.566406 0 -5.664063 -22.53907 0 22.53907 -5.371094 0 z" /> + <Path Name="path4149" Fill="#FFFF0000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 122.42969 243.86892 0 -28.39844 5.78125 0 0 23.57422 14.375 0 0 4.82422 -20.15625 0 z" /> + </Canvas> + </Canvas> +</ResourceDictionary> \ No newline at end of file diff --git a/HashingTool/Resources/Icon_XML_OK.xaml b/HashingTool/Resources/Icon_XML_OK.xaml new file mode 100644 index 0000000000000000000000000000000000000000..c863cfa188d1904dd95881654014b8e9418b0697 --- /dev/null +++ b/HashingTool/Resources/Icon_XML_OK.xaml @@ -0,0 +1,20 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + + <Canvas x:Key="Icon_XML_OK"> + <Canvas.RenderTransform> + <TranslateTransform X="-59.285156" Y="-215.2361" /> + </Canvas.RenderTransform> + <Canvas Name="flowRoot4136" Opacity="1"> + <Path Name="path4145" Fill="#FF00C000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 59.285156 243.86892 9.785156 -14.94141 -8.867187 -13.69141 6.757812 0 5.742188 9.19922 5.625 -9.19922 6.699219 0 -8.90625 13.90625 9.785156 14.72657 -6.972656 0 -6.347657 -9.90235 -6.367187 9.90235 -6.933594 0 z" /> + <Path Name="path4147" Fill="#FF00C000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 88.835937 243.86892 0 -28.63282 8.652344 0 5.195309 19.53125 5.13672 -19.53125 8.67188 0 0 28.63282 -5.3711 0 0 -22.53907 -5.68359 22.53907 -5.566406 0 -5.664063 -22.53907 0 22.53907 -5.371094 0 z" /> + <Path Name="path4149" Fill="#FF00C000" StrokeThickness="1" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 122.42969 243.86892 0 -28.39844 5.78125 0 0 23.57422 14.375 0 0 4.82422 -20.15625 0 z" /> + </Canvas> + </Canvas> +</ResourceDictionary> \ No newline at end of file diff --git a/HashingTool/Resources/Icon_XML_unknown.xaml b/HashingTool/Resources/Icon_XML_unknown.xaml new file mode 100644 index 0000000000000000000000000000000000000000..92d81c29df32d7224872ff4d6a4aa15045a2893a --- /dev/null +++ b/HashingTool/Resources/Icon_XML_unknown.xaml @@ -0,0 +1,19 @@ +<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> + <Canvas x:Key="ICON_XML_unknown" Name="layer1"> + <Canvas.RenderTransform> + <TranslateTransform X="-59.285156" Y="-215.2361" /> + </Canvas.RenderTransform> + <Canvas Name="flowRoot4136" Opacity="1"> + <Path Name="path4145" StrokeThickness="1" Stroke="#FF464646" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 59.285156 243.86892 9.785156 -14.94141 -8.867187 -13.69141 6.757812 0 5.742188 9.19922 5.625 -9.19922 6.699219 0 -8.90625 13.90625 9.785156 14.72657 -6.972656 0 -6.347657 -9.90235 -6.367187 9.90235 -6.933594 0 z" /> + <Path Name="path4147" StrokeThickness="1" Stroke="#FF464646" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 88.835937 243.86892 0 -28.63282 8.652344 0 5.195309 19.53125 5.13672 -19.53125 8.67188 0 0 28.63282 -5.3711 0 0 -22.53907 -5.68359 22.53907 -5.566406 0 -5.664063 -22.53907 0 22.53907 -5.371094 0 z" /> + <Path Name="path4149" StrokeThickness="1" Stroke="#FF464646" StrokeLineJoin="Miter" StrokeStartLineCap="Flat" + StrokeEndLineCap="Flat" + Data="m 122.42969 243.86892 0 -28.39844 5.78125 0 0 23.57422 14.375 0 0 4.82422 -20.15625 0 z" /> + </Canvas> + </Canvas> +</ResourceDictionary> \ No newline at end of file diff --git a/HashingTool/Util/XMLValidator.cs b/HashingTool/Util/XMLValidator.cs new file mode 100644 index 0000000000000000000000000000000000000000..da85aa7d5deebab48a08dd423f797de7dc96efa0 --- /dev/null +++ b/HashingTool/Util/XMLValidator.cs @@ -0,0 +1,75 @@ +using System; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Schema; +using TUGraz.VectoCore.Utils; + +namespace HashingTool.Util +{ + public class XMLValidator + { + private readonly Action<XmlSeverityType, ValidationEvent> _validationErrorAction; + private readonly Action<bool> _resultAction; + private bool _valid; + + public XMLValidator(Action<bool> resultaction, Action<XmlSeverityType, ValidationEvent> validationErrorAction) + { + _validationErrorAction = validationErrorAction ?? ((x, y) => { }); + _resultAction = resultaction ?? (x => { }); + _valid = false; + } + + public Task<bool> ValidateXML(XmlReader hashedComponent) + { + var task = new Task<bool>(() => DoValidation(hashedComponent)); + task.Start(); + return task; + } + + private bool DoValidation(XmlReader hashedComponent) + { + _valid = true; + try { + var settings = new XmlReaderSettings { + ValidationType = ValidationType.Schema, + ValidationFlags = //XmlSchemaValidationFlags.ProcessInlineSchema | + //XmlSchemaValidationFlags.ProcessSchemaLocation | + XmlSchemaValidationFlags.ReportValidationWarnings + }; + settings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); + settings.Schemas.Add(GetXMLSchema("")); + + var vreader = XmlReader.Create(hashedComponent, settings); + var doc = new XmlDocument(); + doc.Load(vreader); + doc.Validate(ValidationCallBack); + } catch (Exception e) { + _validationErrorAction(XmlSeverityType.Error, new ValidationEvent() { Exception = e }); + } + return _valid; + } + + private void ValidationCallBack(object sender, ValidationEventArgs args) + { + _resultAction(false); + _valid = false; + _validationErrorAction(args.Severity, new ValidationEvent { ValidationEventArgs = args }); + } + + private static XmlSchemaSet GetXMLSchema(string version) + { + var resource = RessourceHelper.LoadResourceAsStream(RessourceHelper.ResourceType.XMLSchema, "VectoComponent.xsd"); + var xset = new XmlSchemaSet() { XmlResolver = new XmlResourceResolver() }; + var reader = XmlReader.Create(resource, new XmlReaderSettings(), "schema://"); + xset.Add(XmlSchema.Read(reader, null)); + xset.Compile(); + return xset; + } + } + + public class ValidationEvent + { + public Exception Exception; + public ValidationEventArgs ValidationEventArgs; + } +} diff --git a/HashingTool/ViewModel/HashComponentDataViewModel.cs b/HashingTool/ViewModel/HashComponentDataViewModel.cs index 0b84ba4644ab92ebc87f68d6a78615ddecff1016..da4ea95c71ecb2dd4b6515c56208b78d312cd80d 100644 --- a/HashingTool/ViewModel/HashComponentDataViewModel.cs +++ b/HashingTool/ViewModel/HashComponentDataViewModel.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.IO; using System.Text; using System.Threading.Tasks; @@ -10,6 +11,8 @@ using System.Xml; using System.Xml.Linq; using System.Xml.Schema; using HashingTool.Helper; +using HashingTool.Util; +using HashingTool.ViewModel.UserControl; using TUGraz.VectoCore.Utils; using TUGraz.VectoHashing; @@ -18,23 +21,36 @@ namespace HashingTool.ViewModel public class HashComponentDataViewModel : ObservableObject, IMainView { private readonly ApplicationViewModel _applicationViewModel; - private bool? _componentDataValid; private string _digestValue; - //private ObservableCollection<string> _xmlValidationErrors = new ObservableCollection<string>(); - private Stream _stream; + private XDocument _result; - private IOService _ioService = new WPFIoService(); - private RelayCommand _saveCommand; + private readonly IOService _ioService = new WPFIoService(); + private readonly RelayCommand _saveCommand; private bool _busy; - private string _source; + private XMLFile _sourceFile; + private bool? _componentDataValid; public HashComponentDataViewModel() { XMLValidationErrors = new ObservableCollection<string>(); + _sourceFile = new XMLFile(_ioService, false); + _sourceFile.PropertyChanged += SourceChanged; _saveCommand = new RelayCommand(SaveDocument, () => !_busy && ComponentDataValid != null && ComponentDataValid.Value && _result != null); _busy = false; + + CanonicalizaitionMethods = new ObservableCollection<string>() { + "urn:vecto:xml:2017:canonicalization", + "http://www.w3.org/2001/10/xml-exc-c14n#" + }; + } + + private void SourceChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "Document") { + DoComputeHash(); + } } public HashComponentDataViewModel(ApplicationViewModel applicationViewModel) : this() @@ -52,38 +68,15 @@ namespace HashingTool.ViewModel get { return ApplicationViewModel.HomeView; } } - public string Source + public XMLFile ComponentFile { - get { return _source; } - private set { - if (_source == value) { - return; - } - _source = value; - RaisePropertyChanged("Source"); - } + get { return _sourceFile; } + private set { _sourceFile = value; } } - public bool? ComponentDataValid - { - get { return _componentDataValid; } - private set { - if (_componentDataValid == value) { - return; - } - _componentDataValid = value; - RaisePropertyChanged("ComponentDataValid"); - } - } public ObservableCollection<string> XMLValidationErrors { get; set; } - //{ - // get { return _xmlValidationErrors; } - // private set { - // _xmlValidationErrors = value; - // RaisePropertyChanged("XMLValidationErrors"); - // } - //} + public string DigestValue { @@ -97,11 +90,6 @@ namespace HashingTool.ViewModel } } - public ICommand SetComponentData - { - get { return new RelayCommand(HashComponentData, () => !_busy); } - } - public ICommand SaveHashedDocument { get { return _saveCommand; } @@ -124,28 +112,29 @@ namespace HashingTool.ViewModel } } - private void HashComponentData() + public bool? ComponentDataValid { - string filename; - - var xml = _ioService.OpenFileDialog(null, ".xml", "VECTO XML file|*.xml", out filename); - if (xml == null) { - return; + get { return _componentDataValid; } + private set { + if (_componentDataValid == value) { + return; + } + _componentDataValid = value; + RaisePropertyChanged("ComponentDataValid"); } - - _busy = true; - ComponentDataValid = null; - XMLValidationErrors.Clear(); - DigestValue = ""; - Source = filename; - _stream = xml; - DoComputeHash(); } + public ObservableCollection<string> CanonicalizaitionMethods { get; private set; } + private async void DoComputeHash() { try { - var h = VectoHash.Load(_stream); + _busy = true; + ComponentDataValid = false; + DigestValue = ""; + XMLValidationErrors.Clear(); + + var h = VectoHash.Load(_sourceFile.Document); _result = h.AddHash(); @@ -167,7 +156,7 @@ namespace HashingTool.ViewModel : e.ValidationEventArgs.Message, e.ValidationEventArgs == null ? 0 : e.ValidationEventArgs.Exception.LineNumber))); }); - await validator.ValidateXML(ms); + await validator.ValidateXML(XmlReader.Create(ms)); } if (ComponentDataValid != null && ComponentDataValid.Value) { DigestValue = h.ComputeHash(); diff --git a/HashingTool/ViewModel/UserControl/XMLFile.cs b/HashingTool/ViewModel/UserControl/XMLFile.cs new file mode 100644 index 0000000000000000000000000000000000000000..d8dbc70fc9d55982642c6b536c5028e9a89f1a41 --- /dev/null +++ b/HashingTool/ViewModel/UserControl/XMLFile.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.ObjectModel; +using System.Windows; +using System.Windows.Input; +using System.Xml; +using System.Xml.Schema; +using HashingTool.Helper; +using HashingTool.Util; + +namespace HashingTool.ViewModel.UserControl +{ + public class XMLFile : ObservableObject + { + private string _source; + private bool? _isValid; + + private bool _busy; + + private readonly IOService _ioService; + private readonly bool _validate; + private XmlDocument _document; + + public XMLFile(IOService ioservice, bool validate = false) + { + _ioService = ioservice; + _validate = validate; + XMLValidationErrors = new ObservableCollection<string>(); + Source = ""; + RaisePropertyChanged("ValidateInput"); + } + + public XmlDocument Document + { + get { return _document; } + private set { + if (_document == value) { + return; + } + _document = value; + RaisePropertyChanged("Document"); + } + } + + public string Source + { + get { return _source; } + private set { + if (_source == value) { + return; + } + _source = value; + RaisePropertyChanged("Source"); + } + } + + public bool ValidateInput + { + get { return _validate; } + } + + public bool? IsValid + { + get { return _isValid; } + private set { + if (_isValid == value) { + return; + } + _isValid = value; + RaisePropertyChanged("IsValid"); + } + } + + public ObservableCollection<string> XMLValidationErrors { get; set; } + + public ICommand BrowseFileCommand + { + get { return new RelayCommand(ReadXMLFile, () => !_busy); } + } + + + private void ReadXMLFile() + { + string filename; + + var stream = _ioService.OpenFileDialog(null, ".xml", "VECTO XML file|*.xml", out filename); + if (stream == null) { + return; + } + + _busy = true; + IsValid = null; + XMLValidationErrors.Clear(); + Source = filename; + var reader = XmlReader.Create(stream); + var document = new XmlDocument(); + document.Load(reader); + if (_validate) { + Validate(reader); + } + Document = document; + _busy = false; + } + + private async void Validate(XmlReader xml) + { + try { + IsValid = true; + var validator = new XMLValidator(r => { IsValid = r; }, + (s, e) => { + Application.Current.Dispatcher.Invoke(() => XMLValidationErrors.Add( + string.Format("Validation {0} Line {2}: {1}", s == XmlSeverityType.Warning ? "WARNING" : "ERROR", + e.ValidationEventArgs == null + ? e.Exception.Message + + (e.Exception.InnerException != null ? Environment.NewLine + e.Exception.InnerException.Message : "") + : e.ValidationEventArgs.Message, + e.ValidationEventArgs == null ? 0 : e.ValidationEventArgs.Exception.LineNumber))); + }); + await validator.ValidateXML(xml); + } catch (Exception e) { + IsValid = false; + XMLValidationErrors.Add(e.Message); + } + } + } +} diff --git a/HashingTool/Views/HashComponentData.xaml b/HashingTool/Views/HashComponentData.xaml index 52cfc9a696c24de92c4af39fb03eedafb310b3f6..589cdfe43f434c0645fa794eac0e3322f6b68e9b 100644 --- a/HashingTool/Views/HashComponentData.xaml +++ b/HashingTool/Views/HashComponentData.xaml @@ -4,30 +4,94 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:ViewModel="clr-namespace:HashingTool.ViewModel" xmlns:Helper="clr-namespace:HashingTool.Helper" + xmlns:local="clr-namespace:HashingTool.Views" x:Class="HashingTool.Views.HashComponentData" mc:Ignorable="d" - d:DesignHeight="501.425" d:DesignWidth="548"> + d:DesignHeight="603.125" d:DesignWidth="666"> <UserControl.Resources> - <Helper:BoolViewConverter x:Key="BoolViewConverter" /> + <Helper:CollectionConverter x:Key="CollectionConverter" /> </UserControl.Resources> + <UserControl.DataContext> <ViewModel:HashComponentDataViewModel /> </UserControl.DataContext> <Grid> - <Label HorizontalAlignment="Center" Margin="10,10,0,0" VerticalAlignment="Top" + <Label Name="lblHeader" HorizontalAlignment="Center" Margin="10,10,0,0" VerticalAlignment="Top" Content="{Binding Name}" FontWeight="Bold" FontSize="18" /> - <Button Content="Back" Command="{Binding ShowHomeViewCommand}" Margin="0,0,10,10" HorizontalAlignment="Right" + <Button Name="btnBack" Content="Back" Command="{Binding ShowHomeViewCommand}" Margin="0,0,10,10" + HorizontalAlignment="Right" Width="75" Height="22" VerticalAlignment="Bottom" /> - <Button x:Name="btSelectComponentFile" Content="Browse ..." HorizontalAlignment="Left" Margin="300,79,0,0" - VerticalAlignment="Top" Width="75" Command="{Binding SetComponentData, Mode=OneWay}" /> - <TextBox x:Name="tbComponentFile" HorizontalAlignment="Left" Height="23" Margin="10,79,0,0" TextWrapping="Wrap" - VerticalAlignment="Top" Width="285" IsReadOnly="True" Text="{Binding Source, Mode=OneWay}" /> - <Label Content="{Binding ComponentDataValid, Converter={StaticResource BoolViewConverter}, Mode=OneWay}" - HorizontalAlignment="Left" Margin="10,141,0,0" VerticalAlignment="Top" Height="26" Width="154" /> - <Label Content="{Binding DigestValue}" HorizontalAlignment="Left" Margin="10,172,0,0" VerticalAlignment="Top" /> - <Button Content="Save" HorizontalAlignment="Right" Margin="0,0,90,10" Width="75" Height="22" + <Button Content="Save Component Data" HorizontalAlignment="Right" Margin="0,0,90,10" Width="143" Height="22" VerticalAlignment="Bottom" Command="{Binding SaveHashedDocument, Mode=OneWay}" /> - <ListBox HorizontalAlignment="Left" Height="214" Margin="71,230,0,0" VerticalAlignment="Top" Width="436" IsSynchronizedWithCurrentItem="False" ItemsSource="{Binding XMLValidationErrors}"/> + + <local:VectoXMLFileSelector Margin="0,93,0,0" VerticalAlignment="Top" XMLFile="{Binding ComponentFile}" /> + + <Grid Height="425" VerticalAlignment="Top" Margin="15,141,5,0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Expander Grid.Row="0"> + <Expander.Style> + <Style TargetType="Expander"> + <Setter Property="IsEnabled" Value="True" /> + <Setter Property="Foreground" Value="Red" /> + <Style.Triggers> + <DataTrigger Binding="{Binding XMLValidationErrors.Count}" Value="0"> + <Setter Property="IsExpanded" Value="False" /> + <Setter Property="IsEnabled" Value="False" /> + <Setter Property="Foreground" Value="Black" /> + </DataTrigger> + </Style.Triggers> + </Style> + </Expander.Style> + <Expander.Header> + <TextBlock Text="{Binding XMLValidationErrors.Count, StringFormat='{}{0} Warnings/Errors'}" /> + </Expander.Header> + + <Grid Background="#FFE5E5E5" Margin="10,0,8,0"> + <ListBox Height="185" VerticalAlignment="Top" IsSynchronizedWithCurrentItem="False" + ItemsSource="{Binding XMLValidationErrors}" /> + </Grid> + + </Expander> + <Grid Grid.Row="1" Margin="0,10,0,0"> + <Label x:Name="lblDigestValue" Content="Digest Value:" HorizontalAlignment="Left" Margin="10,38,0,0" + VerticalAlignment="Top" RenderTransformOrigin="0.57,0.5" FontSize="16" /> + <TextBox x:Name="tbDigestValue" Text="{Binding DigestValue}" HorizontalAlignment="Left" Margin="117,41,0,0" + VerticalAlignment="Top" RenderTransformOrigin="4.1,-2.1" Width="454" FontFamily="Courier New" FontWeight="Bold" + FontSize="16" Foreground="#FF03932B" /> + <Label Name="lblC14N" Content="Canonicalization:" HorizontalAlignment="Left" Margin="10,10,0,0" + VerticalAlignment="Top" /> + <Label Name="lblC14NList" + Content="{Binding CanonicalizaitionMethods, Converter={StaticResource CollectionConverter}}" + HorizontalAlignment="Left" Margin="117,10,0,0" VerticalAlignment="Top" + Width="454" /> + </Grid> + <Grid Grid.Row="2" Margin="0,10,0,0"> + <ContentControl HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Width="66" Height="64"> + <ContentControl.RenderTransform> + <ScaleTransform ScaleX="1.5" ScaleY="1.5" /> + </ContentControl.RenderTransform> + <ContentControl.Style> + <Style TargetType="ContentControl"> + <Setter Property="Content" Value="" /> + <Style.Triggers> + <DataTrigger Binding="{Binding ComponentDataValid}" Value="True"> + <Setter Property="Content" Value="{StaticResource Icon_OK}" /> + </DataTrigger> + <DataTrigger Binding="{Binding ComponentDataValid}" Value="False"> + <Setter Property="Content" Value="{StaticResource Icon_NOK}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </ContentControl.Style> + </ContentControl> + + </Grid> + </Grid> + <Label x:Name="lblFileSelect" Content="Component data:" HorizontalAlignment="Left" Margin="10,75,0,0" VerticalAlignment="Top"/> </Grid> </UserControl> \ No newline at end of file diff --git a/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml new file mode 100644 index 0000000000000000000000000000000000000000..e216cb6acfed54b347846f9c140d2b87a16e7cc9 --- /dev/null +++ b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml @@ -0,0 +1,37 @@ +<UserControl + 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:views="clr-namespace:HashingTool.Views" + x:Class="HashingTool.Views.VectoXMLFileSelector" + mc:Ignorable="d" d:DesignWidth="456" MinHeight="43" + d:DataContext="{d:DesignInstance views:VectoXMLFileSelector}" Height="34"> + <UserControl.Resources> + <BooleanToVisibilityConverter x:Key="BoolToVis" /> + </UserControl.Resources> + <Grid> + <TextBox Height="23" Margin="10,10,140,0" TextWrapping="Wrap" Text="{Binding XMLFile.Source}" VerticalAlignment="Top" /> + <Button Content="Browse ..." Command="{Binding XMLFile.BrowseFileCommand, Mode=OneWay}" Margin="0,10,10,0" + VerticalAlignment="Top" HorizontalAlignment="Right" Width="75" /> + <ContentControl Visibility="{Binding XMLFile.ValidateInput, Converter={StaticResource BoolToVis}}" Height="33" + Margin="0,14,40,-4" VerticalAlignment="Top" HorizontalAlignment="Right" Width="93"> + <ContentControl.RenderTransform> + <ScaleTransform ScaleX="0.5" ScaleY="0.5" /> + </ContentControl.RenderTransform> + <ContentControl.Style> + <Style TargetType="ContentControl"> + <Setter Property="Content" Value="{StaticResource ICON_XML_unknown}" /> + <Style.Triggers> + <DataTrigger Binding="{Binding XMLFile.IsValid}" Value="True"> + <Setter Property="Content" Value="{StaticResource Icon_XML_OK}" /> + </DataTrigger> + <DataTrigger Binding="{Binding XMLFile.IsValid}" Value="False"> + <Setter Property="Content" Value="{StaticResource Icon_XML_NOK}" /> + </DataTrigger> + </Style.Triggers> + </Style> + </ContentControl.Style> + </ContentControl> + </Grid> +</UserControl> \ No newline at end of file diff --git a/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs new file mode 100644 index 0000000000000000000000000000000000000000..887cb6c676a91a41e563ad5e71c31e664fac8dfa --- /dev/null +++ b/HashingTool/Views/UserControl/VectoXMLFileSelector.xaml.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using HashingTool.ViewModel; +using HashingTool.ViewModel.UserControl; + +namespace HashingTool.Views +{ + /// <summary> + /// Interaction logic for VectoXMLFileSelector.xaml + /// </summary> + public partial class VectoXMLFileSelector : UserControl + { + public static readonly DependencyProperty XMLFileProperty = DependencyProperty.Register("XMLFile", typeof(XMLFile), + typeof(VectoXMLFileSelector)); + + + public VectoXMLFileSelector() + { + InitializeComponent(); + (Content as FrameworkElement).DataContext = this; + } + + public XMLFile XMLFile + { + get { return (XMLFile)GetValue(XMLFileProperty); } + set { SetValue(XMLFileProperty, value); } + } + } +} diff --git a/VectoCommon/VectoHashing/Impl/XmlDsigVectoTransform.cs b/VectoCommon/VectoHashing/Impl/XmlDsigVectoTransform.cs index 685ec972e043705469e0ba444555437d21c9be81..e2b8f300d1cc52d20c52b82a8d41ddaa2b6fe5e7 100644 --- a/VectoCommon/VectoHashing/Impl/XmlDsigVectoTransform.cs +++ b/VectoCommon/VectoHashing/Impl/XmlDsigVectoTransform.cs @@ -29,74 +29,74 @@ * Martin Rexeis, rexeis@ivt.tugraz.at, IVT, Graz University of Technology */ -using System; -using System.IO; -using System.Reflection; -using System.Security.Cryptography.Xml; -using System.Text; -using System.Xml; - -namespace TUGraz.VectoHashing -{ - public class XmlDsigVectoTransform : Transform - { - //private static readonly Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) }; - //private static readonly Type[] _outputTypes = { typeof(Stream) }; - //private XmlDocument _doc = new XmlDocument(); - - private XmlDsigXsltTransform _transform; - - public XmlDsigVectoTransform() - { - Algorithm = "urn:vecto:xml:2017:canonicalization"; - _transform = new XmlDsigXsltTransform(); - - XmlDocument doc = new XmlDocument(); - doc.Load(ReadStream("TUGraz.VectoHashing.Resources.XSLT.SortInputData.xslt")); - - _transform.LoadInnerXml(doc.ChildNodes); - } - - public override void LoadInnerXml(XmlNodeList nodeList) {} - - protected override XmlNodeList GetInnerXml() - { - return null; - } - - public override void LoadInput(object obj) - { - _transform.LoadInput(obj); - } - - public override object GetOutput() - { - return _transform.GetOutput(); - } - - public override object GetOutput(Type type) - { - return _transform.GetOutput(type); - } - - public override Type[] InputTypes - { - get { return _transform.InputTypes; } - } - - public override Type[] OutputTypes - { - get { return _transform.OutputTypes; } - } - - private static Stream ReadStream(string resourceName) - { - var assembly = Assembly.GetExecutingAssembly(); - var resource = assembly.GetManifestResourceStream(resourceName); - if (resource == null) { - throw new Exception("Resource file not found: " + resourceName); - } - return resource; - } - } -} \ No newline at end of file +using System; +using System.IO; +using System.Reflection; +using System.Security.Cryptography.Xml; +using System.Text; +using System.Xml; + +namespace TUGraz.VectoHashing +{ + public class XmlDsigVectoTransform : Transform + { + //private static readonly Type[] _inputTypes = { typeof(Stream), typeof(XmlDocument), typeof(XmlNodeList) }; + //private static readonly Type[] _outputTypes = { typeof(Stream) }; + //private XmlDocument _doc = new XmlDocument(); + + private XmlDsigXsltTransform _transform; + + public XmlDsigVectoTransform() + { + Algorithm = "urn:vecto:xml:2017:canonicalization"; + _transform = new XmlDsigXsltTransform(); + + XmlDocument doc = new XmlDocument(); + doc.Load(ReadStream("TUGraz.VectoHashing.Resources.XSLT.SortInputData.xslt")); + + _transform.LoadInnerXml(doc.ChildNodes); + } + + public override void LoadInnerXml(XmlNodeList nodeList) {} + + protected override XmlNodeList GetInnerXml() + { + return null; + } + + public override void LoadInput(object obj) + { + _transform.LoadInput(obj); + } + + public override object GetOutput() + { + return _transform.GetOutput(); + } + + public override object GetOutput(Type type) + { + return _transform.GetOutput(type); + } + + public override Type[] InputTypes + { + get { return _transform.InputTypes; } + } + + public override Type[] OutputTypes + { + get { return _transform.OutputTypes; } + } + + private static Stream ReadStream(string resourceName) + { + var assembly = Assembly.GetExecutingAssembly(); + var resource = assembly.GetManifestResourceStream(resourceName); + if (resource == null) { + throw new Exception("Resource file not found: " + resourceName); + } + return resource; + } + } +}