diff --git a/dotAPNS/ApnsClient.cs b/dotAPNS/ApnsClient.cs index f9fac7a..2e507d8 100644 --- a/dotAPNS/ApnsClient.cs +++ b/dotAPNS/ApnsClient.cs @@ -43,6 +43,12 @@ public class ApnsClient : IApnsClient internal const string DevelopmentEndpoint = "https://api.sandbox.push.apple.com"; internal const string ProductionEndpoint = "https://api.push.apple.com"; + // UserId could be defined with all these forms + // - https://oidref.com/0.9.2342.19200300.100.1.1 + // - On Linux .NET Core cert.Subject prints `userId=xxx` instead of `0.9.2342.19200300.100.1.1=xxx` + // - `uid=xxx` instead of `0.9.2342.19200300.100.1.1=xxx` + private static readonly string[] CertificateSubjectUserIdSplit = ["0.9.2342.19200300.100.1.1=", "userId=", "uid="]; + #if NET46 readonly CngKey _key; #else @@ -72,30 +78,27 @@ public class ApnsClient : IApnsClient ApnsClient(HttpClient http, [NotNull] X509Certificate cert) { _http = http; - var split = cert.Subject.Split(new[] { "0.9.2342.19200300.100.1.1=" }, StringSplitOptions.RemoveEmptyEntries); - if (split.Length != 2) - { - // On Linux .NET Core cert.Subject prints `userId=xxx` instead of `0.9.2342.19200300.100.1.1=xxx` - split = cert.Subject.Split(new[] { "userId=" }, StringSplitOptions.RemoveEmptyEntries); - } - if (split.Length != 2) - { - // if subject prints `uid=xxx` instead of `0.9.2342.19200300.100.1.1=xxx` - split = cert.Subject.Split(new[] { "uid=" }, StringSplitOptions.RemoveEmptyEntries); - } + _useCert = true; + GetCertificateInfo(cert, out _certTopic, out _isVoipCert, out _bundleId); + } + + public static void GetCertificateInfo(X509Certificate certificate, out string topic, out bool isVoipCert, out string bundleId) + { + string[] split = certificate.Subject.Split(CertificateSubjectUserIdSplit, StringSplitOptions.RemoveEmptyEntries); if (split.Length != 2) + { throw new InvalidOperationException("Provided certificate does not appear to be a valid APNs certificate."); + } - string topic = split[1]; - _certTopic = topic; - _isVoipCert = topic.EndsWith(".voip"); - _bundleId = split[1].Replace(".voip", ""); - _useCert = true; + topic = split[1]; + var indexOfVoip = topic.LastIndexOf(".voip", StringComparison.Ordinal); + isVoipCert = indexOfVoip > -1; + bundleId = !isVoipCert ? topic : topic.Substring(0, indexOfVoip); } ApnsClient([NotNull] HttpClient http, [NotNull] -#if NET46 +#if NET46 CngKey #else ECDsa diff --git a/dotAPNS/dotAPNS.csproj b/dotAPNS/dotAPNS.csproj index b5a2a98..9d250e2 100644 --- a/dotAPNS/dotAPNS.csproj +++ b/dotAPNS/dotAPNS.csproj @@ -4,10 +4,11 @@ net46;netstandard2.0;netstandard2.1 alexalok dotAPNS is a library used to send push notifications to Apple devices using Apple Push Notification service. - 4.4.1 + 4.5.0 © alexalok 2019-2024 - * Unpinned System.Net.Http.WinHttpHandler version + * Minor perf improvements (#131) + * Allow getting APNs certificate information externally (#131) https://github.com/alexalok/dotAPNS https://github.com/alexalok/dotAPNS