diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c4efe2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,261 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +project.fragment.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +#*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc \ No newline at end of file diff --git a/Asn1Editor.sln b/Asn1Editor.sln new file mode 100644 index 0000000..38e04e7 --- /dev/null +++ b/Asn1Editor.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2037 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Asn1Editor", "Asn1Editor\Asn1Editor.csproj", "{6338C8ED-B646-470E-8A68-7ED4B05AC02E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|x64.ActiveCfg = Debug|x64 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|x64.Build.0 = Debug|x64 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|x86.ActiveCfg = Debug|x86 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Debug|x86.Build.0 = Debug|x86 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|Any CPU.Build.0 = Release|Any CPU + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|x64.ActiveCfg = Release|x64 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|x64.Build.0 = Release|x64 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|x86.ActiveCfg = Release|x86 + {6338C8ED-B646-470E-8A68-7ED4B05AC02E}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {86EC486C-57EE-4B5C-ABF2-48F4486D1B63} + EndGlobalSection +EndGlobal diff --git a/Asn1Editor/API/Converters/TextBlockTrimConverter.cs b/Asn1Editor/API/Converters/TextBlockTrimConverter.cs new file mode 100644 index 0000000..dca92f1 --- /dev/null +++ b/Asn1Editor/API/Converters/TextBlockTrimConverter.cs @@ -0,0 +1,21 @@ +using System; +using System.Globalization; +using System.Windows.Data; +using Asn1Editor.Properties; + +namespace Asn1Editor.API.Converters { + class TextBlockTrimConverter : IValueConverter { + public Object Convert(Object value, Type targetType, Object parameter, CultureInfo culture) { + if (value == null) { return String.Empty; } + String retValue = value.ToString(); + if (retValue.Length > Settings.Default.MaxTreeViewLength) { + retValue = retValue.Substring(0, Settings.Default.MaxTreeViewLength) + "..."; + } + return retValue; + + } + public Object ConvertBack(Object value, Type targetType, Object parameter, CultureInfo culture) { + return null; + } + } +} diff --git a/Asn1Editor/API/Converters/TreeViewLineConverter.cs b/Asn1Editor/API/Converters/TreeViewLineConverter.cs new file mode 100644 index 0000000..32823c2 --- /dev/null +++ b/Asn1Editor/API/Converters/TreeViewLineConverter.cs @@ -0,0 +1,17 @@ +using System; +using System.Windows.Controls; +using System.Windows.Data; + +namespace Asn1Editor.API.Converters { + class TreeViewLineConverter : IValueConverter { + public Object Convert(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture) { + TreeViewItem item = (TreeViewItem)value; + ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item); + return ic.ItemContainerGenerator.IndexFromContainer(item) == ic.Items.Count - 1; + } + + public Object ConvertBack(Object value, Type targetType, Object parameter, System.Globalization.CultureInfo culture) { + return false; + } + } +} diff --git a/Asn1Editor/API/Generic/IObservableList.cs b/Asn1Editor/API/Generic/IObservableList.cs new file mode 100644 index 0000000..126ea14 --- /dev/null +++ b/Asn1Editor/API/Generic/IObservableList.cs @@ -0,0 +1,7 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; + +namespace Asn1Editor.API.Generic { + public interface IObservableList : IList, INotifyCollectionChanged, INotifyPropertyChanged { } +} \ No newline at end of file diff --git a/Asn1Editor/API/Generic/ObservableList.cs b/Asn1Editor/API/Generic/ObservableList.cs new file mode 100644 index 0000000..4cdb594 --- /dev/null +++ b/Asn1Editor/API/Generic/ObservableList.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; + +namespace Asn1Editor.API.Generic { + public class ObservableList : List, IObservableList { + public ObservableList() { + IsNotifying = true; + CollectionChanged += delegate { OnPropertyChanged(nameof(Count)); }; + } + + public Boolean IsNotifying { get; set; } + + public new void Add(T item) { + base.Add(item); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item); + OnCollectionChanged(e); + } + public new void AddRange(IEnumerable collection) { + IEnumerable array = collection as T[] ?? collection.ToArray(); + base.AddRange(array); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new List(array)); + OnCollectionChanged(e); + } + public new void Clear() { + base.Clear(); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset); + OnCollectionChanged(e); + } + public new void Insert(Int32 i, T item) { + base.Insert(i, item); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item); + OnCollectionChanged(e); + } + public new void InsertRange(Int32 i, IEnumerable collection) { + base.InsertRange(i, collection); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, collection); + OnCollectionChanged(e); + } + public new void Remove(T item) { + base.Remove(item); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item); + OnCollectionChanged(e); + } + public new void RemoveAll(Predicate match) { + List backup = FindAll(match); + base.RemoveAll(match); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, backup); + OnCollectionChanged(e); + } + public new void RemoveAt(Int32 i) { + T backup = this[i]; + base.RemoveAt(i); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, backup); + OnCollectionChanged(e); + } + public new void RemoveRange(Int32 index, Int32 count) { + List backup = GetRange(index, count); + base.RemoveRange(index, count); + var e = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, backup); + OnCollectionChanged(e); + } + public new T this[Int32 index] { + get => base[index]; + set { + T oldValue = base[index]; + NotifyCollectionChangedEventArgs e = + new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value, oldValue); + OnCollectionChanged(e); + } + } + + protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { + if (IsNotifying && CollectionChanged != null) { + try { + CollectionChanged(this, e); + } catch (NotSupportedException) { + NotifyCollectionChangedEventArgs alternativeEventArgs = + new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset); + OnCollectionChanged(alternativeEventArgs); + } + } + } + protected void OnPropertyChanged(String propertyName) { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + public event PropertyChangedEventHandler PropertyChanged; + public event NotifyCollectionChangedEventHandler CollectionChanged; + } + +} diff --git a/Asn1Editor/API/ModelObjects/Asn1Lite.cs b/Asn1Editor/API/ModelObjects/Asn1Lite.cs new file mode 100644 index 0000000..d710fdf --- /dev/null +++ b/Asn1Editor/API/ModelObjects/Asn1Lite.cs @@ -0,0 +1,192 @@ +using System; +using System.Windows; +using Asn1Editor.API.Utils; +using Asn1Editor.API.Utils.ASN; +using Asn1Editor.API.ViewModel; +using Asn1Editor.Properties; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.ModelObjects { + public class Asn1Lite : ViewModelBase { + Byte tag, unusedBits; + Boolean invalidData; + Int32 offset, offsetChange; + Int32 payloadLength, deepness; + String tagName, explicitValue, treePath; + + public Asn1Lite(Asn1Reader asn) { + Offset = asn.Offset; + Tag = asn.Tag; + TagName = asn.TagName; + PayloadLength = asn.PayloadLength; + PayloadStartOffset = asn.PayloadStartOffset; + IsContainer = asn.IsConstructed; + Deepness = 0; + Path = String.Empty; + IsRoot = true; + try { + if (!asn.IsConstructed) { + ExplicitValue = AsnDecoder.GetViewValue(asn); + } + } catch { + InvalidData = true; + } + } + public Asn1Lite(Asn1Reader root, Asn1TreeNode tree, Int32 index) { + Offset = root.Offset; + Tag = root.Tag; + TagName = root.TagName; + PayloadLength = root.PayloadLength; + PayloadStartOffset = root.PayloadStartOffset; + IsContainer = root.IsConstructed; + Deepness = tree.Value.Deepness + 1; + Path = tree.Value.Path + "/" + index; + if (Tag == (Byte)Asn1Type.BIT_STRING) { + if (root.PayloadLength > 0) UnusedBits = root.RawData[root.PayloadStartOffset]; + } + if (!root.IsConstructed) { + try { + ExplicitValue = AsnDecoder.GetViewValue(root); + } catch { + InvalidData = true; + } + } + } + + public String Caption { + get { + String value = String.IsNullOrEmpty(explicitValue) || !Settings.Default.DecodePayload + ? String.Empty + : " : " + explicitValue; + String value2 = IsContainer && Tag == (Byte)Asn1Type.BIT_STRING + ? " Unused bits: " + UnusedBits + : String.Empty; + return IsContainer + ? $"({Offset}, {PayloadLength}) {TagName}{value2.TrimEnd()}" + : $"({Offset}, {PayloadLength}) {TagName}{value.TrimEnd()}"; + } + } + public Byte Tag { + get => tag; + set { + tag = value; + OnPropertyChanged("Tag"); + } + } + public Byte UnusedBits { + get => unusedBits; + set { + unusedBits = value; + OnPropertyChanged("UnusedBits"); + OnPropertyChanged("Caption"); + } + } + public String TagName { + get => tagName; + set { + tagName = value; + if (value.StartsWith("CONTEXT SPECIFIC")) { IsContextSpecific = true; } + OnPropertyChanged("Caption"); + } + } + public Int32 Offset { + get => offset; + set { + offset = value; + OnPropertyChanged("Caption"); + } + } + public Int32 OffsetChange { + get => offsetChange; + set { + if (offsetChange == value) { return; } + offsetChange = value; + OnPropertyChanged("OffsetChange"); + } + } + + public Int32 PayloadStartOffset { get; set; } + public Int32 HeaderLength => PayloadStartOffset - Offset; + public Int32 PayloadLength { + get => payloadLength; + set { + payloadLength = value; + OnPropertyChanged("Caption"); + } + } + public Int32 TagLength => HeaderLength + PayloadLength; + public Boolean IsContainer { get; set; } + + public Boolean IsContextSpecific { get; set; } + public Boolean IsRoot { get; set; } + public Boolean InvalidData { + get => invalidData; + set { + invalidData = value; + OnPropertyChanged("InvalidData"); + } + } //TODO + public Int32 Deepness { + get => deepness; + set { + deepness = value; + OnPropertyChanged("Caption"); + } + } + public String Path { + get => treePath; + set { + treePath = value; + OnPropertyChanged("Caption"); + } + } + public String ExplicitValue { + get => explicitValue; + set { + explicitValue = value; + OnPropertyChanged("Caption"); + } + } + + public void UpdateView() { + OnPropertyChanged("Caption"); + } + public Boolean ValidateValue(String newValue, Byte unused) { + Byte[] binValue; + try { + binValue = AsnDecoder.EncodeGeneric(Tag, newValue, unused); + } catch (Exception e) { + Tools.MsgBox("Error", e.Message); + return false; + } + if (Tag == (Byte)Asn1Type.BIT_STRING) { UnusedBits = unused; } + Asn1Reader asn = new Asn1Reader(binValue); + UpdateBinaryCopy(binValue); + PayloadStartOffset = Offset + asn.TagLength - asn.PayloadLength; + ExplicitValue = AsnDecoder.GetViewValue(asn); + OffsetChange = asn.PayloadLength - PayloadLength; + PayloadLength = asn.PayloadLength; + ((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + return true; + } + public override Boolean Equals(Object obj) { + if (ReferenceEquals(null, obj)) { return false; } + if (ReferenceEquals(this, obj)) { return true; } + return obj.GetType() == typeof (Asn1Lite) && Equals((Asn1Lite) obj); + } + protected Boolean Equals(Asn1Lite other) { + return offset == other.offset && tag == other.tag; + } + public override Int32 GetHashCode() { + unchecked { + return (offset * 397) ^ tag.GetHashCode(); + } + } + + void UpdateBinaryCopy(Byte[] newBytes) { + MainWindowVM.RawData.RemoveRange(Offset, TagLength); + MainWindowVM.RawData.InsertRange(Offset, newBytes); + //((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + } + } +} diff --git a/Asn1Editor/API/ModelObjects/Asn1TreeNode.cs b/Asn1Editor/API/ModelObjects/Asn1TreeNode.cs new file mode 100644 index 0000000..389d05e --- /dev/null +++ b/Asn1Editor/API/ModelObjects/Asn1TreeNode.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Windows; +using Asn1Editor.API.Utils; +using Asn1Editor.API.ViewModel; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.ModelObjects { + public class Asn1TreeNode { + readonly ObservableCollection _children = new ObservableCollection(); + + public Asn1TreeNode(Asn1Lite value) { + Value = value; + Path = value.Path; + String[] tokens = Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + MyIndex = String.IsNullOrEmpty(Path) + ? 0 + : Convert.ToInt32(tokens[tokens.Length - 1]); + Value.PropertyChanged += valuePropertyChanged; + } + + public Asn1TreeNode this[Int32 index] => _children[index]; + public String Path { get; set; } + public Int32 MyIndex { get; set; } + public Asn1TreeNode Parent { get; private set; } + public Asn1Lite Value { get; } + public ObservableCollection Children => _children; + public void InsertChildNode(Asn1TreeNode nodeToInsert, Asn1TreeNode caller, NodeAddOption option) { + Int32 indexToInsert, newOffset; + nodeToInsert.Parent = this; + nodeToInsert.Value.IsRoot = false; + Int32 headerLength = nodeToInsert.Value.HeaderLength; + switch (option) { + case NodeAddOption.Before: + indexToInsert = _children.IndexOf(caller); + newOffset = caller.Value.Offset; + break; + case NodeAddOption.After: + indexToInsert = _children.IndexOf(caller) + 1; + newOffset = caller.Value.Offset + caller.Value.TagLength; + break; + case NodeAddOption.Last: + indexToInsert = _children.Count; + newOffset = Value.Offset + Value.TagLength; + break; + default: + return; + } + //TODO verify code + Value.IsContainer = true; + if (indexToInsert < 0) { return; } + MainWindowVM.RawData.InsertRange(newOffset, ClipboardManager.GetClipboardBytes()); + _children.Insert(indexToInsert, nodeToInsert); + NotifySizeChanged(nodeToInsert, nodeToInsert.Value.TagLength); + _children[indexToInsert].Value.Offset = newOffset; + _children[indexToInsert].Value.PayloadStartOffset = newOffset + headerLength; + for (Int32 index = indexToInsert; index < Children.Count; index++) { + UpdatePath(Children[index], Path, index); + } + foreach (Asn1TreeNode child in _children[indexToInsert].Children) { + child.UpdateOffset(newOffset); + } + ((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + } + public Int32 AddChild(Asn1Lite value, Boolean forcePathUpdate = false) { + var node = new Asn1TreeNode(value) { Parent = this }; + _children.Add(node); + if (forcePathUpdate) { + NotifySizeChanged(node, node.Value.TagLength); + UpdatePath(node, Path, _children.Count - 1); + } + Value.IsContainer = true; + return _children.Count - 1; + } + public void AddNewNode(Asn1Lite value) { + value.Offset = Value.Offset + Value.TagLength; + var node = new Asn1TreeNode(value) { Parent = this }; + _children.Add(node); + NotifySizeChanged(node, Value.OffsetChange); + Value.IsContainer = true; + ((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + } + public void RemoveChild(Asn1TreeNode node) { + //Int32 indexToRemove = Children.IndexOf(node); + //if (indexToRemove < 0) { return; } // TODO: is it necessary? + Int32 difference = Children[node.MyIndex].Value.TagLength; + MainWindowVM.RawData.RemoveRange(node.Value.Offset, difference); + NotifySizeChanged(node, -difference); + _children.RemoveAt(node.MyIndex); + ((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + // update path only below removed node + for (Int32 childIndex = node.MyIndex; childIndex < Children.Count; childIndex++) { + UpdatePath(this[childIndex], Path, childIndex); + } + if (_children.Count == 0 && !Value.IsRoot) { + Value.IsContainer = false; + } + } + public IEnumerable Flatten() { + return new[] { Value }.Union(_children.SelectMany(x => x.Flatten())); + } + + void NotifySizeChanged(Asn1TreeNode source, Int32 difference) { + Asn1TreeNode t = this; + do { + if (t.Children.Count > 0) { + Int32 callerIndex = t.Children.IndexOf(source); + if (callerIndex < 0) { return; } + for (Int32 index = callerIndex + 1; index < t.Children.Count; index++) { + t.Children[index].UpdateOffset(difference); + } + } + Byte[] newLenBytes = Asn1Utils.GetLengthBytes(t.Value.PayloadLength + difference); + MainWindowVM.RawData.RemoveRange(t.Value.Offset + 1, t.Value.HeaderLength - 1); + MainWindowVM.RawData.InsertRange(t.Value.Offset + 1, newLenBytes); + Int32 diff = newLenBytes.Length - (t.Value.HeaderLength - 1); + if (diff != 0) { + t.UpdateOffset(diff); + } + source = t; + t = t.Parent; + source.Value.PayloadLength += difference; + } while (t != null); + } + void UpdateOffset(Int32 difference) { + Value.Offset += difference; + Value.PayloadStartOffset += difference; + foreach (Asn1TreeNode children in Children) { + children.UpdateOffset(difference); + } + } + void valuePropertyChanged(Object sender, PropertyChangedEventArgs e) { + if (e.PropertyName == "OffsetChange") { + if (Parent != null) { + if (Value.OffsetChange != 0) { + Parent.NotifySizeChanged(this, Value.OffsetChange); + } + ((MainWindowVM)Application.Current.MainWindow.DataContext).HexViewerContext.BuildHexView(null); + } + } + } + + static void UpdatePath(Asn1TreeNode source, String path, Int32 index) { + source.Value.Path = source.Path = path + "/" + index; + source.MyIndex = index; + Int32 deepness = source.Value.Path.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries).Length; + source.Value.Deepness = deepness; + for (Int32 Index = 0; Index < source.Children.Count; Index++) { + UpdatePath(source.Children[Index], source.Path, Index); + } + } + + protected Boolean Equals(Asn1TreeNode other) { + return String.Equals(Path, other.Path); + } + public override Int32 GetHashCode() { + return Path != null ? Path.GetHashCode() : 0; + } + public override Boolean Equals(Object obj) { + if (ReferenceEquals(null, obj)) { return false; } + if (ReferenceEquals(this, obj)) { return true; } + return obj.GetType() == GetType() && Equals((Asn1TreeNode) obj); + } + } +} diff --git a/Asn1Editor/API/ModelObjects/NodeAddOption.cs b/Asn1Editor/API/ModelObjects/NodeAddOption.cs new file mode 100644 index 0000000..2b058cd --- /dev/null +++ b/Asn1Editor/API/ModelObjects/NodeAddOption.cs @@ -0,0 +1,7 @@ +namespace Asn1Editor.API.ModelObjects { + public enum NodeAddOption { + Before, + After, + Last + } +} diff --git a/Asn1Editor/API/Utils/ASN/AsnDecoder.cs b/Asn1Editor/API/Utils/ASN/AsnDecoder.cs new file mode 100644 index 0000000..d3bf8ef --- /dev/null +++ b/Asn1Editor/API/Utils/ASN/AsnDecoder.cs @@ -0,0 +1,372 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.ViewModel; +using Asn1Editor.Properties; +using SysadminsLV.Asn1Parser; +using SysadminsLV.Asn1Parser.Universal; + +namespace Asn1Editor.API.Utils.ASN { + static class AsnDecoder { + static List generatePrintableStringTable() { + List allowed = new List { 32 }; + for (Byte index = 0x30; index <= 0x39; index++) { allowed.Add(index); } + for (Byte index = 0x41; index <= 0x5a; index++) { allowed.Add(index); } + for (Byte index = 0x61; index <= 0x7a; index++) { allowed.Add(index); } + for (Byte index = 0x27; index <= 0x29; index++) { allowed.Add(index); } + for (Byte index = 0x2b; index <= 0x2f; index++) { allowed.Add(index); } + allowed.AddRange(new Byte[] { 0x3a, 0x3d, 0x3f }); + return allowed; + } + public static String GetEditValue(Asn1Lite asn) { + var raw = MainWindowVM.RawData; + switch (asn.Tag) { + case (Byte)Asn1Type.BOOLEAN: + case (Byte)Asn1Type.UTCTime: + case (Byte)Asn1Type.Generalizedtime: + return asn.ExplicitValue; + case (Byte)Asn1Type.INTEGER: + return HexUtility.GetHexEditString(raw.Skip(asn.PayloadStartOffset).Take(asn.PayloadLength).ToArray()); + case (Byte)Asn1Type.BIT_STRING: + return HexUtility.GetHexEditString(raw.Skip(asn.PayloadStartOffset + 1).Take(asn.PayloadLength - 1).ToArray()); + case (Byte)Asn1Type.OBJECT_IDENTIFIER: + Oid oid = DecodeObjectIdentifier(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + return oid.Value; + case (Byte)Asn1Type.UTF8String: + return DecodeUTF8String(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + case (Byte)Asn1Type.NumericString: + //TODO create appropriate decoder + return Encoding.ASCII.GetString(raw.Skip(asn.PayloadStartOffset).ToArray()); + case (Byte)Asn1Type.PrintableString: + return DecodePrintableString(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + // TODO + case (Byte)Asn1Type.TeletexString: + return Encoding.ASCII.GetString(raw.Skip(asn.PayloadStartOffset).ToArray()); + case (Byte)Asn1Type.VideotexString: + return Encoding.ASCII.GetString(raw.Skip(asn.PayloadStartOffset).ToArray()); + case (Byte)Asn1Type.IA5String: + return DecodeIA5String(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + case (Byte)Asn1Type.VisibleString: + return DecodeVisibleString(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + case (Byte)Asn1Type.UniversalString: + return DecodeUniversalString(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + case (Byte)Asn1Type.BMPString: + return DecodeBMPString(raw.Skip(asn.Offset).Take(asn.TagLength).ToArray()); + default: + return (asn.Tag & (Byte)Asn1Type.TAG_MASK) == 6 + ? Encoding.UTF8.GetString(raw.Skip(asn.PayloadStartOffset).Take(asn.PayloadLength).ToArray()) + : HexUtility.GetHexEditString(raw.Skip(asn.PayloadStartOffset).Take(asn.PayloadLength).ToArray()); + } + } + public static String GetViewValue(Asn1Reader asn) { + if (asn.PayloadLength == 0 && asn.Tag != (Byte)Asn1Type.NULL) { return "NULL"; } + switch (asn.Tag) { + case (Byte)Asn1Type.BOOLEAN: return DecodeBoolean(asn); + case (Byte)Asn1Type.INTEGER: return DecodeInteger(asn); + case (Byte)Asn1Type.BIT_STRING: return DecodeBitString(asn); + case (Byte)Asn1Type.OCTET_STRING: return DecodeOctetString(asn); + case (Byte)Asn1Type.NULL: return null; + case (Byte)Asn1Type.OBJECT_IDENTIFIER: return DecodeObjectIdentifier(asn); + case (Byte)Asn1Type.UTF8String: return DecodeUTF8String(asn); + case (Byte)Asn1Type.NumericString: + case (Byte)Asn1Type.PrintableString: + case (Byte)Asn1Type.TeletexString: + case (Byte)Asn1Type.VideotexString: + case (Byte)Asn1Type.IA5String: + return DecodeAsciiString(asn); + case (Byte)Asn1Type.UTCTime: + return DecodeUtcTime(asn); + case (Byte)Asn1Type.BMPString: return DecodeBMPString(asn); + case (Byte)Asn1Type.Generalizedtime: + return DecodeGeneralizedTime(asn); + default: + return (asn.Tag & (Byte)Asn1Type.TAG_MASK) == 6 + ? DecodeUTF8String(asn) + : DecodeOctetString(asn); + } + } + + #region Data type encoders + public static Byte[] EncodeInteger(UInt64 value) { + return Asn1Utils.Encode(HexUtility.HexToBinary($"{value:x2}"), (Byte)Asn1Type.INTEGER); + } + public static Byte[] EncodeUTCTime(DateTime time) { + Char[] chars = (time.ToUniversalTime().ToString("yyMMddHHmmss") + "Z").ToCharArray(); + Byte[] rawData = new Byte[chars.Length]; + Int32 index = 0; + foreach (Char element in chars) { + rawData[index] = Convert.ToByte(element); + index++; + } + return Asn1Utils.Encode(rawData, (Byte)Asn1Type.UTCTime); + } + public static DateTime DecodeUTCTime(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.Tag != (Byte)Asn1Type.UTCTime) { throw new InvalidDataException("Input data is not valid ASN-encoded UTC Time."); } + StringBuilder SB = new StringBuilder(); + foreach (Byte element in asn.GetPayload()) { SB.Append(Convert.ToChar(element)); } + try { + return DateTime.ParseExact(SB.ToString().Replace("Z", null), "yyMMddHHmmss", null).ToLocalTime(); + } catch { throw new InvalidDataException("Input data is not valid ASN-encoded UTC Time."); } + } + public static Byte[] EncodeGeneralizedTime(DateTime time) { + Char[] chars = (time.ToUniversalTime().ToString("yyyyMMddHHmmss") + "Z").ToCharArray(); + Byte[] rawData = new Byte[chars.Length]; + Int32 index = 0; + foreach (Char element in chars) { + rawData[index] = Convert.ToByte(element); + index++; + } + return Asn1Utils.Encode(rawData, (Byte)Asn1Type.Generalizedtime); + } + public static DateTime DecodeGeneralizedTime(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.Tag != (Byte)Asn1Type.Generalizedtime) { throw new InvalidDataException("Input data is not valid ASN-encoded GENERALIZED TIME."); } + StringBuilder SB = new StringBuilder(); + foreach (Byte element in asn.GetPayload()) { + SB.Append(Convert.ToChar(element)); + } + try { + return DateTime.ParseExact(SB.ToString().Replace("Z", null), "yyyyMMddHHmmss", null).ToLocalTime(); + } catch { throw new InvalidDataException("Input data is not valid ASN-encoded GENERALIZED TIME."); } + } + public static Byte[] EncodeObjectIdentifier(Oid oid) { + if (oid == null) { throw new ArgumentNullException(); } + if (String.IsNullOrEmpty(oid.Value)) { throw new ArgumentException("oid"); } + return CryptoConfig.EncodeOID(oid.Value); + } + public static Oid DecodeObjectIdentifier(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + try { + Byte[] raw = Asn1Utils.Encode(rawData, 48); + AsnEncodedData asnencoded = new AsnEncodedData(raw); + X509EnhancedKeyUsageExtension eku = new X509EnhancedKeyUsageExtension(asnencoded, false); + return eku.EnhancedKeyUsages[0]; + } catch { throw new InvalidDataException("Input data is not valid ASN-encoded Oid."); } + } + public static Byte[] EncodeBoolean(Boolean str) { + Byte[] rawData = { 1, 1, 0 }; + if (str) { rawData[2] = 255; } + return rawData; + } + public static String DecodeUTF8String(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.Tag != (Byte)Asn1Type.UTF8String) { throw new InvalidDataException(); } + return Encoding.UTF8.GetString(asn.GetPayload()); + } + public static Byte[] EncodeUTF8String(String inputString) { + return Asn1Utils.Encode(Encoding.UTF8.GetBytes(inputString), (Byte)Asn1Type.UTF8String); + } + public static String DecodeIA5String(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.GetPayload().Any(@by => @by > 127)) { + throw new ArgumentException("The data is invalid."); + } + if (asn.Tag == (Byte)Asn1Type.IA5String) { + return Encoding.ASCII.GetString(asn.GetPayload()); + } + throw new InvalidDataException(); + } + public static Byte[] EncodeIA5String(String inputString) { + Char[] chars = inputString.ToCharArray(); + if (chars.Any(ch => ch > 127)) { + throw new InvalidDataException(); + } + return Asn1Utils.Encode(Encoding.ASCII.GetBytes(inputString), (Byte)Asn1Type.IA5String); + } + public static String DecodePrintableString(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.Tag != (Byte)Asn1Type.PrintableString) { throw new InvalidDataException(); } + List allowed = generatePrintableStringTable(); + if (asn.GetPayload().Any(@by => !allowed.Contains(@by))) { + throw new ArgumentException("The data is invalid."); + } + return Encoding.ASCII.GetString(asn.GetPayload()); + } + public static Byte[] EncodePrintableString(String inputString) { + List allowed = generatePrintableStringTable(); + if (inputString.Any(c => !allowed.Contains((Byte)c))) { + throw new InvalidDataException(); + } + return Asn1Utils.Encode(Encoding.ASCII.GetBytes(inputString), (Byte)Asn1Type.PrintableString); + } + public static String DecodeVisibleString(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.GetPayload().Any(x => x < 32 || x > 126)) { + throw new InvalidDataException(); + } + if (asn.Tag == (Byte)Asn1Type.VisibleString) { + return Encoding.ASCII.GetString(asn.GetPayload()); + } + throw new InvalidDataException(); + } + public static Byte[] EncodeVisibleString(String inputString) { + Char[] chars = inputString.ToCharArray(); + if (chars.Any(ch => ch < 32 || ch > 126)) { + throw new InvalidDataException(); + } + return Asn1Utils.Encode(Encoding.ASCII.GetBytes(inputString), (Byte)Asn1Type.VisibleString); + } + public static String DecodeBMPString(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + if (asn.Tag == (Byte)Asn1Type.BMPString) { + return Encoding.BigEndianUnicode.GetString(asn.GetPayload()); + } + throw new InvalidDataException(); + } + public static Byte[] EncodeBMPString(String inputString) { + return Asn1Utils.Encode(Encoding.BigEndianUnicode.GetBytes(inputString), (Byte)Asn1Type.BMPString); + } + public static String DecodeUniversalString(Byte[] rawData) { + if (rawData == null) { throw new ArgumentNullException(); } + Asn1Reader asn = new Asn1Reader(rawData); + List orderedBytes = new List(); + if (asn.Tag == (Byte)Asn1Type.UniversalString) { + for (Int32 index = 0; index < rawData.Length; index += 4) { + orderedBytes.AddRange(new[] { rawData[index + 3], rawData[index + 2], rawData[index + 1], rawData[index] }); + } + return Encoding.UTF32.GetString(orderedBytes.ToArray()); + } + throw new InvalidDataException(); + } + public static Byte[] EncodeUniversalString(String inputString) { + List orderedBytes = new List(); + Byte[] unordered = Encoding.UTF32.GetBytes(inputString); + for (Int32 index = 0; index < unordered.Length; index += 4) { + orderedBytes.AddRange(new[] { unordered[index + 3], unordered[index + 2], unordered[index + 1], unordered[index] }); + } + return Asn1Utils.Encode(orderedBytes.ToArray(), (Byte)Asn1Type.UniversalString); + } + public static Byte[] EncodeNull() { + return new Byte[] { 5, 0 }; + } + public static Byte[] EncodeDateTime(DateTime time) { + return time.Year <= 2049 ? EncodeUTCTime(time) : EncodeGeneralizedTime(time); + } + + public static Byte[] EncodeGeneric(Byte tag, String value, Byte unusedBits) { + switch (tag) { + case (Byte)Asn1Type.BOOLEAN: + return EncodeBoolean(Boolean.Parse(value)); + case (Byte)Asn1Type.INTEGER: + return Asn1Utils.Encode(HexUtility.HexToBinary(value), tag); + case (Byte)Asn1Type.BIT_STRING: + List bitBlob = new List { unusedBits }; + bitBlob.AddRange(HexUtility.HexToBinary(value)); + return Asn1Utils.Encode(bitBlob.ToArray(), (Byte)Asn1Type.BIT_STRING); + case (Byte)Asn1Type.OCTET_STRING: + return Asn1Utils.Encode(HexUtility.HexToBinary(value), tag); + case (Byte)Asn1Type.NULL: + return EncodeNull(); + case (Byte)Asn1Type.OBJECT_IDENTIFIER: + return EncodeObjectIdentifier(new Oid(value)); + case (Byte)Asn1Type.ENUMERATED: + return Asn1Utils.Encode(new[] { Byte.Parse(value) }, tag); + case (Byte)Asn1Type.UTF8String: + return EncodeUTF8String(value); + case (Byte)Asn1Type.NumericString: + case (Byte)Asn1Type.TeletexString: + case (Byte)Asn1Type.VideotexString: + return Asn1Utils.Encode(Encoding.ASCII.GetBytes(value), tag); + case (Byte)Asn1Type.PrintableString: + return EncodePrintableString(value); + case (Byte)Asn1Type.IA5String: + return EncodeIA5String(value); + case (Byte)Asn1Type.UTCTime: + return EncodeUTCTime(DateTime.ParseExact(value, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture)); + case (Byte)Asn1Type.Generalizedtime: + return EncodeGeneralizedTime(DateTime.ParseExact(value, "MM/dd/yyyy HH:mm:ss", CultureInfo.InvariantCulture)); + //case (Byte)ASN1Tags.GraphicString + case (Byte)Asn1Type.VisibleString: + return EncodeVisibleString(value); + case (Byte)Asn1Type.GeneralString: + return Asn1Utils.Encode(Encoding.UTF8.GetBytes(value), tag); + case (Byte)Asn1Type.UniversalString: + return EncodeUniversalString(value); + case (Byte)Asn1Type.BMPString: + return EncodeBMPString(value); + default: + if ((tag & (Byte)Asn1Type.TAG_MASK) == 6) { + return Asn1Utils.Encode(Encoding.UTF8.GetBytes(value), tag); + } + return Asn1Utils.Encode(HexUtility.HexToBinary(value), tag); + } + } + #endregion + #region Data type robust decoders + static String DecodeBoolean(Asn1Reader asn) { + if (asn.PayloadLength != 1) { + throw new InvalidDataException("Invalid Boolean."); + } + // non-zero value is True + return asn.RawData[asn.PayloadStartOffset] == 0 ? false.ToString() : true.ToString(); + } + static String DecodeInteger(Asn1Reader asn) { + return Settings.Default.IntAsInt + ? new BigInteger(asn.GetPayload().Reverse().ToArray()).ToString() + : AsnFormatter.BinaryToString( + asn.RawData, + EncodingType.HexRaw, + EncodingFormat.NOCRLF, asn.PayloadStartOffset, asn.PayloadLength); + } + static String DecodeBitString(Asn1Reader asn) { + return String.Format( + "Unused bits: {0} : {1}", + asn.RawData[asn.PayloadStartOffset], + AsnFormatter.BinaryToString( + asn.RawData, + EncodingType.HexRaw, + EncodingFormat.NOCRLF, + asn.PayloadStartOffset + 1, + asn.PayloadLength - 1) + ); + } + static String DecodeOctetString(Asn1Reader asn) { + return AsnFormatter.BinaryToString( + asn.RawData, + EncodingType.HexRaw, + EncodingFormat.NOCRLF, asn.PayloadStartOffset, asn.PayloadLength); + } + static String DecodeObjectIdentifier(Asn1Reader asn) { + Oid oid = Asn1ObjectIdentifier.Decode(asn); + if (String.IsNullOrEmpty(oid.FriendlyName) && MainWindowVM.OIDs.ContainsKey(oid.Value)) { + oid.FriendlyName = MainWindowVM.OIDs[oid.Value]; + } + return String.IsNullOrEmpty(oid.FriendlyName) + ? oid.Value + : String.Format("{0} ({1})", oid.FriendlyName, oid.Value); + } + static String DecodeUTF8String(Asn1Reader asn) { + return Encoding.UTF8.GetString(asn.RawData, asn.PayloadStartOffset, asn.PayloadLength); + } + static String DecodeAsciiString(Asn1Reader asn) { + return Encoding.ASCII.GetString(asn.RawData, asn.PayloadStartOffset, asn.PayloadLength); + } + static String DecodeUtcTime(Asn1Reader asn) { + DateTime dt = Asn1UtcTime.Decode(asn); + return dt.ToString("dd.MM.yyyy hh:mm:ss"); + } + static String DecodeGeneralizedTime(Asn1Reader asn) { + DateTime dt = Asn1GeneralizedTime.Decode(asn); + return dt.ToString("dd.MM.yyyy hh:mm:ss"); + } + static String DecodeBMPString(Asn1Reader asn) { + return Encoding.BigEndianUnicode.GetString(asn.RawData, asn.PayloadStartOffset, asn.PayloadLength); + } + #endregion + } +} diff --git a/Asn1Editor/API/Utils/ASN/AsnTreeBuilder.cs b/Asn1Editor/API/Utils/ASN/AsnTreeBuilder.cs new file mode 100644 index 0000000..1d6eea7 --- /dev/null +++ b/Asn1Editor/API/Utils/ASN/AsnTreeBuilder.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Asn1Editor.API.ModelObjects; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.Utils.ASN { + public static class AsnTreeBuilder { + public static Task BuildTree(Byte[] rawData) { + return Task.Factory.StartNew(() => { + Asn1Reader asn = new Asn1Reader(rawData); + asn.BuildOffsetMap(); + Asn1Lite root = new Asn1Lite(asn); + Asn1TreeNode parent = new Asn1TreeNode(root); + if (asn.NextOffset == 0) { + return parent; + } + List list = new List { parent }; + buildTree(asn, parent); + return list[0]; + }); + } + static void buildTree(Asn1Reader root, Asn1TreeNode tree) { + root.MoveNext(); + Int32 index = 0; + do { + tree.AddChild(new Asn1Lite(root, tree, index)); + index++; + } while (root.MoveNextCurrentLevel()); + root.Reset(); + foreach (Asn1TreeNode node in tree.Children.Where(node => node.Value.IsContainer)) { + root.MoveToPoisition(node.Value.Offset); + buildTree(root, node); + } + } + } +} diff --git a/Asn1Editor/API/Utils/ClipboardManager.cs b/Asn1Editor/API/Utils/ClipboardManager.cs new file mode 100644 index 0000000..ee0aea2 --- /dev/null +++ b/Asn1Editor/API/Utils/ClipboardManager.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils.ASN; + +namespace Asn1Editor.API.Utils { + static class ClipboardManager { + static readonly List _rawData = new List(); + + public static void SetClipboardData(IEnumerable content) { + _rawData.Clear(); + _rawData.AddRange(content); + } + public static void ClearClipboard() { + _rawData.Clear(); + } + public static async Task GetClipboardData() { + return await AsnTreeBuilder.BuildTree(_rawData.ToArray()); + } + public static IEnumerable GetClipboardBytes() { + return _rawData; + } + } +} diff --git a/Asn1Editor/API/Utils/Extensions/StringExtensions.cs b/Asn1Editor/API/Utils/Extensions/StringExtensions.cs new file mode 100644 index 0000000..72ff7ca --- /dev/null +++ b/Asn1Editor/API/Utils/Extensions/StringExtensions.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace Asn1Editor.API.Utils.Extensions { + static class StringExtensions { + public static IEnumerable SplitByLength(this String str, Int32 maxLength) { + for (Int32 index = 0; index < str.Length; index += maxLength) { + yield return str.Substring(index, Math.Min(maxLength, str.Length - index)); + } + } + } +} diff --git a/Asn1Editor/API/Utils/FileUtility.cs b/Asn1Editor/API/Utils/FileUtility.cs new file mode 100644 index 0000000..dbe8977 --- /dev/null +++ b/Asn1Editor/API/Utils/FileUtility.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.Utils { + static class FileUtility { + static String GetRawText(String path) { + using (StreamReader sr = new StreamReader(path)) { + return sr.ReadToEnd(); + } + } + static Boolean ValidateData(Byte tag) { + //List excludedTags = new List( + // new Byte[] { 0, 1, 2, 5, 6, 9, 10, 13 } + //); + //if (excludedTags.Contains(tag)) { return false; } + //Byte masked = (Byte)(tag & (Byte)ASN1Tags.TAG_MASK); + //if ((masked & (Byte)ASN1Classes.CONSTRUCTED) != 0) { + // if (excludedTags.Contains(masked)) { + // return false; + // } + //} + return true; + } + public static Task> FileToBinary(String path) { + return Task.Factory.StartNew(() => { + FileInfo fileInfo = new FileInfo(path); + if (!fileInfo.Exists) { + throw new Win32Exception(2); + } + Byte[] buffer = new Byte[4]; + using (FileStream fs = new FileStream(path, FileMode.Open)) { + fs.Read(buffer, 0, 4); + } + if ( + buffer[0] == 0xfe && buffer[1] == 0xff || // BigEndian unicode + buffer[0] == 0xff && buffer[1] == 0xfe || // LittleEndian unicode + buffer[0] == 0xff && buffer[1] == 0xfe && buffer[2] == 0 && buffer[3] == 0 || // UTF32 + buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf || // UTF8 + buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76 // UTF7 + ) { + return HexUtility.AnyToBinary(GetRawText(path)); + } + Asn1Reader asn = new Asn1Reader(File.ReadAllBytes(path)); + if (asn.TagLength == fileInfo.Length) { + if (ValidateData(asn.Tag)) { + return asn.GetTagRawData(); + } + throw new Exception("The data is invalid"); + } + asn = new Asn1Reader(HexUtility.AnyToBinary(GetRawText(path)).ToArray()); + if (ValidateData(asn.Tag)) { + return asn.GetTagRawData(); + } + throw new Exception("The data is invalid"); + }); + } + } +} diff --git a/Asn1Editor/API/Utils/HexConverter.cs b/Asn1Editor/API/Utils/HexConverter.cs new file mode 100644 index 0000000..66583c7 --- /dev/null +++ b/Asn1Editor/API/Utils/HexConverter.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Asn1Editor.API.ModelObjects; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.Utils { + static class HexUtility { + public static String GetHexString(IEnumerable rawData, Asn1Lite node) { + Int32 startOffset = node.Offset + node.TagLength - node.PayloadLength; + Int32 endOffset = node.Offset + node.TagLength; + return AsnFormatter.BinaryToString(rawData.ToArray(), EncodingType.Hex, 0, startOffset, endOffset - startOffset); + } + public static String GetHexUString(Byte[] rawData) { + if (rawData == null || rawData.Length == 0) { return String.Empty; } + return AsnFormatter.BinaryToString(rawData).ToUpper(); + } + public static String GetHexEditString(Byte[] rawData) { + if (rawData == null || rawData.Length == 0) { return String.Empty; } + return AsnFormatter.BinaryToString(rawData, EncodingType.Hex).ToUpper(); + } + public static String BinaryToHex(Byte[] rawData) { + return AsnFormatter.BinaryToString(rawData, EncodingType.Hex, EncodingFormat.NOCR); + } + public static Byte[] HexToBinary(String hexString) { + return AsnFormatter.StringToBinary(hexString, EncodingType.Hex); + } + public static IEnumerable AnyToBinary(String anyString) { + try { + return AsnFormatter.StringToBinary(anyString, EncodingType.HexAny); + } catch { + try { + return AsnFormatter.StringToBinary(anyString, EncodingType.StringAny); + } catch { + try { + return AsnFormatter.StringToBinary(anyString, EncodingType.Binary); + } catch { + Tools.MsgBox("Error", "The data is invalid"); + return null; + } + } + } + } + } +} diff --git a/Asn1Editor/API/Utils/TextUtility.cs b/Asn1Editor/API/Utils/TextUtility.cs new file mode 100644 index 0000000..6c42bc8 --- /dev/null +++ b/Asn1Editor/API/Utils/TextUtility.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.Controls; + +namespace Asn1Editor.API.Utils { + static class TextUtility { + static Int32 getOffset(Int32 offset) { + Int32 line = (Int32)Math.Floor((Double)offset / 16); + return (offset - 16 * line) * 3 + 50 * line + 2; + } + static TextRange[] GetRanges(IList pointers) { + TextRange[] ranges = new TextRange[3]; + ranges[0] = new TextRange(pointers[0], pointers[1]); + ranges[1] = new TextRange(pointers[2], pointers[3]); + ranges[2] = new TextRange(pointers[4], pointers[5]); + return ranges; + } + static void ScrollToPosition(TextPointer startPointer, BindableRichTextBox rtb, ScrollViewer scroller) { + rtb.CaretPosition = startPointer; + scroller.ScrollToVerticalOffset(rtb.FontSize * (rtb.CurrentLine - 1)); + } + + public static TextRange[] GetTextPointers(Asn1Lite treeNode, BindableRichTextBox rtb, ScrollViewer scroller) { + TextPointer[] pointers = new TextPointer[6]; + // tag + pointers[0] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.Offset) + ); + pointers[1] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.Offset + 1) + ); + // length bytes + pointers[2] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.Offset + 1) + ); + pointers[3] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.PayloadStartOffset) + ); + //// payload + pointers[4] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.PayloadStartOffset) + ); + pointers[5] = rtb.Document.ContentStart.GetPositionAtOffset( + getOffset(treeNode.PayloadStartOffset + treeNode.PayloadLength) + ); + ScrollToPosition(pointers[0], rtb, scroller); + return GetRanges(pointers); + } + public static void Colorize(TextRange[] ranges) { + foreach (TextRange range in ranges) { + range.ApplyPropertyValue(TextElement.FontWeightProperty,FontWeights.Bold); + } + ranges[0].ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red); + ranges[1].ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Green); + ranges[2].ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Black); + } + public static void ResetColors(IEnumerable ranges) { + foreach (TextRange range in ranges.Where(range => range != null)) { + range.ClearAllProperties(); + } + } + } +} diff --git a/Asn1Editor/API/Utils/Tools.cs b/Asn1Editor/API/Utils/Tools.cs new file mode 100644 index 0000000..fa13cc6 --- /dev/null +++ b/Asn1Editor/API/Utils/Tools.cs @@ -0,0 +1,31 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Media; + +namespace Asn1Editor.API.Utils { + static class Tools { + public static MessageBoxResult MsgBox(String header, String message, MessageBoxImage image = MessageBoxImage.Error, MessageBoxButton button = MessageBoxButton.OK) { + WindowCollection windows = Application.Current.Windows; + Window hwnd = null; + if (windows.Count > 0) { + hwnd = windows[windows.Count - 1]; + } + return hwnd == null + ? MessageBox.Show(message, header, button, image) + : MessageBox.Show(hwnd, message, header, button, image); + } + public static Double MeasureString(String str, Int32 size, Boolean includeScrollbars) { + var formattedText = new FormattedText( + str, + CultureInfo.CurrentUICulture, + FlowDirection.LeftToRight, + new Typeface(new FontFamily("Consolas"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), + size, + Brushes.Black); + return includeScrollbars + ? formattedText.Width + SystemParameters.VerticalScrollBarWidth + 12 + : formattedText.Width + 12; + } + } +} diff --git a/Asn1Editor/API/ViewModel/ConverterVM.cs b/Asn1Editor/API/ViewModel/ConverterVM.cs new file mode 100644 index 0000000..441335a --- /dev/null +++ b/Asn1Editor/API/ViewModel/ConverterVM.cs @@ -0,0 +1,317 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Windows; +using System.Windows.Input; +using Asn1Editor.API.Generic; +using Asn1Editor.API.Utils; +using Asn1Editor.Properties; +using Microsoft.Win32; +using SysadminsLV.Asn1Parser; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class ConverterVM : ViewModelBase { + const String master = "123456789012345678901234567890123456789012345678901234567890123456789012345678"; + Double width; + String text, path; + Boolean isLocked, canCheck, + base64, base64header, base64req, base64crl, hex, hexaddr, hexascii, hexaddrascii, hexraw; + + public ConverterVM() { + base64 = true; + OnPropertyChanged(nameof(Base64)); + OpenCommand = new RelayCommand(OpenFile); + SaveCommand = new RelayCommand(SaveFile, CanPrintSave); + PrintCommand = new RelayCommand(Print, CanPrintSave); + ClearCommand = new RelayCommand(ClearText); + ValidateCommand = new RelayCommand(ValidateInput); + TextBoxWidth = Tools.MeasureString(master, Settings.Default.FontSize, true); + } + + public ICommand OpenCommand { get; set; } + public ICommand SaveCommand { get; set; } + public ICommand ClearCommand { get; set; } + public ICommand ValidateCommand { get; set; } + public ICommand PrintCommand { get; set; } + + public String Text { + get => text; + set { + text = value.Trim(); + OnPropertyChanged(nameof(Text)); + } + } + public String Path { + get => path; + set { + path = value; + OnPropertyChanged(nameof(Path)); + } + } + public Double TextBoxWidth { + get => width; + set { + width = value; + OnPropertyChanged(nameof(TextBoxWidth)); + } + } + public Boolean CanCheck { + get => canCheck; + set { + canCheck = value; + OnPropertyChanged(nameof(CanCheck)); + } + } + public ObservableList RawData { get; } = new ObservableList {IsNotifying = true}; + + #region Radiobuttons + public Boolean Base64 { + get => base64; + set { + base64 = value; + if (base64) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64); } + OnPropertyChanged(nameof(Base64)); + } + } + public Boolean Base64Header { + get => base64header; + set { + base64header = value; + if (base64header) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64Header); } + OnPropertyChanged(nameof(Base64Header)); + } + } + public Boolean Base64Req { + get => base64req; + set { + base64req = value; + if (base64req) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64RequestHeader); } + OnPropertyChanged(nameof(Base64Req)); + } + } + public Boolean Base64Crl { + get => base64crl; + set { + base64crl = value; + if (base64crl) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64CrlHeader); } + OnPropertyChanged(nameof(Base64Crl)); + } + } + public Boolean Hex { + get => hex; + set { + hex = value; + if (hex) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Hex); } + OnPropertyChanged(nameof(Hex)); + } + } + public Boolean HexAddr { + get => hexaddr; + set { + hexaddr = value; + if (hexaddr) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAddress); } + OnPropertyChanged(nameof(HexAddr)); + } + } + public Boolean HexAscii { + get => hexascii; + set { + hexascii = value; + if (hexascii) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAscii); } + OnPropertyChanged(nameof(HexAscii)); + } + } + public Boolean HexAddrAscii { + get => hexaddrascii; + set { + hexaddrascii = value; + if (hexaddrascii) { Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAsciiAddress); } + OnPropertyChanged(nameof(HexAddrAscii)); + } + } + public Boolean HexRaw { + get => hexraw; + set { + hexraw = value; + if (hexraw) { Text = AsnFormatter.BinaryToString(RawData.ToArray()); } + OnPropertyChanged(nameof(HexRaw)); + } + } + #endregion + + void OpenFile(Object obj) { + isLocked = true; + OpenFileDialog dlg = new OpenFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + if (result != true) { return; } + Path = dlg.FileName; + RawData.Clear(); + try { + RawData.AddRange(FileUtility.FileToBinary(path).Result); + RadioChanged("base64"); + } catch (Exception e) { + Tools.MsgBox("Read Error", e.Message); + Path = null; + } + isLocked = false; + } + void SaveFile(Object obj) { + switch ((String)obj) { + case "text": + if (String.IsNullOrEmpty(Path)) { + if (!GetFilePath()) { return; } + } + SaveText(); + break; + case "textas": + if (!GetFilePath()) { return; } + SaveText(); + break; + case "bin": + if (String.IsNullOrEmpty(Path)) { + if (!GetFilePath()) { return; } + } + SaveBinary(); + break; + case "binas": + if (!GetFilePath()) { return; } + SaveBinary(); + break; + } + } + void ValidateInput(Object obj) { + if (String.IsNullOrEmpty(Text)) { + Tools.MsgBox("Warning", "There is nothing to validate.", MessageBoxImage.Warning); + return; + } + EncodingType encoding = AsnFormatter.TestInputString(Text); + RawData.Clear(); + switch (encoding) { + case EncodingType.Base64: + base64 = true; + OnPropertyChanged(nameof(Base64)); + break; + case EncodingType.Base64Header: + base64header = true; + OnPropertyChanged(nameof(Base64Header)); + break; + case EncodingType.Base64RequestHeader: + base64req = true; + OnPropertyChanged(nameof(Base64Req)); + break; + case EncodingType.Base64CrlHeader: + base64crl = true; + OnPropertyChanged(nameof(Base64Crl)); + break; + case EncodingType.Hex: + hex = true; + OnPropertyChanged(nameof(Hex)); + break; + case EncodingType.HexAddress: + hexaddr = true; + OnPropertyChanged(nameof(HexAddr)); + break; + case EncodingType.HexAscii: + hexascii = true; + OnPropertyChanged(nameof(HexAscii)); + break; + case EncodingType.HexAsciiAddress: + hexaddrascii = true; + OnPropertyChanged(nameof(HexAddrAscii)); + break; + case EncodingType.HexRaw: + hexraw = true; + OnPropertyChanged(nameof(HexRaw)); + break; + default: + Tools.MsgBox("Error","Input text cannot be validated."); + return; + } + RawData.AddRange(HexUtility.AnyToBinary(Text)); + if (obj != null && obj.ToString() == "Decode") { + OnPropertyChanged("Decode"); + } + } + void ClearText(Object obj) { + Text = String.Empty; + RawData.Clear(); + Path = null; + } + void Print(Object obj) { + StaticCommands.Print(Text); + } + Boolean CanPrintSave(Object obj) { + return CanCheck = RawData.Count > 0; + } + Boolean GetFilePath() { + SaveFileDialog dlg = new SaveFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + if (result != true) { return false; } + Path = dlg.FileName; + return true; + } + void SaveText() { + try { + File.WriteAllText(Path, Text); + } catch (Exception e) { + Tools.MsgBox("Save Error", e.Message); + } + } + void SaveBinary() { + try { + File.WriteAllBytes(Path, RawData.ToArray()); + } catch (Exception e) { + Tools.MsgBox("Save Error", e.Message); + } + } + + public void RadioChanged(String tag) { + if (RawData.Count == 0) { return; } + switch (tag.ToLower()) { + case "base64": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64); + Base64 = true; + break; + case "base64header": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64Header); + break; + case "base64reqheader": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64RequestHeader); + break; + case "base64crlheader": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Base64CrlHeader); + break; + case "hex": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.Hex); + break; + case "hexaddr": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAddress); + break; + case "hexascii": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAscii); + break; + case "hexaddrascii": + Text = AsnFormatter.BinaryToString(RawData.ToArray(), EncodingType.HexAsciiAddress); + break; + case "hexraw": + Text = AsnFormatter.BinaryToString(RawData.ToArray()); + break; + } + } + public void SetBytes(IEnumerable rawData) { + if (rawData == null) { return; } + RawData.Clear(); + RawData.AddRange(rawData); + RadioChanged("base64"); + } + } +} diff --git a/Asn1Editor/API/ViewModel/HexViewerVM.cs b/Asn1Editor/API/ViewModel/HexViewerVM.cs new file mode 100644 index 0000000..2a6baf1 --- /dev/null +++ b/Asn1Editor/API/ViewModel/HexViewerVM.cs @@ -0,0 +1,187 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Windows; +using System.Windows.Documents; +using System.Windows.Input; +using Asn1Editor.API.Utils; +using Asn1Editor.Properties; +using SysadminsLV.Asn1Parser; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class HexViewerVM : INotifyPropertyChanged { + const String masterAddr = "12345678"; + const String masterHex = "123456789012345678901234567890123456789012345678"; + const String masterAscii = "1234567890123456"; + Visibility hexAddressVisible; + Visibility asciiValueVisible; + Boolean hexAddressChecked; + Boolean asciiValueChecked; + FlowDocument addressDocument; + FlowDocument hexDocument; + FlowDocument asciiDocument; + Double addrWidth, hexWidth, asciiWidth; + + public HexViewerVM() { + ChangeHexAddressCommand = new RelayCommand(ChangeHexAddress); + ChangeAsciiValueCommand = new RelayCommand(ChangeAsciiValue); + Init(); + } + + public MainWindowVM ParentVM { get; set; } + public IHexView View { get; set; } + + public ICommand ChangeHexAddressCommand { get; set; } + public ICommand ChangeAsciiValueCommand { get; set; } + + public Visibility HexAddressVisible { + get => hexAddressVisible; + set { + hexAddressVisible = value; + OnPropertyChanged("HexAddressVisible"); + } + } + public Visibility AsciiValueVisible { + get => asciiValueVisible; + set { + asciiValueVisible = value; + OnPropertyChanged("AsciiValueVisible"); + } + } + public Boolean HexAddressChecked { + get => hexAddressChecked; + set { + hexAddressChecked = value; + OnPropertyChanged("HexAddressChecked"); + } + } + public Boolean AsciiValueChecked { + get => asciiValueChecked; + set { + asciiValueChecked = value; + OnPropertyChanged("AsciiValueChecked"); + } + } + public FlowDocument AddressDocument { + get => addressDocument; + set { + addressDocument = value; + OnPropertyChanged("AddressDocument"); + } + } + public FlowDocument HexDocument { + get => hexDocument; + set { + hexDocument = value; + OnPropertyChanged("HexDocument"); + } + } + public FlowDocument AsciiDocument { + get => asciiDocument; + set { + asciiDocument = value; + OnPropertyChanged("AsciiDocument"); + } + } + public Double AddrWidth { + get => addrWidth; + set { + addrWidth = value; + OnPropertyChanged("AddrWidth"); + } + } + public Double HexWidth { + get => hexWidth; + set { + hexWidth = value; + OnPropertyChanged("HexWidth"); + } + } + public Double AsciiWidth { + get => asciiWidth; + set { + asciiWidth = value; + OnPropertyChanged("AsciiWidth"); + } + } + + void Init() { + calculateWidths(); + Settings.Default.PropertyChanged += (Sender, Args) => { + if (Args.PropertyName == "FontSize") { + calculateWidths(); + } + }; + HexAddressVisible = Visibility.Visible; + AsciiValueVisible = Visibility.Visible; + HexAddressChecked = true; + AsciiValueChecked = true; + } + void calculateWidths() { + AddrWidth = Tools.MeasureString(masterAddr, Settings.Default.FontSize, false); + HexWidth = Tools.MeasureString(masterHex, Settings.Default.FontSize, false); + AsciiWidth = Tools.MeasureString(masterAscii, Settings.Default.FontSize, false); + } + void buildAddress(ICollection rawData) { + AddressDocument = new FlowDocument(); + Paragraph addressParagraph = new Paragraph(); + foreach (Int32 row in Enumerable.Range(0, (Int32)Math.Ceiling((Double)rawData.Count / 16))) { + addressParagraph.Inlines.Add(new Run(String.Format("{0:X8}", row * 16) + Environment.NewLine)); + } + AddressDocument.Blocks.Add(addressParagraph); + } + void buildHex(Byte[] rawData) { + HexDocument = new FlowDocument(); + Paragraph hexParagraph = new Paragraph(); + hexParagraph.Inlines.Add(new Run(AsnFormatter.BinaryToString(rawData, EncodingType.Hex).ToUpper())); + HexDocument.Blocks.Add(hexParagraph); + } + void buildAscii(IList rawData) { + AsciiDocument = new FlowDocument(); + Paragraph asciiParagraph = new Paragraph(); + StringBuilder SB = new StringBuilder(); + for (Int32 index = 0; index < rawData.Count; index++) { + Char c = rawData[index] < 32 || rawData[index] > 126 + ? '.' + : (Char)rawData[index]; + if (index != 0 && index % 16 == 0) { + SB.Append(Environment.NewLine); + } + SB.Append(c); + } + asciiParagraph.Inlines.Add(new Run(SB + Environment.NewLine)); + AsciiDocument.Blocks.Add(asciiParagraph); + } + void ChangeHexAddress(Object obj) { + HexAddressVisible = HexAddressChecked + ? Visibility.Visible + : Visibility.Collapsed; + } + void ChangeAsciiValue(Object obj) { + AsciiValueVisible = AsciiValueChecked + ? Visibility.Visible + : Visibility.Collapsed; + } + + public void BuildHexView(Byte[] rawData) { + if (rawData == null) { + if (MainWindowVM.RawData.Count == 0) { return; } + rawData = MainWindowVM.RawData.ToArray(); + } + buildAddress(rawData); + buildHex(rawData); + buildAscii(rawData); + } + + void OnPropertyChanged(String PropertyName) { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) { + handler(this, new PropertyChangedEventArgs(PropertyName)); + } + } + public event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/Asn1Editor/API/ViewModel/IHexView.cs b/Asn1Editor/API/ViewModel/IHexView.cs new file mode 100644 index 0000000..e5e409e --- /dev/null +++ b/Asn1Editor/API/ViewModel/IHexView.cs @@ -0,0 +1,7 @@ +using Asn1Editor.API.ModelObjects; + +namespace Asn1Editor.API.ViewModel { + interface IHexView { + void SelectHexView(Asn1Lite treeNode); + } +} diff --git a/Asn1Editor/API/ViewModel/MainWindowVM.cs b/Asn1Editor/API/ViewModel/MainWindowVM.cs new file mode 100644 index 0000000..e1120d4 --- /dev/null +++ b/Asn1Editor/API/ViewModel/MainWindowVM.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; +using Asn1Editor.API.Generic; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils; +using Asn1Editor.API.Utils.ASN; +using Asn1Editor.Properties; +using Microsoft.Win32; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class MainWindowVM : ViewModelBase { + String path; + Asn1TreeNode selectedNode; + Visibility hexVisible; + Boolean hexChecked, hasClipboard, isBusy; + + public MainWindowVM() { + RawData = new ObservableList { IsNotifying = true }; + Tree = new ObservableCollection(); + HexViewerContext = new HexViewerVM { ParentVM = this }; + TreeCommands = new TreeViewCommands(this); + OpenCommand = new RelayCommand(OpenFile); + SaveCommand = new RelayCommand(SaveFile, CanPrintSave); + HexViewerChanged = new RelayCommand(ChangeHexViewer); + ShowConverterCommand = new RelayCommand(StaticCommands.ShowConverter); + SettingsCommand = new RelayCommand(StaticCommands.ShowSettings); + AboutCommand = new RelayCommand(StaticCommands.ShowAbout); + Settings.Default.PropertyChanged += onSettingChange; + initialize(); + } + + public ICommand OpenCommand { get; set; } + public ICommand SaveCommand { get; set; } + public ICommand PrintCommand { get; set; } + public ICommand HexViewerChanged { get; set; } + public ICommand ShowConverterCommand { get; set; } + public ICommand SettingsCommand { get; set; } + public ICommand AboutCommand { get; set; } + + public HexViewerVM HexViewerContext { get; set; } + public TreeViewCommands TreeCommands { get; set; } + + public static ObservableList RawData { get; set; } + public static Dictionary OIDs { get; set; } + public ObservableCollection Tree { get; set; } + + public String Path { + get => path; + set { + path = value; + OnPropertyChanged("Path"); + OnPropertyChanged("Title"); + } + } + public String Title => String.IsNullOrEmpty(Path) + ? "ASN.1 Editor" + : "ASN.1 Editor " + new FileInfo(Path).Name; + public Boolean HasClipboardData { + get => hasClipboard; + set { + hasClipboard = value; + OnPropertyChanged("HasClipboardData"); + } + } + public Asn1TreeNode SelectedTreeNode { + get => selectedNode; + set { + selectedNode = value; + OnPropertyChanged("SelectedTreeNode"); + if (selectedNode != null) { + HexViewerContext.View.SelectHexView(selectedNode.Value); + } + } + } + public Visibility HexViewerVisible { + get => hexVisible; + set { + hexVisible = value; + OnPropertyChanged("HexViewerVisible"); + } + } + public Boolean HexViewerChecked { + get => hexChecked; + set { + hexChecked = value; + OnPropertyChanged("HexViewerChecked"); + } + } + public Boolean IsBusy { + get => isBusy; + set { + isBusy = value; + OnPropertyChanged("IsBusy"); + } + } + + void initialize() { + HexViewerVisible = Visibility.Collapsed; + HexViewerChecked = false; + } + void OpenFile(Object obj) { + OpenFileDialog dlg = new OpenFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + if (result != true) { return; } + OpenExisting(dlg.FileName); + } + void SaveFile(Object obj) { + if (obj != null || String.IsNullOrEmpty(Path)) { + if (!GetFilePath()) { return; } + } + try { + File.WriteAllBytes(Path, RawData.ToArray()); + } catch (Exception e) { + Tools.MsgBox("Save Error", e.Message); + } + } + async void Decode() { + IsBusy = true; + if (await DecodeFile()) { + Tree.Clear(); + try { + Asn1TreeNode rootNode = await AsnTreeBuilder.BuildTree(RawData.ToArray()); + Tree.Add(rootNode); + HexViewerContext.BuildHexView(RawData.ToArray()); + } catch (Exception e) { + Tools.MsgBox("Error", e.Message); + } + } + IsBusy = false; + } + + + static Boolean CanPrintSave(Object obj) { + return RawData.Count > 0; + } + Boolean GetFilePath() { + SaveFileDialog dlg = new SaveFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + if (result != true) { return false; } + Path = dlg.FileName; + return true; + } + void ChangeHexViewer(Object obj) { + HexViewerVisible = HexViewerChecked + ? Visibility.Visible + : Visibility.Collapsed; + } + async Task DecodeFile() { + if (RawData.Count > 0) { + return true; + } + try { + RawData.AddRange(await FileUtility.FileToBinary(Path)); + return true; + } catch (Exception e) { + Tools.MsgBox("Read Error", e.Message); + Path = null; + return false; + } + } + public void DropFile(String filePath) { + if (!File.Exists(filePath)) { return; } + Path = filePath; + RawData.Clear(); + Decode(); + } + public void OpenExisting(String filePath) { + Path = filePath; + RawData.Clear(); + Decode(); + } + public void OpenRaw(String base64String) { + OpenRaw(Convert.FromBase64String(base64String)); + } + public void OpenRaw(IEnumerable rawBytes) { + Path = null; + RawData.Clear(); + RawData.AddRange(rawBytes); + Decode(); + } + + void onSettingChange(Object sender, PropertyChangedEventArgs e) { + if (Tree.Count == 0) { return; } + switch (e.PropertyName) { + case "IntAsInt": + StaticCommands.UpdateSettingsInteger(Tree[0], RawData); + break; + case "DecodePayload": + StaticCommands.UpdateSettingsDecode(Tree[0]); + break; + } + } + } +} diff --git a/Asn1Editor/API/ViewModel/StaticCommands.cs b/Asn1Editor/API/ViewModel/StaticCommands.cs new file mode 100644 index 0000000..ebc91e7 --- /dev/null +++ b/Asn1Editor/API/ViewModel/StaticCommands.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Numerics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; +using System.Windows.Media; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.Properties; +using Asn1Editor.Views.Windows; +using SysadminsLV.Asn1Parser; + +namespace Asn1Editor.API.ViewModel { + static class StaticCommands { + static Converter converter; + static Boolean converterClosed = true; + static TextViewer textViewer; + static Boolean textViewerClosed = true; + + public static void UpdateSettingsDecode(Asn1TreeNode rootNode) { + foreach (Asn1Lite node in rootNode.Flatten()) { + node.UpdateView(); + } + } + public static void UpdateSettingsInteger(Asn1TreeNode rootNode, IList rawData) { + if (Settings.Default.IntAsInt) { + foreach (Asn1Lite node in rootNode.Flatten().Where(x => x.Tag == (Byte)Asn1Type.INTEGER)) { + Byte[] raw = rawData.Skip(node.PayloadStartOffset).Take(node.PayloadLength).ToArray(); + node.ExplicitValue = new BigInteger(raw.Reverse().ToArray()).ToString(); + } + } else { + foreach (Asn1Lite node in rootNode.Flatten().Where(x => x.Tag == (Byte)Asn1Type.INTEGER)) { + Byte[] raw = rawData.Skip(node.PayloadStartOffset).Take(node.PayloadLength).ToArray(); + node.ExplicitValue = AsnFormatter.BinaryToString( + raw, + EncodingType.HexRaw, + EncodingFormat.NOCRLF + ); + } + } + } + public static void Print(String text) { + PrintDialog printDialog = new PrintDialog(); + if (!printDialog.ShowDialog().GetValueOrDefault()) { return; } + FlowDocument flowDocument = new FlowDocument { + PageHeight = printDialog.PrintableAreaHeight, + PageWidth = printDialog.PrintableAreaWidth, + PagePadding = new Thickness(25), + ColumnGap = 0, + }; + flowDocument.ColumnWidth = flowDocument.PageWidth - + flowDocument.ColumnGap - + flowDocument.PagePadding.Left - + flowDocument.PagePadding.Right; + Paragraph paragraph = new Paragraph { + Margin = new Thickness(0), + FontFamily = new FontFamily("Consolas"), + FontSize = Settings.Default.FontSize, + }; + paragraph.Inlines.Add(new Run(text)); + flowDocument.Blocks.Add(paragraph); + DocumentPaginator paginator = ((IDocumentPaginatorSource)flowDocument).DocumentPaginator; + printDialog.PrintDocument(paginator, String.Empty); + } + public static void ShowAbout(Object obj) { + AboutBox dlg = new AboutBox(Application.Current.MainWindow); + dlg.ShowDialog(); + } + public static void ShowSettings(Object obj) { + SettingsWnd dlg = new SettingsWnd(); + dlg.ShowDialog(); + } + public static void ShowConverter(Object obj) { + if (!converterClosed) { + converter.Focus(); + return; + } + converterClosed = false; + converter = new Converter(); + converter.Closed += (Sender, Args) => { converterClosed = true; }; + ((ConverterVM)converter.DataContext).PropertyChanged += OnPropertyChanged; + ((ConverterVM)converter.DataContext).SetBytes(MainWindowVM.RawData); + converter.Show(); + converter.Focus(); + } + public static void ShowText(Object obj) { + if (obj == null) { return; } + if (!textViewerClosed) { + textViewer.Focus(); + return; + } + textViewerClosed = false; + textViewer = new TextViewer(); + textViewer.Closed += (Sender, Args) => { textViewerClosed = true; }; + ((TextViewerVM)textViewer.DataContext).SetBinding((Asn1TreeNode)obj); + textViewer.Show(); + textViewer.Focus(); + } + public static void ClearResources() { + if (!textViewerClosed) { textViewer.Close(); } + if (!converterClosed) { converter.Close(); } + } + + static void OnPropertyChanged(Object sender, PropertyChangedEventArgs e) { + if (e.PropertyName == "Decode") { + ((MainWindowVM)Application.Current.MainWindow.DataContext).OpenRaw(((ConverterVM)sender).RawData); + } + } + } +} diff --git a/Asn1Editor/API/ViewModel/TagDataEditorVM.cs b/Asn1Editor/API/ViewModel/TagDataEditorVM.cs new file mode 100644 index 0000000..5d5b633 --- /dev/null +++ b/Asn1Editor/API/ViewModel/TagDataEditorVM.cs @@ -0,0 +1,153 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils; +using Asn1Editor.API.Utils.ASN; +using Asn1Editor.Properties; +using Asn1Editor.Views.Windows; +using SysadminsLV.Asn1Parser; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class TagDataEditorVM : INotifyPropertyChanged { + const String masterTag = "123"; + const String masterUnused = "1"; + Asn1Lite asn; + String tagDetails, tagValue, tagHex, oldValue; + Boolean isReadonly, tagIsReadOnly = true; + Visibility unusedBitsVisible = Visibility.Collapsed; + Byte unusedBits, tag; + Double tagTextBoxWidth, unusedTextBoxWidth; + + public TagDataEditorVM() { + OkCommand = new RelayCommand(SubmitValues); + Init(); + } + + public ICommand OkCommand { get; set; } + public Boolean Accepted { get; private set; } + + public String TagDetails { + get => tagDetails; + set { + tagDetails = value; + OnPropertyChanged("TagDetails"); + } + } + public String TagValue { + get => tagValue; + set { + tagValue = value; + OnPropertyChanged("TagValue"); + } + } + public Boolean TagIsReadOnly { + get => tagIsReadOnly; + set { + tagIsReadOnly = value; + OnPropertyChanged("TagIsReadOnly"); + } + } + public Byte Tag { + get => tag; + set { + if (Byte.TryParse(value.ToString(CultureInfo.InvariantCulture), out Byte t)) { + tag = t; + } + OnPropertyChanged("Tag"); + } + } + public Byte UnusedBits { + get => unusedBits; + set { + unusedBits = value; + OnPropertyChanged("UnusedBits"); + } + } + public Visibility UnusedBitsVisible { + get => unusedBitsVisible; + set { + unusedBitsVisible = value; + OnPropertyChanged("UnusedBitsVisible"); + } + } + public Boolean IsReadonly { + get => isReadonly; + set { + isReadonly = value; + OnPropertyChanged("IsReadonly"); + } + } + public Double TagTextBoxWidth { + get => tagTextBoxWidth; + set { + tagTextBoxWidth = value; + OnPropertyChanged("TagTextBoxWidth"); + } + } + public Double UnusedTextBoxWidth { + get => unusedTextBoxWidth; + set { + unusedTextBoxWidth = value; + OnPropertyChanged("UnusedTextBoxWidth"); + } + } + + void Init() { + calculateLengths(); + Settings.Default.PropertyChanged += (Sender, Args) => { + if (Args.PropertyName == "FontSize") { + calculateLengths(); + } + }; + } + void calculateLengths() { + TagTextBoxWidth = Tools.MeasureString(masterTag, Settings.Default.FontSize, false); + UnusedTextBoxWidth = Tools.MeasureString(masterUnused, Settings.Default.FontSize, false); + } + void SubmitValues(Object obj) { + Accepted = true; + if (Tag == 0) { + Tools.MsgBox("Error", "Invalid tag number"); + return; + } + asn.Tag = Tag; + if (TagValue == oldValue) { + ((TagDataEditor)obj).Close(); + return; + } + if (asn.ValidateValue(TagValue, UnusedBits)) { + ((TagDataEditor)obj).Close(); + } + } + + public void SetBinding(Asn1Lite asnNode, Boolean hex) { + asn = asnNode; + Tag = asnNode.Tag; + UnusedBits = asnNode.UnusedBits; + IsReadonly = asnNode.IsContainer || asnNode.Tag == (Byte)Asn1Type.NULL; + TagDetails = String.Format(Resources.TagEditorHeaderTemp, Tag, asnNode.TagName, asnNode.Offset, asnNode.PayloadLength, asnNode.Deepness, asnNode.Path); + TagValue = IsReadonly || asnNode.Tag == (Byte)Asn1Type.NULL + ? "Containers and NULL (0x05) tags are not editable" + : hex + ? HexUtility.BinaryToHex(MainWindowVM.RawData.Skip(asnNode.PayloadStartOffset).Take(asnNode.PayloadLength).ToArray()) + : AsnDecoder.GetEditValue(asnNode); + oldValue = TagValue; + UnusedBitsVisible = asnNode.Tag == (Byte)Asn1Type.BIT_STRING + ? Visibility.Visible + : Visibility.Hidden; + } + + void OnPropertyChanged(String PropertyName) { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) { + handler(this, new PropertyChangedEventArgs(PropertyName)); + } + } + public event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/Asn1Editor/API/ViewModel/TextViewerVM.cs b/Asn1Editor/API/ViewModel/TextViewerVM.cs new file mode 100644 index 0000000..31f655e --- /dev/null +++ b/Asn1Editor/API/ViewModel/TextViewerVM.cs @@ -0,0 +1,149 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Windows.Input; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils; +using Asn1Editor.Properties; +using Microsoft.Win32; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class TextViewerVM : INotifyPropertyChanged { + Asn1TreeNode rootNode; + const String master = "123"; + const String delimieter = " | | |"; + const Int32 minLength = 60; + const Int32 defaultLength = 80; + const Int32 maxLength = 400; + String n = Environment.NewLine; + String text; + Int32 currentLength = 80; + String currentLengthStr = "80"; + Double width; + + public TextViewerVM() { + CurrentLength = defaultLength.ToString(CultureInfo.InvariantCulture); + SaveCommand = new RelayCommand(SaveFile); + PrintCommand = new RelayCommand(Print); + ApplyCommand = new RelayCommand(applyNewLength); + TextBoxWidth = Tools.MeasureString(master, Settings.Default.FontSize, false); + } + + public ICommand SaveCommand { get; set; } + public ICommand PrintCommand { get; set; } + public ICommand ApplyCommand { get; set; } + + public String Text { + get => text; + set { + text = value; + OnPropertyChanged("Text"); + } + } + public String CurrentLength { + get => currentLengthStr; + set { + currentLengthStr = value; + OnPropertyChanged("CurrentLength"); + } + } + public Double TextBoxWidth { + get => width; + set { + width = value; + OnPropertyChanged("TextBoxWidth"); + } + } + + void Print(Object obj) { + StaticCommands.Print(Text); + } + void applyNewLength(Object obj) { + Int32 value; + if (!Int32.TryParse(CurrentLength, NumberStyles.Integer, null, out value)) { + CurrentLength = currentLength.ToString(CultureInfo.InvariantCulture); + return; + } + if (value == currentLength) { return; } + currentLength = value < minLength || value > maxLength + ? minLength + : value; + CurrentLength = currentLength.ToString(CultureInfo.InvariantCulture); + GenerateTable(); + } + void GenerateTable() { + if (rootNode == null) { return; } + StringBuilder SB = new StringBuilder("Offset|Length|LenByte|" + n); + SB.Append("======+======+=======+" + new String('=', currentLength + 10) + n); + foreach (Asn1Lite node in rootNode.Flatten()) { + String padding = new String(' ', (node.Deepness - rootNode.Value.Deepness + 1) * 3); + var str = String.Format("{0,6}|{1,6}|{2,7}|{3}{4} : ", + node.Offset, + node.PayloadLength, + node.HeaderLength - 1, + padding, + node.TagName + ); + SB.Append(str + CalculateValue(node, str.Length, padding.Length)); + } + Text = SB.ToString(); + } + String CalculateValue(Asn1Lite node, Int32 lineLength, Int32 padding) { + if (String.IsNullOrEmpty(node.ExplicitValue)) { return n; } + if (24 + padding + node.ExplicitValue.Length <= currentLength) { + return "'" + node.ExplicitValue.Trim() + "'" + n; + } + Int32 remaining = currentLength - 22 - padding; + if (node.ExplicitValue.Length <= remaining - 2) { + return String.Format( + "{0}{1}{4}{2}{3}{2}{0}", + n, + delimieter, + "'", + node.ExplicitValue.Trim(), + new String(' ', padding + 3) + ); + } + return Utils.Extensions.StringExtensions + .SplitByLength(node.ExplicitValue, currentLength - padding) + .Aggregate(n, (current, line) => + current + String.Format("{0}{1}{2}{3}", delimieter, new String(' ', padding + 3), line.Trim(), n)); + } + void SaveFile(Object obj) { + String path = GetFilePath(); + if (String.IsNullOrEmpty(path)) { return; } + try { + File.WriteAllText(path, Text); + } catch (Exception e) { + Tools.MsgBox("Save Error", e.Message); + } + } + + static String GetFilePath() { + SaveFileDialog dlg = new SaveFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + return result != true + ? String.Empty + : dlg.FileName; + } + public void SetBinding(Asn1TreeNode node) { + rootNode = node; + GenerateTable(); + } + void OnPropertyChanged(String PropertyName) { + PropertyChangedEventHandler handler = PropertyChanged; + if (handler != null) { + handler(this, new PropertyChangedEventArgs(PropertyName)); + } + } + public event PropertyChangedEventHandler PropertyChanged; + } +} diff --git a/Asn1Editor/API/ViewModel/TreeViewCommands.cs b/Asn1Editor/API/ViewModel/TreeViewCommands.cs new file mode 100644 index 0000000..27666b5 --- /dev/null +++ b/Asn1Editor/API/ViewModel/TreeViewCommands.cs @@ -0,0 +1,168 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils; +using Asn1Editor.Views.Windows; +using Microsoft.Win32; +using SysadminsLV.Asn1Parser; +using SysadminsLV.WPF.OfficeTheme.Toolkit.Commands; + +namespace Asn1Editor.API.ViewModel { + class TreeViewCommands { + readonly MainWindowVM _parentVM; + readonly List _excludedTags = new List( + new Byte[] { 0, 1, 2, 5, 6, 9, 10, 13 } + ); + + public TreeViewCommands(MainWindowVM Parent) { + _parentVM = Parent; + SaveNodeCommand = new RelayCommand(SaveNode, CanContextMenu); + EditNodeCommand = new RelayCommand(EditNode, CanContextMenu); + ShowTextCommand = new RelayCommand(StaticCommands.ShowText, CanContextMenu); + NewNodeCommand = new RelayCommand(NewNode, CanNew); + CutNodeCommand = new RelayCommand(CutNode, CanRemove); + CopyNodeCommand = new RelayCommand(CopyNode, CanContextMenu); + PasteBeforeCommand = new RelayCommand(PasteBefore, CanPasteAfterBefore); + PasteAfterCommand = new RelayCommand(PasteAfter, CanPasteAfterBefore); + PasteLastCommand = new RelayCommand(PasteLast, CanPasteLast); + DeleteNodeCommand = new RelayCommand(RemoveNode, CanRemove); + } + + public ICommand EditNodeCommand { get; set; } + public ICommand SaveNodeCommand { get; set; } + public ICommand ShowTextCommand { get; set; } + public ICommand NewNodeCommand { get; set; } + public ICommand DeleteNodeCommand { get; set; } + public ICommand CutNodeCommand { get; set; } + public ICommand CopyNodeCommand { get; set; } + public ICommand PasteBeforeCommand { get; set; } + public ICommand PasteAfterCommand { get; set; } + public ICommand PasteLastCommand { get; set; } + + void EditNode(Object obj) { + TagDataEditor dlg = (String)obj == "hex" + ? new TagDataEditor(_parentVM.SelectedTreeNode.Value, true) + : new TagDataEditor(_parentVM.SelectedTreeNode.Value); + dlg.ShowDialog(); + } + void NewNode(Object obj) { + Asn1Lite asn = new Asn1Lite(new Asn1Reader(new Byte[] { 48, 0 })) { IsContainer = true }; + TagDataEditor dlg = new TagDataEditor(asn); + ((TagDataEditorVM)dlg.DataContext).TagIsReadOnly = false; + dlg.ShowDialog(); + if (!((TagDataEditorVM)dlg.DataContext).Accepted) { return; } + if (obj == null) { + Asn1TreeNode node = new Asn1TreeNode(asn); + _parentVM.Tree.Add(node); + MainWindowVM.RawData.AddRange(new Byte[] { 48, 0 }); + _parentVM.HexViewerContext.BuildHexView(null); + } else { + asn = new Asn1Lite(new Asn1Reader(new Byte[] { ((TagDataEditorVM)dlg.DataContext).Tag, 0 })) { + Offset = + _parentVM.SelectedTreeNode + .Value.Offset + + _parentVM.SelectedTreeNode + .Value.TagLength + }; + asn.PayloadStartOffset = asn.Offset + 2; + MainWindowVM.RawData.Insert(_parentVM.SelectedTreeNode.Value.Offset + _parentVM.SelectedTreeNode.Value.TagLength, 0); + MainWindowVM.RawData.Insert(_parentVM.SelectedTreeNode.Value.Offset + _parentVM.SelectedTreeNode.Value.TagLength, asn.Tag); + asn.IsRoot = false; + asn.Deepness += _parentVM.SelectedTreeNode.Value.Deepness; + _parentVM.SelectedTreeNode.AddChild(asn, true); + _parentVM.HexViewerContext.BuildHexView(null); + } + } + void CutNode(Object obj) { + ClipboardManager.SetClipboardData( + MainWindowVM.RawData + .Skip(((Asn1TreeNode)obj).Value.Offset) + .Take(((Asn1TreeNode)obj).Value.TagLength) + ); + _parentVM.HasClipboardData = true; + ((Asn1TreeNode)obj).Parent.RemoveChild((Asn1TreeNode)obj); + } + void CopyNode(Object obj) { + ClipboardManager.SetClipboardData( + MainWindowVM.RawData + .Skip(((Asn1TreeNode)obj).Value.Offset) + .Take(((Asn1TreeNode)obj).Value.TagLength) + ); + _parentVM.HasClipboardData = true; + } + static async void PasteBefore(Object obj) { + Asn1TreeNode childNode = await ClipboardManager.GetClipboardData(); + ((Asn1TreeNode)obj).Parent.InsertChildNode( + childNode, + (Asn1TreeNode)obj, + NodeAddOption.Before + ); + } + static async void PasteAfter(Object obj) { + Asn1TreeNode childNode = await ClipboardManager.GetClipboardData(); + ((Asn1TreeNode)obj).Parent.InsertChildNode( + childNode, + (Asn1TreeNode)obj, + NodeAddOption.After + ); + } + static async void PasteLast(Object obj) { + Asn1TreeNode childNode = await ClipboardManager.GetClipboardData(); + ((Asn1TreeNode)obj).InsertChildNode( + childNode, + (Asn1TreeNode)obj, + NodeAddOption.Last + ); + } + static void SaveNode(Object obj) { + SaveFileDialog dlg = new SaveFileDialog { + FileName = "", + DefaultExt = ".*", + Filter = "All files (*.*)|*.*" + }; + Boolean? result = dlg.ShowDialog(); + if (result == true) { + Asn1Lite node = (Asn1Lite)obj; + try { + File.WriteAllBytes(dlg.FileName, MainWindowVM.RawData.Skip(node.Offset).Take(node.TagLength).ToArray()); + } catch (Exception e) { + Tools.MsgBox("Save Error", e.Message); + } + } + } + static void RemoveNode(Object obj) { + MessageBoxResult response = Tools.MsgBox("Delete", "Do you want to delete the node?\nThis action cannot be undone.", MessageBoxImage.Question, MessageBoxButton.YesNo); + if (response == MessageBoxResult.Yes) { + ((Asn1TreeNode)obj).Parent.RemoveChild((Asn1TreeNode)obj); + } + } + + Boolean CanNew(Object obj) { + return _parentVM.Tree.Count == 0 || + _parentVM.SelectedTreeNode != null && + !_excludedTags.Contains(_parentVM.SelectedTreeNode.Value.Tag); + } + Boolean CanRemove(Object obj) { + if (obj == null) { return false; } + return ((Asn1TreeNode)obj).Parent != null && CanContextMenu(null); + } + Boolean CanPasteAfterBefore(Object obj) { + return _parentVM.HasClipboardData && + _parentVM.SelectedTreeNode != null && + _parentVM.SelectedTreeNode.Parent != null; + } + Boolean CanPasteLast(Object obj) { + return obj != null && + _parentVM.HasClipboardData && + !_excludedTags.Contains(((Asn1TreeNode)obj).Value.Tag) && + String.IsNullOrEmpty(((Asn1TreeNode)obj).Value.ExplicitValue); + } + Boolean CanContextMenu(Object obj) { + return _parentVM.SelectedTreeNode != null; + } + } +} diff --git a/Asn1Editor/API/ViewModel/ViewModelBase.cs b/Asn1Editor/API/ViewModel/ViewModelBase.cs new file mode 100644 index 0000000..f054ced --- /dev/null +++ b/Asn1Editor/API/ViewModel/ViewModelBase.cs @@ -0,0 +1,11 @@ +using System; +using System.ComponentModel; + +namespace Asn1Editor.API.ViewModel { + public abstract class ViewModelBase : INotifyPropertyChanged { + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged(String propertyName = null) { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } +} diff --git a/Asn1Editor/App.config b/Asn1Editor/App.config new file mode 100644 index 0000000..ff69897 --- /dev/null +++ b/Asn1Editor/App.config @@ -0,0 +1,30 @@ + + + + +
+ + + + + + + + + 150 + + + 12 + + + True + + + True + + + / + + + + diff --git a/Asn1Editor/App.xaml b/Asn1Editor/App.xaml new file mode 100644 index 0000000..5cd8428 --- /dev/null +++ b/Asn1Editor/App.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + + diff --git a/Asn1Editor/App.xaml.cs b/Asn1Editor/App.xaml.cs new file mode 100644 index 0000000..75bd6cf --- /dev/null +++ b/Asn1Editor/App.xaml.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Windows; +using Asn1Editor.API.ViewModel; +using Asn1Editor.Views.Windows; + +namespace Asn1Editor { + /// + /// Interaction logic for App.xaml + /// + public partial class App { + void AppStartup(Object sender, StartupEventArgs e) { + //AsnFormatter = true; + readOids(); + MainWindow mw = new MainWindow(); + parseArguments((App)sender, e.Args); + mw.Show(); + } + void readOids() { + MainWindowVM.OIDs = new Dictionary(); + var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + if (!File.Exists(path + @"\OID.txt")) { return; } + String[] strings = File.ReadAllLines(path + @"\OID.txt"); + foreach (String[] tokens in strings.Select(str => str.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))) { + try { + MainWindowVM.OIDs.Add(tokens[0], tokens[1].Trim()); + } catch { } + } + } + void parseArguments(App sender, String[] args) { + for (Int32 i = 0; i < args.Length;) { + switch (args[i].ToLower()) { + case "-path": // SRP log file path + i++; + if (args.Length <= i) throw new ArgumentException(args[i]); + ((MainWindowVM)sender.MainWindow.DataContext).OpenExisting(args[i]); + return; + case "-raw": // excluded path patterns (path begins) + i++; + if (args.Length <= i) throw new ArgumentException(args[i]); + ((MainWindowVM)sender.MainWindow.DataContext).OpenRaw(args[i]); + return; + default: + Console.WriteLine($"Unknown parameter '{args[i]}'"); + return; + } + } + } + } +} diff --git a/Asn1Editor/Asn1Editor.csproj b/Asn1Editor/Asn1Editor.csproj new file mode 100644 index 0000000..73d9082 --- /dev/null +++ b/Asn1Editor/Asn1Editor.csproj @@ -0,0 +1,400 @@ + + + + + Debug + AnyCPU + {6338C8ED-B646-470E-8A68-7ED4B05AC02E} + WinExe + Properties + Asn1Editor + Asn1Editor + v4.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + SAK + SAK + SAK + SAK + + + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\x86\Release\ + TRACE + prompt + 4 + false + + + asnlogo.ico + + + bin\x64\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + x64 + bin\x64\Debug\ + + + x64 + bin\x64\Release\ + TRACE + true + + + x64 + bin\x64\x64\ + + + bin\x86\ + TRACE + true + pdbonly + x64 + prompt + MinimumRecommendedRules.ruleset + + + bin\x64\x86\ + x64 + + + x86 + bin\x86\Debug\ + + + x86 + bin\x86\Release\ + + + x86 + bin\x86\x64\ + + + x86 + bin\x86\ + + + + False + True + + + False + _ExternalReferences\SysadminsLV.Asn1Parser.dll + + + + + + + 4.0 + + + + + + False + _ExternalReferences\Wpf.OfficeTheme.dll + + + + + MSBuild:Compile + Designer + + + + + + + + + + + + + + + + + + + + + + + + + + + + AboutBox.xaml + + + SettingsWnd.xaml + + + AsnTreeView.xaml + + + BusyIndicator.xaml + + + HexViewerUC.xaml + + + Converter.xaml + + + TagDataEditor.xaml + + + TextViewer.xaml + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + + App.xaml + Code + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 Client Profile %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + + + + + + + 5.8.6 + + + + + \ No newline at end of file diff --git a/Asn1Editor/Controls/BindableRichTextBox.cs b/Asn1Editor/Controls/BindableRichTextBox.cs new file mode 100644 index 0000000..30b72d4 --- /dev/null +++ b/Asn1Editor/Controls/BindableRichTextBox.cs @@ -0,0 +1,75 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Documents; + +namespace Asn1Editor.Controls { + public class BindableRichTextBox : RichTextBox { + public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register( + nameof(Document), + typeof(FlowDocument), + typeof(BindableRichTextBox), + new FrameworkPropertyMetadata(null, OnDocumentChanged)); + public static readonly DependencyProperty CurrentLineProperty = DependencyProperty.Register( + nameof(CurrentLine), + typeof(Int32), + typeof(BindableRichTextBox), + new FrameworkPropertyMetadata(1)); + public static readonly DependencyProperty CurrentColumnProperty = DependencyProperty.Register( + nameof(CurrentColumn), + typeof(Int32), + typeof(BindableRichTextBox), + new FrameworkPropertyMetadata(1)); + public static readonly DependencyProperty ObserveCaretProperty = DependencyProperty.Register( + nameof(ObserveCaret), + typeof(Boolean), + typeof(BindableRichTextBox), + new UIPropertyMetadata(false, OnObserveCaretPropertyChanged)); + + static void OnObserveCaretPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { + RichTextBox rtb = (RichTextBox)d; + if (rtb != null) { + if ((Boolean)e.NewValue) { + rtb.SelectionChanged += RtbSelectionChanged; + } else { + rtb.SelectionChanged -= RtbSelectionChanged; + } + } + } + static void RtbSelectionChanged(Object sender, RoutedEventArgs e) { + BindableRichTextBox rtb = (BindableRichTextBox)sender; + if (rtb == null) { return; } + + rtb.CaretPosition.GetLineStartPosition(-Int32.MaxValue, out Int32 lineNumber); + rtb.CurrentLine = -lineNumber + 1; + TextPointer lineStartPosition = rtb.CaretPosition.GetLineStartPosition(0); + if (lineStartPosition != null) { + rtb.CurrentColumn = lineNumber == 0 + ? lineStartPosition.GetOffsetToPosition(rtb.CaretPosition) + : lineStartPosition.GetOffsetToPosition(rtb.CaretPosition) - 1; + } + } + + public new FlowDocument Document { + get => (FlowDocument)GetValue(DocumentProperty); + set => SetValue(DocumentProperty, value); + } + public Boolean ObserveCaret { + get => (Boolean)GetValue(ObserveCaretProperty); + set => SetValue(ObserveCaretProperty, value); + } + public Int32 CurrentLine { + get => (Int32)GetValue(CurrentLineProperty); + set => SetValue(CurrentLineProperty, value); + } + public Int32 CurrentColumn { + get => (Int32)GetValue(CurrentColumnProperty); + set => SetValue(CurrentColumnProperty, value); + } + + public static void OnDocumentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args) { + RichTextBox rtb = (RichTextBox)obj; + rtb.Document = (FlowDocument)args.NewValue; + } + } +} diff --git a/Asn1Editor/Controls/CaretBehavior.cs b/Asn1Editor/Controls/CaretBehavior.cs new file mode 100644 index 0000000..f770a8d --- /dev/null +++ b/Asn1Editor/Controls/CaretBehavior.cs @@ -0,0 +1,56 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace Asn1Editor.Controls { + public static class CaretBehavior { + static void OnObserveCaretPropertyChanged(DependencyObject dpo, DependencyPropertyChangedEventArgs e) { + if (dpo is TextBox textBox) { + if ((Boolean)e.NewValue) { + textBox.SelectionChanged += TextBoxSelectionChanged; + } else { + textBox.SelectionChanged -= TextBoxSelectionChanged; + } + } + } + static void TextBoxSelectionChanged(Object sender, RoutedEventArgs e) { + if (sender is TextBox textBox) { + Int32 line = textBox.GetLineIndexFromCharacterIndex(textBox.SelectionStart); + SetCaretIndex(textBox, textBox.SelectionStart - textBox.GetCharacterIndexFromLineIndex(line) + 1); + SetLineIndex(textBox, line + 1); + } + } + static readonly DependencyProperty LineIndexProperty = DependencyProperty.RegisterAttached( + "LineIndex", + typeof(Int32), + typeof(CaretBehavior)); + static readonly DependencyProperty CaretIndexProperty = DependencyProperty.RegisterAttached( + "CaretIndex", + typeof(Int32), + typeof(CaretBehavior)); + + public static readonly DependencyProperty ObserveCaretProperty = DependencyProperty.RegisterAttached( + "ObserveCaret", + typeof(Boolean), + typeof(CaretBehavior), + new UIPropertyMetadata(false, OnObserveCaretPropertyChanged)); + public static Boolean GetObserveCaret(DependencyObject obj) { + return (Boolean)obj.GetValue(ObserveCaretProperty); + } + public static void SetObserveCaret(DependencyObject obj, Boolean value) { + obj.SetValue(ObserveCaretProperty, value); + } + public static void SetCaretIndex(DependencyObject element, Int32 value) { + element.SetValue(CaretIndexProperty, value); + } + public static Int32 GetCaretIndex(DependencyObject element) { + return (Int32)element.GetValue(CaretIndexProperty); + } + public static void SetLineIndex(DependencyObject element, Int32 value) { + element.SetValue(LineIndexProperty, value); + } + public static Int32 GetLineIndex(DependencyObject element) { + return (Int32)element.GetValue(LineIndexProperty); + } + } +} diff --git a/Asn1Editor/OID.txt b/Asn1Editor/OID.txt new file mode 100644 index 0000000..87314bc --- /dev/null +++ b/Asn1Editor/OID.txt @@ -0,0 +1,705 @@ +0.9.2342.19200300.100.1.25, domainComponent +1.2.36.68980861.1.1.10, Signet pilot +1.2.36.68980861.1.1.11, Signet intraNet +1.2.36.68980861.1.1.2, Signet personal +1.2.36.68980861.1.1.20, Signet securityPolicy +1.2.36.68980861.1.1.3, Signet business +1.2.36.68980861.1.1.4, Signet legal +1.2.36.75878867.1.100.1.1, Certificates Australia policyIdentifier +1.2.752.34.1, seis-cp +1.2.752.34.1.1, SEIS certificatePolicy-s10 +1.2.752.34.2, SEIS pe +1.2.752.34.3, SEIS at +1.2.752.34.3.1, SEIS at-personalIdentifier +1.2.840.10040.2.1, holdinstruction-none +1.2.840.10040.2.2, holdinstruction-callissuer +1.2.840.10040.2.3, holdinstruction-reject +1.2.840.10040.4.1, dsa +1.2.840.10040.4.3, dsaWithSha1 +1.2.840.10045.1, fieldType +1.2.840.10045.1.1, prime-field +1.2.840.10045.1.2, characteristic-two-field +1.2.840.10045.1.2.1, ecPublicKey +1.2.840.10045.1.2.3, characteristic-two-basis +1.2.840.10045.1.2.3.1, onBasis +1.2.840.10045.1.2.3.2, tpBasis +1.2.840.10045.1.2.3.3, ppBasis +1.2.840.10045.2, publicKeyType +1.2.840.10045.2.1, ecPublicKey +1.2.840.10046.2.1, dhPublicNumber +1.2.840.113533.7, nsn +1.2.840.113533.7.65, nsn-ce +1.2.840.113533.7.65.0, entrustVersInfo +1.2.840.113533.7.66, nsn-alg +1.2.840.113533.7.66.10, cast5CBC +1.2.840.113533.7.66.11, cast5MAC +1.2.840.113533.7.66.12, pbeWithMD5AndCAST5-CBC +1.2.840.113533.7.66.13, passwordBasedMac +1.2.840.113533.7.66.3, cast3CBC +1.2.840.113533.7.67, nsn-oc +1.2.840.113533.7.67.0, entrustUser +1.2.840.113533.7.68, nsn-at +1.2.840.113533.7.68.0, entrustCAInfo +1.2.840.113533.7.68.10, attributeCertificate +1.2.840.113549.1.1, pkcs-1 +1.2.840.113549.1.1.1, rsaEncryption +1.2.840.113549.1.1.2, md2withRSAEncryption +1.2.840.113549.1.1.3, md4withRSAEncryption +1.2.840.113549.1.1.4, md5withRSAEncryption +1.2.840.113549.1.1.5, sha1withRSAEncryption +1.2.840.113549.1.1.6, rsaOAEPEncryptionSET +1.2.840.113549.1.12, pkcs-12 +1.2.840.113549.1.12.1, pkcs-12-PbeIds +1.2.840.113549.1.12.1.1, pbeWithSHAAnd128BitRC4 +1.2.840.113549.1.12.1.2, pbeWithSHAAnd40BitRC4 +1.2.840.113549.1.12.1.3, pbeWithSHAAnd3-KeyTripleDES-CBC +1.2.840.113549.1.12.1.4, pbeWithSHAAnd2-KeyTripleDES-CBC +1.2.840.113549.1.12.1.5, pbeWithSHAAnd128BitRC2-CBC +1.2.840.113549.1.12.1.6, pbeWithSHAAnd40BitRC2-CBC +1.2.840.113549.1.12.10, pkcs-12Version1 +1.2.840.113549.1.12.10.1, pkcs-12BadIds +1.2.840.113549.1.12.10.1.1, pkcs-12-keyBag +1.2.840.113549.1.12.10.1.2, pkcs-12-pkcs-8ShroudedKeyBag +1.2.840.113549.1.12.10.1.3, pkcs-12-certBag +1.2.840.113549.1.12.10.1.4, pkcs-12-crlBag +1.2.840.113549.1.12.10.1.5, pkcs-12-secretBag +1.2.840.113549.1.12.10.1.6, pkcs-12-safeContentsBag +1.2.840.113549.1.12.2, pkcs-12-ESPVKID +1.2.840.113549.1.12.2.1, pkcs-12-PKCS8KeyShrouding +1.2.840.113549.1.12.3, pkcs-12-BagIds +1.2.840.113549.1.12.3.1, pkcs-12-keyBagId +1.2.840.113549.1.12.3.2, pkcs-12-certAndCRLBagId +1.2.840.113549.1.12.3.3, pkcs-12-secretBagId +1.2.840.113549.1.12.3.4, pkcs-12-safeContentsId +1.2.840.113549.1.12.3.5, pkcs-12-pkcs-8ShroudedKeyBagId +1.2.840.113549.1.12.4, pkcs-12-CertBagID +1.2.840.113549.1.12.4.1, pkcs-12-X509CertCRLBagID +1.2.840.113549.1.12.4.2, pkcs-12-SDSICertBagID +1.2.840.113549.1.12.5, pkcs-12-OID +1.2.840.113549.1.12.5.1, pkcs-12-PBEID +1.2.840.113549.1.12.5.1.1, pkcs-12-PBEWithSha1And128BitRC4 +1.2.840.113549.1.12.5.1.2, pkcs-12-PBEWithSha1And40BitRC4 +1.2.840.113549.1.12.5.1.3, pkcs-12-PBEWithSha1AndTripleDESCBC +1.2.840.113549.1.12.5.1.4, pkcs-12-PBEWithSha1And128BitRC2CBC +1.2.840.113549.1.12.5.1.5, pkcs-12-PBEWithSha1And40BitRC2CBC +1.2.840.113549.1.12.5.1.6, pkcs-12-PBEWithSha1AndRC4 +1.2.840.113549.1.12.5.1.7, pkcs-12-PBEWithSha1AndRC2CBC +1.2.840.113549.1.12.5.2, pkcs-12-EnvelopingID +1.2.840.113549.1.12.5.2.1, pkcs-12-RSAEncryptionWith128BitRC4 +1.2.840.113549.1.12.5.2.2, pkcs-12-RSAEncryptionWith40BitRC4 +1.2.840.113549.1.12.5.2.3, pkcs-12-RSAEncryptionWithTripleDES +1.2.840.113549.1.12.5.3, pkcs-12-SignatureID +1.2.840.113549.1.12.5.3.1, pkcs-12-RSASignatureWithSHA1Digest +1.2.840.113549.1.3, pkcs-3 +1.2.840.113549.1.3.1, dhKeyAgreement +1.2.840.113549.1.5, pkcs-5 +1.2.840.113549.1.5.1, pbeWithMD2AndDES-CBC +1.2.840.113549.1.5.10, pbeWithSHAAndDES-CBC +1.2.840.113549.1.5.3, pbeWithMD5AndDES-CBC +1.2.840.113549.1.5.4, pbeWithMD2AndRC2-CBC +1.2.840.113549.1.5.6, pbeWithMD5AndRC2-CBC +1.2.840.113549.1.5.9, pbeWithMD5AndXOR +1.2.840.113549.1.7, pkcs-7 +1.2.840.113549.1.7.1, data +1.2.840.113549.1.7.2, signedData +1.2.840.113549.1.7.3, envelopedData +1.2.840.113549.1.7.4, signedAndEnvelopedData +1.2.840.113549.1.7.5, digestData +1.2.840.113549.1.7.6, encryptedData +1.2.840.113549.1.7.7, dataWithAttributes +1.2.840.113549.1.7.8, encryptedPrivateKeyInfo +1.2.840.113549.1.9, pkcs-9 +1.2.840.113549.1.9.1, emailAddress +1.2.840.113549.1.9.10, issuerAndSerialNumber +1.2.840.113549.1.9.11, passwordCheck +1.2.840.113549.1.9.12, publicKey +1.2.840.113549.1.9.13, signingDescription +1.2.840.113549.1.9.14, extensionReq +1.2.840.113549.1.9.15, sMIMECapabilities +1.2.840.113549.1.9.15.1, preferSignedData +1.2.840.113549.1.9.15.2, canNotDecryptAny +1.2.840.113549.1.9.15.3, receiptRequest +1.2.840.113549.1.9.15.4, receipt +1.2.840.113549.1.9.15.5, contentHints +1.2.840.113549.1.9.15.6, mlExpansionHistory +1.2.840.113549.1.9.16, id-sMIME +1.2.840.113549.1.9.16.0, id-mod +1.2.840.113549.1.9.16.0.1, id-mod-cms +1.2.840.113549.1.9.16.0.2, id-mod-ess +1.2.840.113549.1.9.16.1, id-ct +1.2.840.113549.1.9.16.1.1, id-ct-receipt +1.2.840.113549.1.9.16.2, id-aa +1.2.840.113549.1.9.16.2.1, id-aa-receiptRequest +1.2.840.113549.1.9.16.2.2, id-aa-securityLabel +1.2.840.113549.1.9.16.2.3, id-aa-mlExpandHistory +1.2.840.113549.1.9.16.2.4, id-aa-contentHint +1.2.840.113549.1.9.2, unstructuredName +1.2.840.113549.1.9.20, friendlyName +1.2.840.113549.1.9.21, localKeyID +1.2.840.113549.1.9.22, certTypes +1.2.840.113549.1.9.22.1, x509Certificate +1.2.840.113549.1.9.22.2, sdsiCertificate +1.2.840.113549.1.9.23, crlTypes +1.2.840.113549.1.9.23.1, x509Crl +1.2.840.113549.1.9.3, contentType +1.2.840.113549.1.9.4, messageDigest +1.2.840.113549.1.9.5, signingTime +1.2.840.113549.1.9.6, countersignature +1.2.840.113549.1.9.7, challengePassword +1.2.840.113549.1.9.8, unstructuredAddress +1.2.840.113549.1.9.9, extendedCertificateAttributes +1.2.840.113549.2, digestAlgorithm +1.2.840.113549.2.2, md2 +1.2.840.113549.2.4, md4 +1.2.840.113549.2.5, md5 +1.2.840.113549.3, encryptionAlgorithm +1.2.840.113549.3.10, desCDMF +1.2.840.113549.3.2, rc2CBC +1.2.840.113549.3.3, rc2ECB +1.2.840.113549.3.4, rc4 +1.2.840.113549.3.5, rc4WithMAC +1.2.840.113549.3.6, DESX-CBC +1.2.840.113549.3.7, DES-EDE3-CBC +1.2.840.113549.3.8, RC5CBC +1.2.840.113549.3.9, RC5-CBCPad +1.2.840.113556.1.4.319, LDAP_PAGED_RESULT_OID_STRING +1.2.840.113556.1.4.417, LDAP_SERVER_SHOW_DELETED_OID +1.2.840.113556.1.4.473, LDAP_SERVER_SORT_OID +1.2.840.113556.1.4.474, LDAP_SERVER_RESP_SORT_OID +1.2.840.113556.1.4.521, LDAP_SERVER_CROSSDOM_MOVE_TARGET_OID +1.2.840.113556.1.4.528, LDAP_SERVER_NOTIFICATION_OID +1.2.840.113556.1.4.529, LDAP_SERVER_EXTENDED_DN_OID +1.2.840.113556.1.4.619, LDAP_SERVER_LAZY_COMMIT_OID +1.2.840.113556.1.4.801, LDAP_SERVER_SD_FLAGS_OID +1.2.840.113556.1.4.802, LDAP_SERVER_RANGE_OPTION_OID +1.2.840.113556.1.4.805, LDAP_SERVER_TREE_DELETE_OID +1.2.840.113556.1.4.841, LDAP_SERVER_DIRSYNC_OID +1.2.840.113556.1.4.970, LDAP_SERVER_GET_STATS_OID +1.2.840.113556.1.4.1338, LDAP_SERVER_VERIFY_NAME_OID +1.2.840.113556.1.4.1339, LDAP_SERVER_DOMAIN_SCOPE_OID +1.2.840.113556.1.4.1340, LDAP_SERVER_SEARCH_OPTIONS_OID +1.2.840.113556.1.4.1341, LDAP_SERVER_RODC_DCPROMO_OID +1.2.840.113556.1.4.1413, LDAP_SERVER_PERMISSIVE_MODIFY_OID +1.2.840.113556.1.4.1504, LDAP_SERVER_ASQ_OID +1.2.840.113556.1.4.1852, LDAP_SERVER_QUOTA_CONTROL_OID +1.2.840.113556.1.4.1907, LDAP_SERVER_SHUTDOWN_NOTIFY_OID +1.2.840.113556.1.4.1948, LDAP_SERVER_RANGE_RETRIEVAL_NOERR_OID +1.2.840.113556.1.4.1974, LDAP_SERVER_FORCE_UPDATE_OID +1.2.840.113556.1.4.2026, LDAP_SERVER_DN_INPUT_OID +1.2.840.113556.1.4.2064, LDAP_SERVER_SHOW_RECYCLED_OID +1.2.840.113556.1.4.2065, LDAP_SERVER_SHOW_DEACTIVATED_LINK_OID +1.2.840.113556.1.4.2066, LDAP_SERVER_POLICY_HINTS_DEPRECATED_OID +1.2.840.113556.1.4.2090, LDAP_SERVER_DIRSYNC_EX_OID +1.2.840.113556.1.4.2204, LDAP_SERVER_TREE_DELETE_EX_OID +1.2.840.113556.1.4.2205, LDAP_SERVER_UPDATE_STATS_OID +1.2.840.113556.1.4.2206, LDAP_SERVER_SEARCH_HINTS_OID +1.2.840.113556.1.4.2211, LDAP_SERVER_EXPECTED_ENTRY_COUNT_OID +1.2.840.113556.1.4.2239, LDAP_SERVER_POLICY_HINTS_OID +1.2.840.113556.1.4.2255, LDAP_SERVER_SET_OWNER_OID +1.2.840.113556.1.4.2256, LDAP_SERVER_BYPASS_QUOTA_OID +1.2.840.113556.4.3, microsoftExcel +1.2.840.113556.4.4, titledWithOID +1.2.840.113556.4.5, microsoftPowerPoint +1.3.133.16.840.9.84, x9-84 +1.3.133.16.840.9.84.0, x9-84-Module +1.3.133.16.840.9.84.0.1, x9-84-Biometrics +1.3.133.16.840.9.84.0.2, x9-84-CMS +1.3.133.16.840.9.84.0.3, x9-84-Identifiers +1.3.133.16.840.9.84.1, biometric +1.3.133.16.840.9.84.1.0, id-unknown-Type +1.3.133.16.840.9.84.1.1, id-body-Odor +1.3.133.16.840.9.84.1.10, id-palm +1.3.133.16.840.9.84.1.11, id-retina +1.3.133.16.840.9.84.1.12, id-signature +1.3.133.16.840.9.84.1.13, id-speech-Pattern +1.3.133.16.840.9.84.1.14, id-thermal-Image +1.3.133.16.840.9.84.1.15, id-vein-Pattern +1.3.133.16.840.9.84.1.16, id-thermal-Face-Image +1.3.133.16.840.9.84.1.17, id-thermal-Hand-Image +1.3.133.16.840.9.84.1.18, id-lip-Movement +1.3.133.16.840.9.84.1.19, id-gait +1.3.133.16.840.9.84.1.2, id-dna +1.3.133.16.840.9.84.1.3, id-ear-Shape +1.3.133.16.840.9.84.1.4, id-facial-Features +1.3.133.16.840.9.84.1.5, id-finger-Image +1.3.133.16.840.9.84.1.6, id-finger-Geometry +1.3.133.16.840.9.84.1.7, id-hand-Geometry +1.3.133.16.840.9.84.1.8, id-iris-Features +1.3.133.16.840.9.84.1.9, id-keystroke-Dynamics +1.3.133.16.840.9.84.2, processing-algorithm +1.3.133.16.840.9.84.3, matching-method +1.3.133.16.840.9.84.4, format-Owner +1.3.133.16.840.9.84.4.0, cbeff-Owner +1.3.133.16.840.9.84.4.1, ibia-Owner +1.3.133.16.840.9.84.4.1.1, id-ibia-SAFLINK +1.3.133.16.840.9.84.4.1.10, id-ibia-SecuGen +1.3.133.16.840.9.84.4.1.11, id-ibia-PreciseBiometric +1.3.133.16.840.9.84.4.1.12, id-ibia-Identix +1.3.133.16.840.9.84.4.1.13, id-ibia-DERMALOG +1.3.133.16.840.9.84.4.1.14, id-ibia-LOGICO +1.3.133.16.840.9.84.4.1.15, id-ibia-NIST +1.3.133.16.840.9.84.4.1.16, id-ibia-A3Vision +1.3.133.16.840.9.84.4.1.17, id-ibia-NEC +1.3.133.16.840.9.84.4.1.18, id-ibia-STMicroelectronics +1.3.133.16.840.9.84.4.1.2, id-ibia-Bioscrypt +1.3.133.16.840.9.84.4.1.3, id-ibia-Visionics +1.3.133.16.840.9.84.4.1.4, id-ibia-InfineonTechnologiesAG +1.3.133.16.840.9.84.4.1.5, id-ibia-IridianTechnologies +1.3.133.16.840.9.84.4.1.6, id-ibia-Veridicom +1.3.133.16.840.9.84.4.1.7, id-ibia-CyberSIGN +1.3.133.16.840.9.84.4.1.8, id-ibia-eCryp. +1.3.133.16.840.9.84.4.1.9, id-ibia-FingerprintCardsAB +1.3.133.16.840.9.84.4.2, x9-Owner +1.3.14.2.26.5, sha +1.3.14.3.2.1.1, rsa +1.3.14.3.2.10, desMAC +1.3.14.3.2.11, rsaSignature +1.3.14.3.2.12, dsa +1.3.14.3.2.13, dsaWithSHA +1.3.14.3.2.14, mdc2WithRSASignature +1.3.14.3.2.15, shaWithRSASignature +1.3.14.3.2.16, dhWithCommonModulus +1.3.14.3.2.17, desEDE +1.3.14.3.2.18, sha +1.3.14.3.2.19, mdc-2 +1.3.14.3.2.2, md4WitRSA +1.3.14.3.2.2.1, sqmod-N +1.3.14.3.2.20, dsaCommon +1.3.14.3.2.21, dsaCommonWithSHA +1.3.14.3.2.22, rsaKeyTransport +1.3.14.3.2.23, keyed-hash-seal +1.3.14.3.2.24, md2WithRSASignature +1.3.14.3.2.25, md5WithRSASignature +1.3.14.3.2.26, sha1 +1.3.14.3.2.27, dsaWithSHA1 +1.3.14.3.2.28, dsaWithCommonSHA1 +1.3.14.3.2.29, sha-1WithRSAEncryption +1.3.14.3.2.3, md5WithRSA +1.3.14.3.2.3.1, sqmod-NwithRSA +1.3.14.3.2.4, md4WithRSAEncryption +1.3.14.3.2.6, desECB +1.3.14.3.2.7, desCBC +1.3.14.3.2.8, desOFB +1.3.14.3.2.9, desCFB +1.3.14.3.3.1, simple-strong-auth-mechanism +1.3.14.7.2.1.1, ElGamal +1.3.14.7.2.3.1, md2WithRSA +1.3.14.7.2.3.2, md2WithElGamal +1.3.36.3, algorithm +1.3.36.3.1, encryptionAlgorithm +1.3.36.3.1.1, des +1.3.36.3.1.1.1.1, desECBPad +1.3.36.3.1.1.1.1.1, desECBPadISO +1.3.36.3.1.1.2.1, desCBCPad +1.3.36.3.1.1.2.1.1, desCBCPadISO +1.3.36.3.1.2, idea +1.3.36.3.1.2.1, ideaECB +1.3.36.3.1.2.1.1, ideaECBPad +1.3.36.3.1.2.1.1.1, ideaECBPadISO +1.3.36.3.1.2.2, ideaCBC +1.3.36.3.1.2.2.1, ideaCBCPad +1.3.36.3.1.2.2.1.1, ideaCBCPadISO +1.3.36.3.1.2.3, ideaOFB +1.3.36.3.1.2.4, ideaCFB +1.3.36.3.1.3, des-3 +1.3.36.3.1.3.1.1, des-3ECBPad +1.3.36.3.1.3.1.1.1, des-3ECBPadISO +1.3.36.3.1.3.2.1, des-3CBCPad +1.3.36.3.1.3.2.1.1, des-3CBCPadISO +1.3.36.3.2, hashAlgorithm +1.3.36.3.2.1, ripemd160 +1.3.36.3.2.2, ripemd128 +1.3.36.3.2.3, ripemd256 +1.3.36.3.2.4, mdc2singleLength +1.3.36.3.2.5, mdc2doubleLength +1.3.36.3.3, signatureAlgorithm +1.3.36.3.3.1, rsa +1.3.36.3.3.1.1, rsaMitSHA-1 +1.3.36.3.3.1.2, rsaMitRIPEMD160 +1.3.36.3.3.2, ellipticCurve +1.3.36.3.4, signatureScheme +1.3.36.3.4.1, iso9796-1 +1.3.36.3.4.2.1, iso9796-2 +1.3.36.3.4.2.2, iso9796-2rsa +1.3.36.4, attribute +1.3.36.5, policy +1.3.36.6, api +1.3.36.6.1, manufacturerSpecific +1.3.36.6.2, functionalitySpecific +1.3.36.7, api +1.3.36.7.1, keyAgreement +1.3.36.7.2, keyTransport +1.3.6.1.4.1.2428.10.1.1, UNINETT policyIdentifier +1.3.6.1.4.1.2712.10, ICE-TEL policyIdentifier +1.3.6.1.4.1.3029.32.1, cryptlibEnvelope +1.3.6.1.4.1.3029.32.2, cryptlibPrivateKey +1.3.6.1.4.1.311, Microsoft OID +1.3.6.1.4.1.311.10.2, nextUpdateLocation +1.3.6.1.4.1.311.2, Authenticode +1.3.6.1.4.1.311.2.1.4, SPC_INDIRECT_DATA_OBJID +1.3.6.1.4.1.311.2.1.10, SPC_SP_AGENCY_INFO_OBJID +1.3.6.1.4.1.311.2.1.11, SPC_STATEMENT_TYPE_OBJID +1.3.6.1.4.1.311.2.1.12, SPC_SP_OPUS_INFO_OBJID +1.3.6.1.4.1.311.2.1.14, SPC_CERT_EXTENSIONS_OBJID +1.3.6.1.4.1.311.2.1.15, SPC_PE_IMAGE_DATA_OBJID +1.3.6.1.4.1.311.2.1.18, SPC_RAW_FILE_DATA_OBJID +1.3.6.1.4.1.311.2.1.19, SPC_STRUCTURED_STORAGE_DATA_OBJID +1.3.6.1.4.1.311.2.1.20, SPC_JAVA_CLASS_DATA_OBJID +1.3.6.1.4.1.311.2.1.21, SPC_INDIVIDUAL_SP_KEY_PURPOSE_OBJID +1.3.6.1.4.1.311.2.1.22, SPC_COMMERCIAL_SP_KEY_PURPOSE_OBJID +1.3.6.1.4.1.311.2.1.25, SPC_CAB_DATA_OBJID +1.3.6.1.4.1.311.2.1.26, SPC_MINIMAL_CRITERIA_OBJID +1.3.6.1.4.1.311.2.1.27, SPC_FINANCIAL_CRITERIA_OBJID +1.3.6.1.4.1.311.2.1.28, SPC_LINK_OBJID +1.3.6.1.4.1.311.2.1.29, SPC_HASH_INFO_OBJID +1.3.6.1.4.1.311.2.1.30, SPC_SIPINFO_OBJID +1.3.6.1.4.1.311.2.2, CTL for Software Publishers Trusted CAs +1.3.6.1.4.1.311.2.2.1, szOID_TRUSTED_CODESIGNING_CA_LIST +1.3.6.1.4.1.311.2.2.2, szOID_TRUSTED_CLIENT_AUTH_CA_LIST +1.3.6.1.4.1.311.2.2.3, szOID_TRUSTED_SERVER_AUTH_CA_LIST +1.3.6.1.4.1.311.3, Time Stamping +1.3.6.1.4.1.311.3.2.1, SPC_TIME_STAMP_REQUEST_OBJID +1.3.6.1.4.1.311.4, Permissions +1.3.6.1.4.1.311.10.3.1, certTrustListSigning +1.3.6.1.4.1.311.10.3.2, timeStampSigning +1.3.6.1.4.1.311.10.3.3, serverGatedCrypto +1.3.6.1.4.1.311.10.3.3.1, szOID_SERIALIZED +1.3.6.1.4.1.311.10.3.4, encryptedFileSystem +1.3.6.1.4.1.311.10.3.4.1, szOID_EFS_RECOVERY +1.3.6.1.4.1.311.10.3.5, szOID_WHQL_CRYPTO +1.3.6.1.4.1.311.10.3.6, szOID_NT5_CRYPTO +1.3.6.1.4.1.311.10.3.7, szOID_OEM_WHQL_CRYPTO +1.3.6.1.4.1.311.10.3.8, szOID_EMBEDDED_NT_CRYPTO +1.3.6.1.4.1.311.10.3.9, szOID_ROOT_LIST_SIGNER +1.3.6.1.4.1.311.10.3.10, szOID_KP_QUALIFIED_SUBORDINATION +1.3.6.1.4.1.311.10.3.11, szOID_KP_KEY_RECOVERY +1.3.6.1.4.1.311.10.3.12, szOID_KP_DOCUMENT_SIGNING +1.3.6.1.4.1.311.10.4.1, yesnoTrustAttr +1.3.6.1.4.1.311.10.5.1, szOID_DRM +1.3.6.1.4.1.311.10.5.2, szOID_DRM_INDIVIDUALIZATION +1.3.6.1.4.1.311.10.6.1, szOID_LICENSES +1.3.6.1.4.1.311.10.6.2, szOID_LICENSE_SERVER +1.3.6.1.4.1.311.10.7, szOID_MICROSOFT_RDN_PREFIX +1.3.6.1.4.1.311.10.7.1, szOID_KEYID_RDN +1.3.6.1.4.1.311.10.8.1, szOID_REMOVE_CERTIFICATE +1.3.6.1.4.1.311.10.9.1, szOID_CROSS_CERT_DIST_POINTS +1.3.6.1.4.1.311.10, Crypto 2.0 +1.3.6.1.4.1.311.10.1, certTrustList +1.3.6.1.4.1.311.10.1.1, szOID_SORTED_CTL +1.3.6.1.4.1.311.10.10, Microsoft CMC OIDs +1.3.6.1.4.1.311.10.10.1, szOID_CMC_ADD_ATTRIBUTES +1.3.6.1.4.1.311.10.11, Microsoft certificate property OIDs +1.3.6.1.4.1.311.10.11.1, szOID_CERT_PROP_ID_PREFIX +1.3.6.1.4.1.311.10.12, CryptUI +1.3.6.1.4.1.311.10.12.1, szOID_ANY_APPLICATION_POLICY +1.3.6.1.4.1.311.12, Catalog +1.3.6.1.4.1.311.12.1.1, szOID_CATALOG_LIST +1.3.6.1.4.1.311.12.1.2, szOID_CATALOG_LIST_MEMBER +1.3.6.1.4.1.311.12.1.3, szOID_CATALOG_LIST_MEMBER_V2 +1.3.6.1.4.1.311.12.2.1, CAT_NAMEVALUE_OBJID +1.3.6.1.4.1.311.12.2.2, CAT_MEMBERINFO_OBJID +1.3.6.1.4.1.311.12.2.3, CAT_MEMBERINFO2_OBJID +1.3.6.1.4.1.311.13, Microsoft PKCS10 OIDs +1.3.6.1.4.1.311.13.1, szOID_RENEWAL_CERTIFICATE +1.3.6.1.4.1.311.13.2.1, szOID_ENROLLMENT_NAME_VALUE_PAIR +1.3.6.1.4.1.311.13.2.2, szOID_ENROLLMENT_CSP_PROVIDER +1.3.6.1.4.1.311.13.2.3, OS Version +1.3.6.1.4.1.311.15, Microsoft Java +1.3.6.1.4.1.311.16, Microsoft Outlook/Exchange +1.3.6.1.4.1.311.16.4, Outlook Express +1.3.6.1.4.1.311.17, Microsoft PKCS12 attributes +1.3.6.1.4.1.311.17.1, szOID_LOCAL_MACHINE_KEYSET +1.3.6.1.4.1.311.18, Microsoft Hydra +1.3.6.1.4.1.311.19, Microsoft ISPU Test +1.3.6.1.4.1.311.20, Microsoft Enrollment Infrastructure +1.3.6.1.4.1.311.20.1, szOID_AUTO_ENROLL_CTL_USAGE +1.3.6.1.4.1.311.20.2, szOID_ENROLL_CERTTYPE_EXTENSION +1.3.6.1.4.1.311.20.2.1, szOID_ENROLLMENT_AGENT +1.3.6.1.4.1.311.20.2.2, szOID_KP_SMARTCARD_LOGON +1.3.6.1.4.1.311.20.2.3, szOID_NT_PRINCIPAL_NAME +1.3.6.1.4.1.311.20.3, szOID_CERT_MANIFOLD +1.3.6.1.4.1.311.21, Microsoft CertSrv Infrastructure +1.3.6.1.4.1.311.21.1, szOID_CERTSRV_CA_VERSION +1.3.6.1.4.1.311.21.20, Client Information +1.3.6.1.4.1.311.25, Microsoft Directory Service +1.3.6.1.4.1.311.25.1, szOID_NTDS_REPLICATION +1.3.6.1.4.1.311.30, IIS +1.3.6.1.4.1.311.31, Windows updates and service packs +1.3.6.1.4.1.311.31.1, szOID_PRODUCT_UPDATE +1.3.6.1.4.1.311.40, Fonts +1.3.6.1.4.1.311.41, Microsoft Licensing and Registration +1.3.6.1.4.1.311.42, Microsoft Corporate PKI (ITG) +1.3.6.1.4.1.311.88, CAPICOM +1.3.6.1.4.1.311.88.1, szOID_CAPICOM_VERSION +1.3.6.1.4.1.311.88.2, szOID_CAPICOM_ATTRIBUTE +1.3.6.1.4.1.311.88.2.1, szOID_CAPICOM_DOCUMENT_NAME +1.3.6.1.4.1.311.88.2.2, szOID_CAPICOM_DOCUMENT_DESCRIPTION +1.3.6.1.4.1.311.88.3, szOID_CAPICOM_ENCRYPTED_DATA +1.3.6.1.4.1.311.88.3.1, szOID_CAPICOM_ENCRYPTED_CONTENT +1.3.6.1.5.5.7, pkix +1.3.6.1.5.5.7.1, privateExtension +1.3.6.1.5.5.7.1.1, authorityInfoAccess +1.3.6.1.5.5.7.12.2, CMC Data +1.3.6.1.5.5.7.2, policyQualifierIds +1.3.6.1.5.5.7.2.1, cps +1.3.6.1.5.5.7.2.2, unotice +1.3.6.1.5.5.7.3, keyPurpose +1.3.6.1.5.5.7.3.1, serverAuth +1.3.6.1.5.5.7.3.2, clientAuth +1.3.6.1.5.5.7.3.3, codeSigning +1.3.6.1.5.5.7.3.4, emailProtection +1.3.6.1.5.5.7.3.5, ipsecEndSystem +1.3.6.1.5.5.7.3.6, ipsecTunnel +1.3.6.1.5.5.7.3.7, ipsecUser +1.3.6.1.5.5.7.3.8, timeStamping +1.3.6.1.5.5.7.4, cmpInformationTypes +1.3.6.1.5.5.7.4.1, caProtEncCert +1.3.6.1.5.5.7.4.2, signKeyPairTypes +1.3.6.1.5.5.7.4.3, encKeyPairTypes +1.3.6.1.5.5.7.4.4, preferredSymmAlg +1.3.6.1.5.5.7.4.5, caKeyUpdateInfo +1.3.6.1.5.5.7.4.6, currentCRL +1.3.6.1.5.5.7.48.1, ocsp +1.3.6.1.5.5.7.48.2, caIssuers +1.3.6.1.5.5.8.1.1, HMAC-MD5 +1.3.6.1.5.5.8.1.2, HMAC-SHA +2.16.840.1.101.2.1.1.1, sdnsSignatureAlgorithm +2.16.840.1.101.2.1.1.10, mosaicKeyManagementAlgorithm +2.16.840.1.101.2.1.1.11, sdnsKMandSigAlgorithm +2.16.840.1.101.2.1.1.12, mosaicKMandSigAlgorithm +2.16.840.1.101.2.1.1.13, SuiteASignatureAlgorithm +2.16.840.1.101.2.1.1.14, SuiteAConfidentialityAlgorithm +2.16.840.1.101.2.1.1.15, SuiteAIntegrityAlgorithm +2.16.840.1.101.2.1.1.16, SuiteATokenProtectionAlgorithm +2.16.840.1.101.2.1.1.17, SuiteAKeyManagementAlgorithm +2.16.840.1.101.2.1.1.18, SuiteAKMandSigAlgorithm +2.16.840.1.101.2.1.1.19, mosaicUpdatedSigAlgorithm +2.16.840.1.101.2.1.1.2, mosaicSignatureAlgorithm +2.16.840.1.101.2.1.1.20, mosaicKMandUpdSigAlgorithms +2.16.840.1.101.2.1.1.21, mosaicUpdatedIntegAlgorithm +2.16.840.1.101.2.1.1.22, mosaicKeyEncryptionAlgorithm +2.16.840.1.101.2.1.1.3, sdnsConfidentialityAlgorithm +2.16.840.1.101.2.1.1.4, mosaicConfidentialityAlgorithm +2.16.840.1.101.2.1.1.5, sdnsIntegrityAlgorithm +2.16.840.1.101.2.1.1.6, mosaicIntegrityAlgorithm +2.16.840.1.101.2.1.1.7, sdnsTokenProtectionAlgorithm +2.16.840.1.101.2.1.1.8, mosaicTokenProtectionAlgorithm +2.16.840.1.101.2.1.1.9, sdnsKeyManagementAlgorithm +2.16.840.1.113730.1, cert-extension +2.16.840.1.113730.1.1, netscape-cert-type +2.16.840.1.113730.1.10, EntityLogo +2.16.840.1.113730.1.11, UserPicture +2.16.840.1.113730.1.12, netscape-ssl-server-name +2.16.840.1.113730.1.13, netscape-comment +2.16.840.1.113730.1.2, netscape-base-url +2.16.840.1.113730.1.3, netscape-revocation-url +2.16.840.1.113730.1.4, netscape-ca-revocation-url +2.16.840.1.113730.1.7, netscape-cert-renewal-url +2.16.840.1.113730.1.8, netscape-ca-policy-url +2.16.840.1.113730.1.9, HomePage-url +2.16.840.1.113730.2, data-type +2.16.840.1.113730.2.1, GIF +2.16.840.1.113730.2.2, JPEG +2.16.840.1.113730.2.3, URL +2.16.840.1.113730.2.4, HTML +2.16.840.1.113730.2.5, netscape-cert-sequence +2.16.840.1.113730.2.6, netscape-cert-url +2.16.840.1.113730.3, LDAPv3 +2.16.840.1.113730.3.4.9, LDAP_CONTROL_VLVREQUEST +2.16.840.1.113730.3.4.10, LDAP_CONTROL_VLVRESPONSE +2.16.840.1.113730.4.1, serverGatedCrypto +2.16.840.1.113733.1.6.3, Unknown Verisign extension +2.16.840.1.113733.1.6.6, Unknown Verisign extension +2.16.840.1.113733.1.7.1.1, Verisign certificatePolicy +2.16.840.1.113733.1.7.1.1.1, Unknown Verisign policy qualifier +2.16.840.1.113733.1.7.1.1.2, Unknown Verisign policy qualifier +2.23.133, TCPA +2.23.133.1, tcpa_specVersion +2.23.133.2, tcpa_attribute +2.23.133.2.1, tcpa_at_tpmManufacturer +2.23.133.2.10, tcpa_at_securityQualities +2.23.133.2.11, tcpa_at_tpmProtectionProfile +2.23.133.2.12, tcpa_at_tpmSecurityTarget +2.23.133.2.13, tcpa_at_foundationProtectionProfile +2.23.133.2.14, tcpa_at_foundationSecurityTarget +2.23.133.2.15, tcpa_at_tpmIdLabel +2.23.133.2.2, tcpa_at_tpmModel +2.23.133.2.3, tcpa_at_tpmVersion +2.23.133.2.4, tcpa_at_platformManufacturer +2.23.133.2.5, tcpa_at_platformModel +2.23.133.2.6, tcpa_at_platformVersion +2.23.133.2.7, tcpa_at_componentManufacturer +2.23.133.2.8, tcpa_at_componentModel +2.23.133.2.9, tcpa_at_componentVersion +2.23.133.3, tcpa_protocol +2.23.133.3.1, tcpa_prtt_tpmIdProtocol +2.23.42.0, contentType +2.23.42.0.0, PANData +2.23.42.0.1, PANToken +2.23.42.0.2, PANOnly +2.23.42.1, msgExt +2.23.42.10, national +2.23.42.10.192, Japan +2.23.42.2, field +2.23.42.2.0, fullName +2.23.42.2.1, givenName +2.23.42.2.10, amount +2.23.42.2.2, familyName +2.23.42.2.3, birthFamilyName +2.23.42.2.4, placeName +2.23.42.2.5, identificationNumber +2.23.42.2.6, month +2.23.42.2.7, date +2.23.42.2.7.11, accountNumber +2.23.42.2.7.12, passPhrase +2.23.42.2.8, address +2.23.42.2.9, telephone +2.23.42.3, attribute +2.23.42.3.0, cert +2.23.42.3.0.0, rootKeyThumb +2.23.42.3.0.1, additionalPolicy +2.23.42.4, algorithm +2.23.42.5, policy +2.23.42.5.0, root +2.23.42.6, module +2.23.42.7, certExt +2.23.42.7.0, hashedRootKey +2.23.42.7.1, certificateType +2.23.42.7.2, merchantData +2.23.42.7.3, cardCertRequired +2.23.42.7.4, tunneling +2.23.42.7.5, setExtensions +2.23.42.7.6, setQualifier +2.23.42.8, brand +2.23.42.8.1, IATA-ATA +2.23.42.8.30, Diners +2.23.42.8.34, AmericanExpress +2.23.42.8.4, VISA +2.23.42.8.5, MasterCard +2.23.42.8.6011, Novus +2.23.42.9, vendor +2.23.42.9.0, GlobeSet +2.23.42.9.1, IBM +2.23.42.9.10, Griffin +2.23.42.9.11, Certicom +2.23.42.9.12, OSS +2.23.42.9.13, TenthMountain +2.23.42.9.14, Antares +2.23.42.9.15, ECC +2.23.42.9.16, Maithean +2.23.42.9.17, Netscape +2.23.42.9.18, Verisign +2.23.42.9.19, BlueMoney +2.23.42.9.2, CyberCash +2.23.42.9.20, Lacerte +2.23.42.9.21, Fujitsu +2.23.42.9.22, eLab +2.23.42.9.23, Entrust +2.23.42.9.24, VIAnet +2.23.42.9.25, III +2.23.42.9.26, OpenMarket +2.23.42.9.27, Lexem +2.23.42.9.28, Intertrader +2.23.42.9.29, Persimmon +2.23.42.9.3, Terisa +2.23.42.9.30, NABLE +2.23.42.9.31, espace-net +2.23.42.9.32, Hitachi +2.23.42.9.33, Microsoft +2.23.42.9.34, NEC +2.23.42.9.35, Mitsubishi +2.23.42.9.36, NCR +2.23.42.9.37, e-COMM +2.23.42.9.38, Gemplus +2.23.42.9.4, RSADSI +2.23.42.9.5, VeriFone +2.23.42.9.6, TrinTech +2.23.42.9.7, BankGate +2.23.42.9.8, GTE +2.23.42.9.9, CompuSource +2.5.29.1, authorityKeyIdentifier +2.5.29.10, basicConstraints +2.5.29.11, nameConstraints +2.5.29.12, policyConstraints +2.5.29.13, basicConstraints +2.5.29.14, subjectKeyIdentifier +2.5.29.15, keyUsage +2.5.29.16, privateKeyUsagePeriod +2.5.29.17, subjectAltName +2.5.29.18, issuerAltName +2.5.29.19, basicConstraints +2.5.29.2, keyAttributes +2.5.29.20, cRLNumber +2.5.29.21, cRLReason +2.5.29.22, expirationDate +2.5.29.23, instructionCode +2.5.29.24, invalidityDate +2.5.29.25, cRLDistributionPoints +2.5.29.26, issuingDistributionPoint +2.5.29.27, deltaCRLIndicator +2.5.29.28, issuingDistributionPoint +2.5.29.29, certificateIssuer +2.5.29.3, certificatePolicies +2.5.29.30, nameConstraints +2.5.29.31, cRLDistributionPoints +2.5.29.32, certificatePolicies +2.5.29.33, policyMappings +2.5.29.34, policyConstraints +2.5.29.35, authorityKeyIdentifier +2.5.29.36, policyConstraints +2.5.29.37, extKeyUsage +2.5.29.4, keyUsageRestriction +2.5.29.5, policyMapping +2.5.29.6, subtreesConstraint +2.5.29.7, subjectAltName +2.5.29.8, issuerAltName +2.5.29.9, subjectDirectoryAttributes +2.5.4.0, objectClass +2.5.4.1, aliasObjectName +2.5.4.10, organizationName +2.5.4.11, organizationalUnitName +2.5.4.12, title +2.5.4.13, description +2.5.4.14, searchGuide +2.5.4.15, businessCategory +2.5.4.16, postalAddress +2.5.4.17, postalCode +2.5.4.18, postOfficeBox +2.5.4.19, physicalDeliveryOfficeName +2.5.4.2, knowledgeInformation +2.5.4.20, telephoneNumber +2.5.4.21, telexNumber +2.5.4.22, teletexTerminalIdentifier +2.5.4.23, facsimileTelephoneNumber +2.5.4.24, x121Address +2.5.4.25, internationalISDNNumber +2.5.4.26, registeredAddress +2.5.4.27, destinationIndicator +2.5.4.28, preferredDeliveryMehtod +2.5.4.29, presentationAddress +2.5.4.3, commonName +2.5.4.30, supportedApplicationContext +2.5.4.31, member +2.5.4.32, owner +2.5.4.33, roleOccupant +2.5.4.34, seeAlso +2.5.4.35, userPassword +2.5.4.36, userCertificate +2.5.4.37, caCertificate +2.5.4.38, authorityRevocationList +2.5.4.39, certificateRevocationList +2.5.4.4, surname +2.5.4.40, crossCertificatePair +2.5.4.41, givenName +2.5.4.42, givenName +2.5.4.5, serialNumber +2.5.4.52, supportedAlgorithms +2.5.4.53, deltaRevocationList +2.5.4.58, crossCertificatePair +2.5.4.6, countryName +2.5.4.7, localityName +2.5.4.8, stateOrProvinceName +2.5.4.9, streetAddress +2.5.8, X.500-Algorithms +2.5.8.1, X.500-Alg-Encryption +2.5.8.1.1, rsa \ No newline at end of file diff --git a/Asn1Editor/Properties/AssemblyInfo.cs b/Asn1Editor/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8a8812d --- /dev/null +++ b/Asn1Editor/Properties/AssemblyInfo.cs @@ -0,0 +1,56 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Asn1Editor")] +[assembly: AssemblyDescription("Grpahic ASN.1 node viewer and editor")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Sysadmins LV")] +[assembly: AssemblyProduct("Asn1Editor")] +[assembly: AssemblyCopyright("Copyright © Sysadmins LV 2014 - 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.3.10.0")] +[assembly: AssemblyFileVersion("1.3.10.0")] +[assembly: GuidAttribute("2b21970c-0f72-4a53-909e-23148c2f7540")] diff --git a/Asn1Editor/Properties/Resources.Designer.cs b/Asn1Editor/Properties/Resources.Designer.cs new file mode 100644 index 0000000..535327d --- /dev/null +++ b/Asn1Editor/Properties/Resources.Designer.cs @@ -0,0 +1,76 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.34014 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Asn1Editor.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // 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", "4.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() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [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("Asn1Editor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Tag: {0} (0x{0:X2}) : {1} + ///Offset: {2} (0x{2:X2}) + ///Length: {3} (0x{3:X2}) + ///Deepness: {4} + ///Path: {5}. + /// + internal static string TagEditorHeaderTemp { + get { + return ResourceManager.GetString("TagEditorHeaderTemp", resourceCulture); + } + } + } +} diff --git a/Asn1Editor/Properties/Resources.resx b/Asn1Editor/Properties/Resources.resx new file mode 100644 index 0000000..12f8a67 --- /dev/null +++ b/Asn1Editor/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Tag: {0} (0x{0:X2}) : {1} +Offset: {2} (0x{2:X2}) +Length: {3} (0x{3:X2}) +Deepness: {4} +Path: {5} + + \ No newline at end of file diff --git a/Asn1Editor/Properties/Settings.Designer.cs b/Asn1Editor/Properties/Settings.Designer.cs new file mode 100644 index 0000000..29533b7 --- /dev/null +++ b/Asn1Editor/Properties/Settings.Designer.cs @@ -0,0 +1,86 @@ +//------------------------------------------------------------------------------ +// +// 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. +// +//------------------------------------------------------------------------------ + +namespace Asn1Editor.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.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; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("150")] + public int MaxTreeViewLength { + get { + return ((int)(this["MaxTreeViewLength"])); + } + set { + this["MaxTreeViewLength"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("12")] + public int FontSize { + get { + return ((int)(this["FontSize"])); + } + set { + this["FontSize"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool DecodePayload { + get { + return ((bool)(this["DecodePayload"])); + } + set { + this["DecodePayload"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool IntAsInt { + get { + return ((bool)(this["IntAsInt"])); + } + set { + this["IntAsInt"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("/")] + public char PathDelimiter { + get { + return ((char)(this["PathDelimiter"])); + } + set { + this["PathDelimiter"] = value; + } + } + } +} diff --git a/Asn1Editor/Properties/Settings.settings b/Asn1Editor/Properties/Settings.settings new file mode 100644 index 0000000..c8e9330 --- /dev/null +++ b/Asn1Editor/Properties/Settings.settings @@ -0,0 +1,21 @@ + + + + + + 150 + + + 12 + + + True + + + True + + + / + + + \ No newline at end of file diff --git a/Asn1Editor/Views/Images/AsnEditor/BIT_STRING.png b/Asn1Editor/Views/Images/AsnEditor/BIT_STRING.png new file mode 100644 index 0000000..8ccf19b Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/BIT_STRING.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/BOOLEAN.png b/Asn1Editor/Views/Images/AsnEditor/BOOLEAN.png new file mode 100644 index 0000000..6f64f61 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/BOOLEAN.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/CONTEXT_SPECIFIC.png b/Asn1Editor/Views/Images/AsnEditor/CONTEXT_SPECIFIC.png new file mode 100644 index 0000000..60e7381 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/CONTEXT_SPECIFIC.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/DateTime.png b/Asn1Editor/Views/Images/AsnEditor/DateTime.png new file mode 100644 index 0000000..c6fc153 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/DateTime.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/ENUMERATED.png b/Asn1Editor/Views/Images/AsnEditor/ENUMERATED.png new file mode 100644 index 0000000..7609f2b Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/ENUMERATED.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/External.png b/Asn1Editor/Views/Images/AsnEditor/External.png new file mode 100644 index 0000000..785a0ba Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/External.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/Integer.png b/Asn1Editor/Views/Images/AsnEditor/Integer.png new file mode 100644 index 0000000..fbf5293 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/Integer.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/NULL.png b/Asn1Editor/Views/Images/AsnEditor/NULL.png new file mode 100644 index 0000000..b51d561 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/NULL.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/OBJECT_IDENTIFIER.png b/Asn1Editor/Views/Images/AsnEditor/OBJECT_IDENTIFIER.png new file mode 100644 index 0000000..2ba1700 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/OBJECT_IDENTIFIER.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/OCTET_STRING.png b/Asn1Editor/Views/Images/AsnEditor/OCTET_STRING.png new file mode 100644 index 0000000..5d5d0fa Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/OCTET_STRING.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/REAL.png b/Asn1Editor/Views/Images/AsnEditor/REAL.png new file mode 100644 index 0000000..60d7bd2 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/REAL.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/Root.png b/Asn1Editor/Views/Images/AsnEditor/Root.png new file mode 100644 index 0000000..4130946 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/Root.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/SEQUENCE.png b/Asn1Editor/Views/Images/AsnEditor/SEQUENCE.png new file mode 100644 index 0000000..4ee6422 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/SEQUENCE.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/SET.png b/Asn1Editor/Views/Images/AsnEditor/SET.png new file mode 100644 index 0000000..7681053 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/SET.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/String.png b/Asn1Editor/Views/Images/AsnEditor/String.png new file mode 100644 index 0000000..dd80c0d Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/String.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/_BOOLEAN.png b/Asn1Editor/Views/Images/AsnEditor/_BOOLEAN.png new file mode 100644 index 0000000..6a5e6d6 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/_BOOLEAN.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/_OBJECT_IDENTIFIER.png b/Asn1Editor/Views/Images/AsnEditor/_OBJECT_IDENTIFIER.png new file mode 100644 index 0000000..c7e70a3 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/_OBJECT_IDENTIFIER.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/_SEQUENCE.png b/Asn1Editor/Views/Images/AsnEditor/_SEQUENCE.png new file mode 100644 index 0000000..c8cf29d Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/_SEQUENCE.png differ diff --git a/Asn1Editor/Views/Images/AsnEditor/_SET.png b/Asn1Editor/Views/Images/AsnEditor/_SET.png new file mode 100644 index 0000000..377c246 Binary files /dev/null and b/Asn1Editor/Views/Images/AsnEditor/_SET.png differ diff --git a/Asn1Editor/Views/Images/Menu/AddressEnabled_32x32.png b/Asn1Editor/Views/Images/Menu/AddressEnabled_32x32.png new file mode 100644 index 0000000..1b8120e Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/AddressEnabled_32x32.png differ diff --git a/Asn1Editor/Views/Images/Menu/AsciiEnabled_32x32.png b/Asn1Editor/Views/Images/Menu/AsciiEnabled_32x32.png new file mode 100644 index 0000000..12e2149 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/AsciiEnabled_32x32.png differ diff --git a/Asn1Editor/Views/Images/Menu/HexFull_32x32.png b/Asn1Editor/Views/Images/Menu/HexFull_32x32.png new file mode 100644 index 0000000..bc2696c Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/HexFull_32x32.png differ diff --git a/Asn1Editor/Views/Images/Menu/ascii_16x16.png b/Asn1Editor/Views/Images/Menu/ascii_16x16.png new file mode 100644 index 0000000..942874e Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/ascii_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/converter_16x16.png b/Asn1Editor/Views/Images/Menu/converter_16x16.png new file mode 100644 index 0000000..dede275 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/converter_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/copy_16x16.png b/Asn1Editor/Views/Images/Menu/copy_16x16.png new file mode 100644 index 0000000..9fbf2ec Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/copy_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/cut_16x16.png b/Asn1Editor/Views/Images/Menu/cut_16x16.png new file mode 100644 index 0000000..2137827 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/cut_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/delete_16x16.png b/Asn1Editor/Views/Images/Menu/delete_16x16.png new file mode 100644 index 0000000..073627b Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/delete_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/edit_16x16.png b/Asn1Editor/Views/Images/Menu/edit_16x16.png new file mode 100644 index 0000000..041e23f Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/edit_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/eraser_16x16.png b/Asn1Editor/Views/Images/Menu/eraser_16x16.png new file mode 100644 index 0000000..a6fb364 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/eraser_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/help_16x16.png b/Asn1Editor/Views/Images/Menu/help_16x16.png new file mode 100644 index 0000000..ff0e6ed Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/help_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/hexview_16x16.png b/Asn1Editor/Views/Images/Menu/hexview_16x16.png new file mode 100644 index 0000000..af7fee4 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/hexview_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/info_16x16.png b/Asn1Editor/Views/Images/Menu/info_16x16.png new file mode 100644 index 0000000..85966f9 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/info_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/insertafter_16x16.png b/Asn1Editor/Views/Images/Menu/insertafter_16x16.png new file mode 100644 index 0000000..475ee25 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/insertafter_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/insertbefore_16x16.png b/Asn1Editor/Views/Images/Menu/insertbefore_16x16.png new file mode 100644 index 0000000..6e86bf5 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/insertbefore_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/insertlast_16x16.png b/Asn1Editor/Views/Images/Menu/insertlast_16x16.png new file mode 100644 index 0000000..4827812 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/insertlast_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/new_16x16.png b/Asn1Editor/Views/Images/Menu/new_16x16.png new file mode 100644 index 0000000..0a7f0ba Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/new_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/newnode_16x16.png b/Asn1Editor/Views/Images/Menu/newnode_16x16.png new file mode 100644 index 0000000..c09089f Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/newnode_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/newnode_32x32.png b/Asn1Editor/Views/Images/Menu/newnode_32x32.png new file mode 100644 index 0000000..48cfcba Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/newnode_32x32.png differ diff --git a/Asn1Editor/Views/Images/Menu/open_16x16.png b/Asn1Editor/Views/Images/Menu/open_16x16.png new file mode 100644 index 0000000..62852df Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/open_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/paste_16x16.png b/Asn1Editor/Views/Images/Menu/paste_16x16.png new file mode 100644 index 0000000..c7d86d3 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/paste_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/print_16x16.png b/Asn1Editor/Views/Images/Menu/print_16x16.png new file mode 100644 index 0000000..ebbcd6a Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/print_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/printpreview_16x16.png b/Asn1Editor/Views/Images/Menu/printpreview_16x16.png new file mode 100644 index 0000000..8ac0586 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/printpreview_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/redo_16x16.png b/Asn1Editor/Views/Images/Menu/redo_16x16.png new file mode 100644 index 0000000..ececc91 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/redo_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/save_16x16.png b/Asn1Editor/Views/Images/Menu/save_16x16.png new file mode 100644 index 0000000..4ab565b Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/save_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/settings_16x16.png b/Asn1Editor/Views/Images/Menu/settings_16x16.png new file mode 100644 index 0000000..ff0d17e Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/settings_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/undo_16x16.png b/Asn1Editor/Views/Images/Menu/undo_16x16.png new file mode 100644 index 0000000..ea1db05 Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/undo_16x16.png differ diff --git a/Asn1Editor/Views/Images/Menu/viewtext_16x16.png b/Asn1Editor/Views/Images/Menu/viewtext_16x16.png new file mode 100644 index 0000000..e6930db Binary files /dev/null and b/Asn1Editor/Views/Images/Menu/viewtext_16x16.png differ diff --git a/Asn1Editor/Views/Images/asnlogo.ico b/Asn1Editor/Views/Images/asnlogo.ico new file mode 100644 index 0000000..2220a74 Binary files /dev/null and b/Asn1Editor/Views/Images/asnlogo.ico differ diff --git a/Asn1Editor/Views/UserControls/AsnTreeView.xaml b/Asn1Editor/Views/UserControls/AsnTreeView.xaml new file mode 100644 index 0000000..c89e171 --- /dev/null +++ b/Asn1Editor/Views/UserControls/AsnTreeView.xaml @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Asn1Editor/Views/UserControls/AsnTreeView.xaml.cs b/Asn1Editor/Views/UserControls/AsnTreeView.xaml.cs new file mode 100644 index 0000000..5bfeb2e --- /dev/null +++ b/Asn1Editor/Views/UserControls/AsnTreeView.xaml.cs @@ -0,0 +1,47 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.ViewModel; +using Asn1Editor.Views.Windows; + +namespace Asn1Editor.Views.UserControls { + /// + /// Interaction logic for AsnTreeView.xaml + /// + public partial class AsnTreeView { + public AsnTreeView() { + InitializeComponent(); + } + + void TreeViewDoubleClick(Object sender, MouseButtonEventArgs e) { + if (tree.SelectedItem == null) { return; } + TagDataEditor dlg = new TagDataEditor(((Asn1TreeNode)tree.SelectedItem).Value); + dlg.ShowDialog(); + } + void OnPreviewMouseRightButtonDown(Object sender, MouseButtonEventArgs e) { + TreeViewItem treeViewItem = VisualUpwardSearch(e.OriginalSource as DependencyObject); + if (treeViewItem != null) { + treeViewItem.Focus(); + e.Handled = true; + } + } + void TreeViewSelectedItemChanged(Object sender, RoutedPropertyChangedEventArgs e) { + if (e.NewValue == null) { return; } + ((MainWindowVM)DataContext).SelectedTreeNode = (Asn1TreeNode)e.NewValue; + } + void Tree_OnDrop(Object sender, DragEventArgs e) { + String[] file = (String[])e.Data.GetData(DataFormats.FileDrop, true); + ((MainWindowVM)DataContext).DropFile(file[0]); + } + + static TreeViewItem VisualUpwardSearch(DependencyObject source) { + while (source != null && !(source is TreeViewItem)) { + source = VisualTreeHelper.GetParent(source); + } + return (TreeViewItem)source; + } + } +} diff --git a/Asn1Editor/Views/UserControls/BusyIndicator.xaml b/Asn1Editor/Views/UserControls/BusyIndicator.xaml new file mode 100644 index 0000000..046d2cd --- /dev/null +++ b/Asn1Editor/Views/UserControls/BusyIndicator.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + diff --git a/Asn1Editor/Views/UserControls/BusyIndicator.xaml.cs b/Asn1Editor/Views/UserControls/BusyIndicator.xaml.cs new file mode 100644 index 0000000..76572db --- /dev/null +++ b/Asn1Editor/Views/UserControls/BusyIndicator.xaml.cs @@ -0,0 +1,18 @@ +using System; +using System.Windows; + +namespace Asn1Editor.Views.UserControls { + /// + /// Interaction logic for BusyIndicator.xaml + /// + public partial class BusyIndicator { + public BusyIndicator() { + InitializeComponent(); + IsVisibleChanged += OnIsVisibleChanged; + } + + void OnIsVisibleChanged(Object Sender, DependencyPropertyChangedEventArgs e) { + pb.IsIndeterminate = (Boolean)e.NewValue; + } + } +} diff --git a/Asn1Editor/Views/UserControls/HexViewerUC.xaml b/Asn1Editor/Views/UserControls/HexViewerUC.xaml new file mode 100644 index 0000000..7507db0 --- /dev/null +++ b/Asn1Editor/Views/UserControls/HexViewerUC.xaml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Asn1Editor/Views/UserControls/HexViewerUC.xaml.cs b/Asn1Editor/Views/UserControls/HexViewerUC.xaml.cs new file mode 100644 index 0000000..29636ca --- /dev/null +++ b/Asn1Editor/Views/UserControls/HexViewerUC.xaml.cs @@ -0,0 +1,29 @@ +using System; +using System.Windows; +using System.Windows.Documents; +using Asn1Editor.API.ModelObjects; +using Asn1Editor.API.Utils; +using Asn1Editor.API.ViewModel; + +namespace Asn1Editor.Views.UserControls { + /// + /// Interaction logic for HexViewerUC.xaml + /// + partial class HexViewerUC : IHexView { + TextRange[] ranges; + public HexViewerUC() { + InitializeComponent(); + ranges = new TextRange[3]; + } + + void HexViewerUC_OnLoaded(Object sender, RoutedEventArgs e) { + ((MainWindowVM)DataContext).HexViewerContext.View = this; + } + + public void SelectHexView(Asn1Lite treeNode) { + TextUtility.ResetColors(ranges); + ranges = TextUtility.GetTextPointers(treeNode, hexTextBox, Scroller); + TextUtility.Colorize(ranges); + } + } +} diff --git a/Asn1Editor/Views/Windows/AboutBox.xaml b/Asn1Editor/Views/Windows/AboutBox.xaml new file mode 100644 index 0000000..813aa07 --- /dev/null +++ b/Asn1Editor/Views/Windows/AboutBox.xaml @@ -0,0 +1,81 @@ + + + + + + More Info + + + + + + + + + + + + + + + + + + diff --git a/Asn1Editor/Views/Windows/MainWindow.xaml.cs b/Asn1Editor/Views/Windows/MainWindow.xaml.cs new file mode 100644 index 0000000..f524260 --- /dev/null +++ b/Asn1Editor/Views/Windows/MainWindow.xaml.cs @@ -0,0 +1,22 @@ +using System; +using System.ComponentModel; +using System.Windows; +using Asn1Editor.API.ViewModel; + +namespace Asn1Editor.Views.Windows { + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow { + public MainWindow() { + InitializeComponent(); + } + + void CloseClick(Object sender, RoutedEventArgs e) { + Close(); + } + void OnClosing(Object sender, CancelEventArgs e) { + StaticCommands.ClearResources(); + } + } +} diff --git a/Asn1Editor/Views/Windows/SettingsWnd.xaml b/Asn1Editor/Views/Windows/SettingsWnd.xaml new file mode 100644 index 0000000..7c6910b --- /dev/null +++ b/Asn1Editor/Views/Windows/SettingsWnd.xaml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + 8 + + + 9 + + + 10 + + + 11 + + + 12 + + + 14 + + + 16 + + + 18 + + + + + + + + + + + + + + + + + + + + + + +