From 8d25e9baca269e4455b14e4f6e5cf7222eb8c96d Mon Sep 17 00:00:00 2001 From: Aptivi CEO Date: Mon, 1 Apr 2024 16:21:56 +0300 Subject: [PATCH] add - doc - Added key info --- We've added key information --- Type: add Breaking: False Doc Required: True Part: 1/1 --- .../TestFiles/fourVCard3.vcf | 25 +++- .../TestFiles/fourVCard4.vcf | 4 + VisualCard/Parsers/VcardConstants.cs | 1 + VisualCard/Parsers/VcardParserTools.cs | 5 + VisualCard/Parts/Enums/PartsArrayEnum.cs | 4 + VisualCard/Parts/Implementations/KeyInfo.cs | 141 ++++++++++++++++++ 6 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 VisualCard/Parts/Implementations/KeyInfo.cs diff --git a/VisualCard.ShowContacts/TestFiles/fourVCard3.vcf b/VisualCard.ShowContacts/TestFiles/fourVCard3.vcf index 1486a74..5a6d10c 100644 --- a/VisualCard.ShowContacts/TestFiles/fourVCard3.vcf +++ b/VisualCard.ShowContacts/TestFiles/fourVCard3.vcf @@ -42,9 +42,28 @@ ADR;TYPE=home:;;Street Address;;;; ORG:Organization TITLE:Title NOTE:Notes -X-AIM;HOME:IM -X-MSN;HOME:Windows LIVE -X-YAHOO;HOME:Yahoo +X-AIM;TYPE=HOME:IM +X-MSN;TYPE=HOME:Windows LIVE +X-YAHOO;TYPE=HOME:Yahoo +KEY:http://www.example.com/keys/jdoe.cer +KEY;MEDIATYPE=application/pgp-keys:ftp://example.com/keys/jdoe +KEY:data:application/pgp-keys;base64,MIICajCCAdOgAwIBAgICBE + UwDQYJKoZIhvcNAQEEBQAwdzELMAkGA1UEBhMCVVMxLDAqBgNVBAoTI05l +KEY;ENCODING=b:MIICajCCAdOgAwIBAgICBEUwDQYJKoZIhvcNAQEEBQA + wdzELMAkGA1UEBhMCVVMxLDAqBgNVBAoTI05ldHNjYXBlIENbW11bmljYX + Rpb25zIENvcnBvcmF0aW9uMRwwGgYDVQQLExNJbmZvcm1hdGlvbiBTeXN0 + ZW1zMRwwGgYDVQQDExNyb290Y2EubmV0c2NhcGUuY29tMB4XDTk3MDYwNj + E5NDc1OVoXDTk3MTIwMzE5NDc1OVowgYkxCzAJBgNVBAYTAlVTMSYwJAYD + VQQKEx1OZXRzY2FwZSBDb21tdW5pY2F0aW9ucyBDb3JwLjEYMBYGA1UEAx + MPVGltb3RoeSBBIEhvd2VzMSEwHwYJKoZIhvcNAQkBFhJob3dlc0BuZXRz + Y2FwZS5jb20xFTATBgoJkiaJk/IsZAEBEwVob3dlczBcMA0GCSqGSIb3DQ + EBAQUAA0sAMEgCQQC0JZf6wkg8pLMXHHCUvMfL5H6zjSk4vTTXZpYyrdN2 + dXcoX49LKiOmgeJSzoiFKHtLOIboyludF90CgqcxtwKnAgMBAAGjNjA0MB + EGCWCGSAGG+EIBAQQEAwIAoDAfBgNVHSMEGDAWgBT84FToB/GV3jr3mcau + +hUMbsQukjANBgkqhkiG9w0BAQQFAAOBgQBexv7o7mi3PLXadkmNP9LcIP + mx93HGp0Kgyx1jIVMyNgsemeAwBM+MSlhMfcpbTrONwNjZYW8vJDSoi//y + rZlVt9bJbs7MNYZVsyF1unsqaln4/vy6Uawfg8VUMk1U7jt8LYpo4YULU7 + UZHPYVUaSgVttImOHZIKi4hlPXBOhcUQ== END:VCARD BEGIN:VCARD VERSION:3.0 diff --git a/VisualCard.ShowContacts/TestFiles/fourVCard4.vcf b/VisualCard.ShowContacts/TestFiles/fourVCard4.vcf index ad15ed4..bbfc8a8 100644 --- a/VisualCard.ShowContacts/TestFiles/fourVCard4.vcf +++ b/VisualCard.ShowContacts/TestFiles/fourVCard4.vcf @@ -74,4 +74,8 @@ FN:VCardTest N:VCardTest;;;; TEL;TYPE=work:1091090902 TEL;TYPE=home:1092222222 +KEY:http://www.example.com/keys/jdoe.cer +KEY;MEDIATYPE=application/pgp-keys:ftp://example.com/keys/jdoe +KEY:data:application/pgp-keys;base64,MIICajCCAdOgAwIBAgICBE + UwDQYJKoZIhvcNAQEEBQAwdzELMAkGA1UEBhMCVVMxLDAqBgNVBAoTI05l END:VCARD diff --git a/VisualCard/Parsers/VcardConstants.cs b/VisualCard/Parsers/VcardConstants.cs index 800b861..e89c44e 100644 --- a/VisualCard/Parsers/VcardConstants.cs +++ b/VisualCard/Parsers/VcardConstants.cs @@ -60,6 +60,7 @@ internal static class VcardConstants internal const string _calUriSpecifier = "CALURI"; internal const string _caladrUriSpecifier = "CALADRURI"; internal const string _categoriesSpecifier = "CATEGORIES"; + internal const string _keySpecifier = "KEY"; internal const string _xSpecifier = "X-"; internal const string _typeArgumentSpecifier = "TYPE="; internal const string _valueArgumentSpecifier = "VALUE="; diff --git a/VisualCard/Parsers/VcardParserTools.cs b/VisualCard/Parsers/VcardParserTools.cs index 20671e3..21c25d3 100644 --- a/VisualCard/Parsers/VcardParserTools.cs +++ b/VisualCard/Parsers/VcardParserTools.cs @@ -115,6 +115,7 @@ internal static bool EnumArrayTypeSupported(PartsArrayEnum partsArrayEnum, Versi PartsArrayEnum.Geo => true, PartsArrayEnum.Sounds => true, PartsArrayEnum.Categories => true, + PartsArrayEnum.Key => true, PartsArrayEnum.NonstandardNames => true, PartsArrayEnum.Impps => cardVersion.Major >= 3, PartsArrayEnum.Nicknames => cardVersion.Major >= 3, @@ -189,6 +190,7 @@ internal static string GetPrefixFromPartsArrayEnum(PartsArrayEnum partsArrayEnum PartsArrayEnum.Categories => VcardConstants._categoriesSpecifier, PartsArrayEnum.Langs => VcardConstants._langSpecifier, PartsArrayEnum.Xml => VcardConstants._xmlSpecifier, + PartsArrayEnum.Key => VcardConstants._keySpecifier, PartsArrayEnum.NonstandardNames => VcardConstants._xSpecifier, _ => throw new NotImplementedException($"String enumeration {partsArrayEnum} is not implemented.") @@ -255,6 +257,8 @@ internal static PartsArrayEnum GetPartsArrayEnumFromType(Type partsArrayType) return PartsArrayEnum.Langs; else if (partsArrayType == typeof(XmlInfo)) return PartsArrayEnum.Xml; + else if (partsArrayType == typeof(KeyInfo)) + return PartsArrayEnum.Key; else if (partsArrayType == typeof(XNameInfo)) return PartsArrayEnum.NonstandardNames; throw new NotImplementedException($"Type {partsArrayType.Name} doesn't represent any part array."); @@ -282,6 +286,7 @@ internal static (PartType type, object enumeration, Type enumType, Func (PartType.PartsArray, PartsArrayEnum.Categories, typeof(CategoryInfo), CategoryInfo.FromStringVcardStatic, "", ""), VcardConstants._langSpecifier => (PartType.PartsArray, PartsArrayEnum.Langs, typeof(LangInfo), LangInfo.FromStringVcardStatic, "HOME", ""), VcardConstants._xmlSpecifier => (PartType.PartsArray, PartsArrayEnum.Xml, typeof(XmlInfo), XmlInfo.FromStringVcardStatic, "", ""), + VcardConstants._keySpecifier => (PartType.PartsArray, PartsArrayEnum.Key, typeof(KeyInfo), KeyInfo.FromStringVcardStatic, "", ""), VcardConstants._xSpecifier => (PartType.PartsArray, PartsArrayEnum.NonstandardNames, typeof(XNameInfo), XNameInfo.FromStringVcardStatic, "", ""), VcardConstants._revSpecifier => (PartType.Parts, PartsEnum.Revision, typeof(RevisionInfo), RevisionInfo.FromStringVcardStatic, "", ""), VcardConstants._birthSpecifier => (PartType.Parts, PartsEnum.Birthdate, typeof(BirthDateInfo), BirthDateInfo.FromStringVcardStatic, "", ""), diff --git a/VisualCard/Parts/Enums/PartsArrayEnum.cs b/VisualCard/Parts/Enums/PartsArrayEnum.cs index ba813f8..00d0a48 100644 --- a/VisualCard/Parts/Enums/PartsArrayEnum.cs +++ b/VisualCard/Parts/Enums/PartsArrayEnum.cs @@ -101,6 +101,10 @@ public enum PartsArrayEnum /// Xml, /// + /// The contact's key URL or embedded PGP key + /// + Key, + /// /// The contact's extended options (usually starts with X-SOMETHING:Value1;Value2...) /// NonstandardNames, diff --git a/VisualCard/Parts/Implementations/KeyInfo.cs b/VisualCard/Parts/Implementations/KeyInfo.cs new file mode 100644 index 0000000..b4d8464 --- /dev/null +++ b/VisualCard/Parts/Implementations/KeyInfo.cs @@ -0,0 +1,141 @@ +// +// VisualCard Copyright (C) 2021-2024 Aptivi +// +// This file is part of VisualCard +// +// VisualCard is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// VisualCard is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY, without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using VisualCard.Parsers; + +namespace VisualCard.Parts.Implementations +{ + /// + /// Contact key info + /// + [DebuggerDisplay("Key, {Encoding}, {KeyType}, {ValueType}")] + public class KeyInfo : BaseCardPartInfo, IEquatable + { + /// + /// Key encoding type + /// + public string Encoding { get; } + /// + /// Encoded key + /// + public string KeyEncoded { get; } + + internal static BaseCardPartInfo FromStringVcardStatic(string value, string[] finalArgs, int altId, string[] elementTypes, string valueType, Version cardVersion) => + new KeyInfo().FromStringVcardInternal(value, finalArgs, altId, elementTypes, valueType, cardVersion); + + internal override string ToStringVcardInternal(Version cardVersion) => + KeyEncoded; + + internal override BaseCardPartInfo FromStringVcardInternal(string value, string[] finalArgs, int altId, string[] elementTypes, string valueType, Version cardVersion) + { + bool vCard4 = cardVersion.Major >= 4; + + // Check to see if the value is prepended by the ENCODING= argument + string keyEncoding = ""; + if (vCard4) + { + // We're on a vCard 4.0 contact that contains this information + if (!Uri.TryCreate(value, UriKind.Absolute, out Uri uri)) + throw new InvalidDataException($"URL {value} is invalid"); + value = uri.ToString(); + } + else + { + // vCard 3.0 handles this in a different way + keyEncoding = VcardParserTools.GetValuesString(finalArgs, "b", VcardConstants._encodingArgumentSpecifier); + if (!keyEncoding.Equals("b", StringComparison.OrdinalIgnoreCase)) + { + // Since we don't need embedded keys, we need to check a URL. + if (!Uri.TryCreate(value, UriKind.Absolute, out Uri uri)) + throw new InvalidDataException($"URL {value} is invalid"); + value = uri.ToString(); + } + } + + // Populate the fields + KeyInfo _key = new(vCard4 ? altId : 0, finalArgs, elementTypes, valueType, keyEncoding, value); + return _key; + } + + /// + public override bool Equals(object obj) => + Equals((KeyInfo)obj); + + /// + /// Checks to see if both the parts are equal + /// + /// The target instance to check to see if they equal + /// True if all the part elements are equal. Otherwise, false. + public bool Equals(KeyInfo other) => + Equals(this, other); + + /// + /// Checks to see if both the parts are equal + /// + /// The source instance to check to see if they equal + /// The target instance to check to see if they equal + /// True if all the part elements are equal. Otherwise, false. + public bool Equals(KeyInfo source, KeyInfo target) + { + // We can't perform this operation on null. + if (source is null || target is null) + return false; + + // Check all the properties + return + source.Encoding == target.Encoding && + source.KeyEncoded == target.KeyEncoded + ; + } + + /// + public override int GetHashCode() + { + int hashCode = 2051368178; + hashCode = hashCode * -1521134295 + base.GetHashCode(); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(Encoding); + hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(KeyEncoded); + return hashCode; + } + + /// + public static bool operator ==(KeyInfo left, KeyInfo right) => + left.Equals(right); + + /// + public static bool operator !=(KeyInfo left, KeyInfo right) => + !(left == right); + + internal override bool EqualsInternal(BaseCardPartInfo source, BaseCardPartInfo target) => + ((KeyInfo)source) == ((KeyInfo)target); + + internal KeyInfo() { } + + internal KeyInfo(int altId, string[] arguments, string[] elementTypes, string valueType, string encoding, string keyEncoded) : + base(arguments, altId, elementTypes, valueType) + { + Encoding = encoding; + KeyEncoded = keyEncoded; + } + } +}