From 7a82b22ff443f5f123b4525a05b6c4a5c0eeb03a Mon Sep 17 00:00:00 2001 From: lay295 Date: Mon, 25 Sep 2023 02:39:45 -0500 Subject: [PATCH 01/37] Limited VOD + Clip + Chat Download support for desktop app --- .../Modes/Arguments/ClipDownloadArgs.cs | 2 + .../Modes/Arguments/CurlArgs.cs | 21 + TwitchDownloaderCLI/Modes/DownloadChat.cs | 8 +- TwitchDownloaderCLI/Modes/DownloadClip.cs | 20 +- TwitchDownloaderCLI/Modes/DownloadVideo.cs | 7 +- TwitchDownloaderCLI/Program.cs | 4 +- .../Properties/launchSettings.json | 2 +- TwitchDownloaderCLI/Tools/CurlHandler.cs | 70 + .../TwitchDownloaderCLI.csproj | 1 + TwitchDownloaderCore/Chat/ChatHtml.cs | 2 +- TwitchDownloaderCore/Chat/ChatJson.cs | 2 +- TwitchDownloaderCore/Chat/ChatText.cs | 2 +- TwitchDownloaderCore/ChatRenderer.cs | 2 +- TwitchDownloaderCore/ChatUpdater.cs | 7 +- .../Options/ChatDownloadOptions.cs | 9 + .../Options/ClipDownloadOptions.cs | 5 +- .../Options/VideoDownloadOptions.cs | 7 +- TwitchDownloaderCore/PlatformHelper.cs | 53 + TwitchDownloaderCore/Tools/CommentTools.cs | 2 +- TwitchDownloaderCore/Tools/CurlImpersonate.cs | 47 + TwitchDownloaderCore/Tools/DownloadTools.cs | 494 +++ TwitchDownloaderCore/Tools/DriveHelper.cs | 33 + TwitchDownloaderCore/Tools/FfmpegMetadata.cs | 2 +- TwitchDownloaderCore/Tools/HighlightIcons.cs | 2 +- TwitchDownloaderCore/Tools/UrlParse.cs | 73 + .../TwitchDownloaderCore.csproj | 1 + .../TwitchObjects/StvEmoteFlags.cs | 21 - TwitchDownloaderCore/VideoDownloader.cs | 707 ---- .../Interfaces/ChatDownloaderFactory.cs | 37 + .../Interfaces/ClipDownloaderFactory.cs | 37 + .../Interfaces/IChatDownloader.cs | 14 + .../Interfaces/IClipDownloader.cs | 10 + .../Interfaces/IVideoDownloader.cs | 14 + .../VideoPlatforms/Interfaces/IVideoInfo.cs | 18 + .../Interfaces/VideoDownloaderFactory.cs | 37 + .../VideoPlatforms/Interfaces/VideoQuality.cs | 16 + .../Kick/Downloaders/KickChatDownloader.cs | 409 ++ .../Kick/Downloaders/KickClipDownloader.cs | 153 + .../Kick/Downloaders/KickVideoDownloader.cs | 181 + .../VideoPlatforms/Kick/KickChatResponse.cs | 54 + .../VideoPlatforms/Kick/KickClipResponse.cs | 86 + .../VideoPlatforms/Kick/KickClipSegment.cs | 9 + .../VideoPlatforms/Kick/KickHelper.cs | 127 + .../VideoPlatforms/Kick/KickVideoResponse.cs | 122 + .../Twitch}/Api/BTTVChannelEmoteResponse.cs | 2 +- .../Twitch}/Api/FFZEmote.cs | 2 +- .../Twitch}/Api/STVChannelEmoteResponse.cs | 2 +- .../Twitch}/Api/STVGlobalEmoteResponse.cs | 2 +- .../Twitch}/ChatBadge.cs | 6 +- .../Twitch}/ChatRoot.cs | 8 +- .../Twitch}/ChatRootInfo.cs | 8 +- .../Twitch}/CheerEmote.cs | 6 +- .../Twitch}/CommentSection.cs | 2 +- .../Downloaders/TwitchChatDownloader.cs} | 34 +- .../Downloaders/TwitchClipDownloader.cs} | 35 +- .../Downloaders/TwitchVideoDownloader.cs | 230 ++ .../Twitch}/EmoteResponse.cs | 2 +- .../Twitch}/EmoteResponseItem.cs | 2 +- .../Twitch}/GifEmote.cs | 2 +- .../Twitch}/Gql/GqlBadgeResponse.cs | 2 +- .../Twitch}/Gql/GqlCheerResponse.cs | 2 +- .../Twitch}/Gql/GqlClipResponse.cs | 15 +- .../Twitch}/Gql/GqlClipSearchResponse.cs | 2 +- .../Twitch}/Gql/GqlClipTokenResponse.cs | 6 +- .../Twitch}/Gql/GqlCommentResponse.cs | 2 +- .../Twitch}/Gql/GqlUserInfoResponse.cs | 2 +- .../Twitch}/Gql/GqlVideoChapterResponse.cs | 2 +- .../Twitch}/Gql/GqlVideoResponse.cs | 23 +- .../Twitch}/Gql/GqlVideoSearchResponse.cs | 2 +- .../Twitch}/Gql/GqlVideoTokenResponse.cs | 2 +- .../VideoPlatforms/Twitch/StvEmoteFlags.cs | 21 + .../Twitch}/TwitchComment.cs | 2 +- .../Twitch}/TwitchEmote.cs | 6 +- .../Twitch}/TwitchHelper.cs | 106 +- .../Twitch}/UpdateFrame.cs | 2 +- .../Curl-Impersonate/curl-ca-bundle.crt | 3372 +++++++++++++++++ .../Curl-Impersonate/libcurl.a | Bin 0 -> 998618 bytes .../Curl-Impersonate/libcurl.dll | Bin 0 -> 4563456 bytes .../Curl-Impersonate/libcurldll.a | Bin 0 -> 58418 bytes TwitchDownloaderWPF/MainWindow.xaml.cs | 10 + TwitchDownloaderWPF/PageChatDownload.xaml.cs | 84 +- TwitchDownloaderWPF/PageChatRender.xaml.cs | 2 +- TwitchDownloaderWPF/PageChatUpdate.xaml.cs | 4 +- TwitchDownloaderWPF/PageClipDownload.xaml.cs | 60 +- TwitchDownloaderWPF/PageVodDownload.xaml.cs | 80 +- .../TwitchDownloaderWPF.csproj | 28 +- .../TwitchTasks/ChatDownloadTask.cs | 5 +- .../TwitchTasks/ClipDownloadTask.cs | 3 +- .../TwitchTasks/VodDownloadTask.cs | 3 +- .../WindowMassDownload.xaml.cs | 4 +- .../WindowQueueOptions.xaml.cs | 2 +- TwitchDownloaderWPF/WindowUrlList.xaml.cs | 4 +- 92 files changed, 6129 insertions(+), 1002 deletions(-) create mode 100644 TwitchDownloaderCLI/Modes/Arguments/CurlArgs.cs create mode 100644 TwitchDownloaderCLI/Tools/CurlHandler.cs create mode 100644 TwitchDownloaderCore/PlatformHelper.cs create mode 100644 TwitchDownloaderCore/Tools/CurlImpersonate.cs create mode 100644 TwitchDownloaderCore/Tools/DownloadTools.cs create mode 100644 TwitchDownloaderCore/Tools/UrlParse.cs delete mode 100644 TwitchDownloaderCore/TwitchObjects/StvEmoteFlags.cs delete mode 100644 TwitchDownloaderCore/VideoDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/ChatDownloaderFactory.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/ClipDownloaderFactory.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/IChatDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/IClipDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoInfo.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoDownloaderFactory.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoQuality.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickChatDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickClipDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickVideoDownloader.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/KickChatResponse.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/KickClipResponse.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/KickClipSegment.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/KickHelper.cs create mode 100644 TwitchDownloaderCore/VideoPlatforms/Kick/KickVideoResponse.cs rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Api/BTTVChannelEmoteResponse.cs (93%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Api/FFZEmote.cs (93%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Api/STVChannelEmoteResponse.cs (97%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Api/STVGlobalEmoteResponse.cs (97%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/ChatBadge.cs (96%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/ChatRoot.cs (97%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/ChatRootInfo.cs (95%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/CheerEmote.cs (93%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/CommentSection.cs (87%) rename TwitchDownloaderCore/{ChatDownloader.cs => VideoPlatforms/Twitch/Downloaders/TwitchChatDownloader.cs} (93%) rename TwitchDownloaderCore/{ClipDownloader.cs => VideoPlatforms/Twitch/Downloaders/TwitchClipDownloader.cs} (72%) create mode 100644 TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchVideoDownloader.cs rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/EmoteResponse.cs (87%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/EmoteResponseItem.cs (87%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/GifEmote.cs (97%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlBadgeResponse.cs (95%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlCheerResponse.cs (94%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlClipResponse.cs (55%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlClipSearchResponse.cs (95%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlClipTokenResponse.cs (85%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlCommentResponse.cs (98%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlUserInfoResponse.cs (92%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlVideoChapterResponse.cs (96%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlVideoResponse.cs (53%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlVideoSearchResponse.cs (96%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/Gql/GqlVideoTokenResponse.cs (91%) create mode 100644 TwitchDownloaderCore/VideoPlatforms/Twitch/StvEmoteFlags.cs rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/TwitchComment.cs (88%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/TwitchEmote.cs (97%) rename TwitchDownloaderCore/{ => VideoPlatforms/Twitch}/TwitchHelper.cs (90%) rename TwitchDownloaderCore/{TwitchObjects => VideoPlatforms/Twitch}/UpdateFrame.cs (87%) create mode 100644 TwitchDownloaderWPF/Curl-Impersonate/curl-ca-bundle.crt create mode 100644 TwitchDownloaderWPF/Curl-Impersonate/libcurl.a create mode 100644 TwitchDownloaderWPF/Curl-Impersonate/libcurl.dll create mode 100644 TwitchDownloaderWPF/Curl-Impersonate/libcurldll.a diff --git a/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs b/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs index ec06dd27..b34c69da 100644 --- a/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs +++ b/TwitchDownloaderCLI/Modes/Arguments/ClipDownloadArgs.cs @@ -23,6 +23,8 @@ public class ClipDownloadArgs : ITwitchDownloaderArgs [Option("ffmpeg-path", HelpText = "Path to FFmpeg executable.")] public string FfmpegPath { get; set; } + [Option("curl-path", HelpText = "Path to curl-impersonate executable.")] + public string CurlImpersonatePath { get; set; } [Option("temp-path", Default = "", HelpText = "Path to temporary caching folder.")] public string TempFolder { get; set; } diff --git a/TwitchDownloaderCLI/Modes/Arguments/CurlArgs.cs b/TwitchDownloaderCLI/Modes/Arguments/CurlArgs.cs new file mode 100644 index 00000000..4d6f3f5b --- /dev/null +++ b/TwitchDownloaderCLI/Modes/Arguments/CurlArgs.cs @@ -0,0 +1,21 @@ +using CommandLine.Text; +using CommandLine; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TwitchDownloaderCLI.Modes.Arguments +{ + [Verb("curl", HelpText = "Manage standalone curl-impersonate")] + public class CurlArgs : ITwitchDownloaderArgs + { + [Option('d', "download", Default = false, Required = false, HelpText = "Downloads curl-impersonate as a standalone file.")] + public bool DownloadCurl { get; set; } + + [Option("banner", Default = true, HelpText = "Displays a banner containing version and copyright information.")] + public bool? ShowBanner { get; set; } + } +} diff --git a/TwitchDownloaderCLI/Modes/DownloadChat.cs b/TwitchDownloaderCLI/Modes/DownloadChat.cs index e645d323..9aa04edc 100644 --- a/TwitchDownloaderCLI/Modes/DownloadChat.cs +++ b/TwitchDownloaderCLI/Modes/DownloadChat.cs @@ -7,6 +7,8 @@ using TwitchDownloaderCore; using TwitchDownloaderCore.Chat; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderCLI.Modes { @@ -16,10 +18,10 @@ internal static void Download(ChatDownloadArgs inputOptions) { var downloadOptions = GetDownloadOptions(inputOptions); - ChatDownloader chatDownloader = new(downloadOptions); Progress progress = new(); - progress.ProgressChanged += ProgressHandler.Progress_ProgressChanged; - chatDownloader.DownloadAsync(progress, new CancellationToken()).Wait(); + ChatDownloaderFactory downloadFactory = new ChatDownloaderFactory(progress); + IChatDownloader chatDownloader = downloadFactory.Create(downloadOptions); + chatDownloader.DownloadAsync(new CancellationToken()).Wait(); } private static ChatDownloadOptions GetDownloadOptions(ChatDownloadArgs inputOptions) diff --git a/TwitchDownloaderCLI/Modes/DownloadClip.cs b/TwitchDownloaderCLI/Modes/DownloadClip.cs index 7f12e654..8b349be8 100644 --- a/TwitchDownloaderCLI/Modes/DownloadClip.cs +++ b/TwitchDownloaderCLI/Modes/DownloadClip.cs @@ -6,6 +6,8 @@ using TwitchDownloaderCLI.Tools; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; namespace TwitchDownloaderCLI.Modes { @@ -23,7 +25,8 @@ internal static void Download(ClipDownloadArgs inputOptions) var downloadOptions = GetDownloadOptions(inputOptions); - ClipDownloader clipDownloader = new(downloadOptions, progress); + ClipDownloaderFactory downloadFactory = new ClipDownloaderFactory(progress); + IClipDownloader clipDownloader = downloadFactory.Create(downloadOptions); clipDownloader.DownloadAsync(new CancellationToken()).Wait(); } @@ -35,23 +38,28 @@ private static ClipDownloadOptions GetDownloadOptions(ClipDownloadArgs inputOpti Environment.Exit(1); } - var clipIdRegex = new Regex(@"(?<=^|(?:clips\.)?twitch\.tv\/(?:\S+\/clip)?\/?)[\w-]+?(?=$|\?)"); - var clipIdMatch = clipIdRegex.Match(inputOptions.Id); - if (!clipIdMatch.Success) + bool success = UrlParse.TryParseClip(inputOptions.Id, out VideoPlatform videoPlatform, out string videoId); + if (!success) { Console.WriteLine("[ERROR] - Unable to parse Clip ID/URL."); Environment.Exit(1); } + if (videoPlatform == VideoPlatform.Kick) + { + CurlHandler.DetectCurl(inputOptions.CurlImpersonatePath); + } + ClipDownloadOptions downloadOptions = new() { - Id = clipIdMatch.Value, + Id = videoId, Filename = inputOptions.OutputFile, Quality = inputOptions.Quality, ThrottleKib = inputOptions.ThrottleKib, FfmpegPath = string.IsNullOrWhiteSpace(inputOptions.FfmpegPath) ? FfmpegHandler.FfmpegExecutableName : Path.GetFullPath(inputOptions.FfmpegPath), EncodeMetadata = inputOptions.EncodeMetadata!.Value, - TempFolder = inputOptions.TempFolder + TempFolder = inputOptions.TempFolder, + VideoPlatform = videoPlatform, }; return downloadOptions; diff --git a/TwitchDownloaderCLI/Modes/DownloadVideo.cs b/TwitchDownloaderCLI/Modes/DownloadVideo.cs index 07d85a7b..52cb9135 100644 --- a/TwitchDownloaderCLI/Modes/DownloadVideo.cs +++ b/TwitchDownloaderCLI/Modes/DownloadVideo.cs @@ -6,6 +6,8 @@ using TwitchDownloaderCLI.Tools; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderCLI.Modes { @@ -19,7 +21,8 @@ internal static void Download(VideoDownloadArgs inputOptions) progress.ProgressChanged += ProgressHandler.Progress_ProgressChanged; var downloadOptions = GetDownloadOptions(inputOptions); - VideoDownloader videoDownloader = new(downloadOptions, progress); + VideoDownloaderFactory downloadFactory = new VideoDownloaderFactory(progress); + IVideoDownloader videoDownloader = downloadFactory.Create(downloadOptions); videoDownloader.DownloadAsync(new CancellationToken()).Wait(); } @@ -43,7 +46,7 @@ private static VideoDownloadOptions GetDownloadOptions(VideoDownloadArgs inputOp { DownloadThreads = inputOptions.DownloadThreads, ThrottleKib = inputOptions.ThrottleKib, - Id = int.Parse(vodIdMatch.ValueSpan), + Id = vodIdMatch.ValueSpan.ToString(), Oauth = inputOptions.Oauth, Filename = inputOptions.OutputFile, Quality = inputOptions.Quality, diff --git a/TwitchDownloaderCLI/Program.cs b/TwitchDownloaderCLI/Program.cs index 20a96813..63cbf55f 100644 --- a/TwitchDownloaderCLI/Program.cs +++ b/TwitchDownloaderCLI/Program.cs @@ -18,6 +18,7 @@ private static void Main(string[] args) { // Set the working dir to the app dir in case we inherited a different working dir Directory.SetCurrentDirectory(AppContext.BaseDirectory); + Environment.SetEnvironmentVariable("CURL_IMPERSONATE", "chrome110"); var preParsedArgs = PreParseArgs.Parse(args, Path.GetFileName(Environment.ProcessPath)); @@ -27,7 +28,7 @@ private static void Main(string[] args) config.HelpWriter = TextWriter.Null; }); - var parserResult = parser.ParseArguments(preParsedArgs); + var parserResult = parser.ParseArguments(preParsedArgs); parserResult.WithNotParsed(errors => WriteHelpText(errors, parserResult, parser.Settings)); CoreLicensor.EnsureFilesExist(AppContext.BaseDirectory); @@ -40,6 +41,7 @@ private static void Main(string[] args) .WithParsed(UpdateChat.Update) .WithParsed(RenderChat.Render) .WithParsed(FfmpegHandler.ParseArgs) + .WithParsed(CurlHandler.ParseArgs) .WithParsed(CacheHandler.ParseArgs); } diff --git a/TwitchDownloaderCLI/Properties/launchSettings.json b/TwitchDownloaderCLI/Properties/launchSettings.json index a28423c5..b03889fd 100644 --- a/TwitchDownloaderCLI/Properties/launchSettings.json +++ b/TwitchDownloaderCLI/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "TwitchDownloaderCLI": { "commandName": "Project", - "commandLineArgs": "chatrender -i chat.json --badge-filter 255 -o chat.mp4" + "commandLineArgs": "curl --download" }, "WSL": { "commandName": "WSL2", diff --git a/TwitchDownloaderCLI/Tools/CurlHandler.cs b/TwitchDownloaderCLI/Tools/CurlHandler.cs new file mode 100644 index 00000000..324cfeea --- /dev/null +++ b/TwitchDownloaderCLI/Tools/CurlHandler.cs @@ -0,0 +1,70 @@ +using ICSharpCode.SharpZipLib.GZip; +using ICSharpCode.SharpZipLib.Tar; +using Microsoft.Extensions.Hosting.Internal; +using Mono.Unix; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCLI.Modes.Arguments; + +namespace TwitchDownloaderCLI.Tools +{ + public class CurlHandler + { + public static readonly string[] FilesToExtract = new string[] { "curl-ca-bundle.crt", "libcurl.dll", "libcurl.a", "libcurldll.a", }; + + public static void DetectCurl(string curlImpersonatePath) + { + throw new NotImplementedException(); + + Console.WriteLine("[ERROR] - Unable to find curl-impersonate, exiting."); + Environment.Exit(1); + } + public static void ParseArgs(CurlArgs args) + { + if (args.DownloadCurl) + { + DownloadCurl(args).Wait(); + } + } + + private static async Task DownloadCurl(CurlArgs args) + { + using HttpClient httpClient = new HttpClient(); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + using (HttpResponseMessage response = await httpClient.GetAsync("https://github.com/depler/curl-impersonate-win/releases/download/20230227/curl-impersonate-win.zip")) + using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync()) + { + using (var fs = new FileStream("curl-impersonate-win.zip", FileMode.Create)) + { + await response.Content.CopyToAsync(fs); + } + } + + using (var archive = ZipFile.OpenRead("curl-impersonate-win.zip")) + { + foreach (var item in archive.Entries) + { + if (FilesToExtract.Contains(item.Name)) + { + item.ExtractToFile(Path.Combine(Directory.GetCurrentDirectory(), item.FullName.Replace("curl-impersonate-win/", "")), true); + } + } + } + + File.Delete("curl-impersonate-win.zip"); + } + else + { + throw new NotImplementedException(); + } + } + } +} diff --git a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj index c00a7611..b31c83b3 100644 --- a/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj +++ b/TwitchDownloaderCLI/TwitchDownloaderCLI.csproj @@ -15,6 +15,7 @@ + diff --git a/TwitchDownloaderCore/Chat/ChatHtml.cs b/TwitchDownloaderCore/Chat/ChatHtml.cs index a4400fb3..44e49318 100644 --- a/TwitchDownloaderCore/Chat/ChatHtml.cs +++ b/TwitchDownloaderCore/Chat/ChatHtml.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using System.Web; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Chat { diff --git a/TwitchDownloaderCore/Chat/ChatJson.cs b/TwitchDownloaderCore/Chat/ChatJson.cs index a0f67526..2d013c54 100644 --- a/TwitchDownloaderCore/Chat/ChatJson.cs +++ b/TwitchDownloaderCore/Chat/ChatJson.cs @@ -8,7 +8,7 @@ using System.Threading; using System.Threading.Tasks; using TwitchDownloaderCore.Extensions; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Chat { diff --git a/TwitchDownloaderCore/Chat/ChatText.cs b/TwitchDownloaderCore/Chat/ChatText.cs index df09a61b..07b49f1e 100644 --- a/TwitchDownloaderCore/Chat/ChatText.cs +++ b/TwitchDownloaderCore/Chat/ChatText.cs @@ -2,7 +2,7 @@ using System.IO; using System.Threading.Tasks; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Chat { diff --git a/TwitchDownloaderCore/ChatRenderer.cs b/TwitchDownloaderCore/ChatRenderer.cs index 9ffe12d4..57163800 100644 --- a/TwitchDownloaderCore/ChatRenderer.cs +++ b/TwitchDownloaderCore/ChatRenderer.cs @@ -17,7 +17,7 @@ using TwitchDownloaderCore.Extensions; using TwitchDownloaderCore.Options; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore { diff --git a/TwitchDownloaderCore/ChatUpdater.cs b/TwitchDownloaderCore/ChatUpdater.cs index 9ac3c06a..2a1a94b5 100644 --- a/TwitchDownloaderCore/ChatUpdater.cs +++ b/TwitchDownloaderCore/ChatUpdater.cs @@ -7,7 +7,8 @@ using TwitchDownloaderCore.Chat; using TwitchDownloaderCore.Options; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderCore { @@ -310,8 +311,8 @@ private async Task ChatEndingCropTask(IProgress progress, Cancel private async Task AppendCommentSection(ChatDownloadOptions downloadOptions, string inputFile, CancellationToken cancellationToken = new()) { - ChatDownloader chatDownloader = new ChatDownloader(downloadOptions); - await chatDownloader.DownloadAsync(new Progress(), cancellationToken); + TwitchChatDownloader chatDownloader = new TwitchChatDownloader(downloadOptions, new Progress()); + await chatDownloader.DownloadAsync(cancellationToken); ChatRoot newChatRoot = await ChatJson.DeserializeAsync(inputFile, getComments: true, getEmbeds: false, cancellationToken); diff --git a/TwitchDownloaderCore/Options/ChatDownloadOptions.cs b/TwitchDownloaderCore/Options/ChatDownloadOptions.cs index ee7c2c2b..4b6d0d25 100644 --- a/TwitchDownloaderCore/Options/ChatDownloadOptions.cs +++ b/TwitchDownloaderCore/Options/ChatDownloadOptions.cs @@ -1,4 +1,5 @@ using TwitchDownloaderCore.Chat; +using TwitchDownloaderCore.Tools; namespace TwitchDownloaderCore.Options { @@ -34,5 +35,13 @@ public string FileExtension } } public string TempFolder { get; set; } + public VideoPlatform VideoPlatform { get; set; } + public ChatDownloadType DownloadType { get; set; } + } + + public enum ChatDownloadType + { + Clip, + Video } } diff --git a/TwitchDownloaderCore/Options/ClipDownloadOptions.cs b/TwitchDownloaderCore/Options/ClipDownloadOptions.cs index 9f8c6ce9..063f9a92 100644 --- a/TwitchDownloaderCore/Options/ClipDownloadOptions.cs +++ b/TwitchDownloaderCore/Options/ClipDownloadOptions.cs @@ -1,4 +1,6 @@ -namespace TwitchDownloaderCore.Options +using TwitchDownloaderCore.Tools; + +namespace TwitchDownloaderCore.Options { public class ClipDownloadOptions { @@ -9,5 +11,6 @@ public class ClipDownloadOptions public string TempFolder { get; set; } public bool EncodeMetadata { get; set; } public string FfmpegPath { get; set; } + public VideoPlatform VideoPlatform { get; set; } } } \ No newline at end of file diff --git a/TwitchDownloaderCore/Options/VideoDownloadOptions.cs b/TwitchDownloaderCore/Options/VideoDownloadOptions.cs index 7ac21df3..94a88793 100644 --- a/TwitchDownloaderCore/Options/VideoDownloadOptions.cs +++ b/TwitchDownloaderCore/Options/VideoDownloadOptions.cs @@ -1,8 +1,10 @@ -namespace TwitchDownloaderCore.Options +using TwitchDownloaderCore.Tools; + +namespace TwitchDownloaderCore.Options { public class VideoDownloadOptions { - public int Id { get; set; } + public string Id { get; set; } public string Quality { get; set; } public string Filename { get; set; } public bool CropBeginning { get; set; } @@ -14,5 +16,6 @@ public class VideoDownloadOptions public string Oauth { get; set; } public string FfmpegPath { get; set; } public string TempFolder { get; set; } + public VideoPlatform VideoPlatform { get; set; } } } diff --git a/TwitchDownloaderCore/PlatformHelper.cs b/TwitchDownloaderCore/PlatformHelper.cs new file mode 100644 index 00000000..4172d3f0 --- /dev/null +++ b/TwitchDownloaderCore/PlatformHelper.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Kick; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; + +namespace TwitchDownloaderCore +{ + public class PlatformHelper + { + public static async Task GetClipInfo(VideoPlatform videoPlatform, string clipId) + { + if (videoPlatform == VideoPlatform.Twitch) + { + IVideoInfo clipInfo = await TwitchHelper.GetClipInfo(clipId); + List clipResponse = await TwitchHelper.GetClipLinks(clipId); + clipInfo.VideoQualities = new List(); + foreach (var clip in clipResponse[0].data.clip.videoQualities) + { + clipInfo.VideoQualities.Add(new VideoQuality { Quality = clip.quality, Framerate = clip.frameRate, SourceUrl = clip.sourceURL }); + } + return clipInfo; + } + + if (videoPlatform == VideoPlatform.Kick) + { + return await KickHelper.GetClipInfo(clipId); + } + + throw new NotImplementedException(); + } + + public static async Task GetVideoInfo(VideoPlatform videoPlatform, string videoId, string Oauth = "") + { + if (videoPlatform == VideoPlatform.Twitch) + { + return await TwitchHelper.GetVideoInfo(int.Parse(videoId)); + } + + if (videoPlatform == VideoPlatform.Kick) + { + return await KickHelper.GetVideoInfo(videoId); + } + + throw new NotImplementedException(); + } + } +} diff --git a/TwitchDownloaderCore/Tools/CommentTools.cs b/TwitchDownloaderCore/Tools/CommentTools.cs index cb3d769f..4f9c90dc 100644 --- a/TwitchDownloaderCore/Tools/CommentTools.cs +++ b/TwitchDownloaderCore/Tools/CommentTools.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Tools { diff --git a/TwitchDownloaderCore/Tools/CurlImpersonate.cs b/TwitchDownloaderCore/Tools/CurlImpersonate.cs new file mode 100644 index 00000000..3fb79280 --- /dev/null +++ b/TwitchDownloaderCore/Tools/CurlImpersonate.cs @@ -0,0 +1,47 @@ +using CurlThin.Enums; +using CurlThin; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.Tools +{ + public static class CurlImpersonate + { + static CURLcode global = CurlNative.Init(); + public static string GetCurlReponse(string url) + { + + var easy = CurlNative.Easy.Init(); + try + { + CurlNative.Easy.SetOpt(easy, CURLoption.URL, url); + CurlNative.Easy.SetOpt(easy, CURLoption.CAINFO, "curl-ca-bundle.crt"); + CurlNative.Easy.SetOpt(easy, CURLoption.TIMEOUT_MS, 3000); + + var stream = new MemoryStream(); + CurlNative.Easy.SetOpt(easy, CURLoption.WRITEFUNCTION, (data, size, nmemb, user) => + { + var length = (int)size * (int)nmemb; + var buffer = new byte[length]; + Marshal.Copy(data, buffer, 0, length); + stream.Write(buffer, 0, length); + return (UIntPtr)length; + }); + + var result = CurlNative.Easy.Perform(easy); + string response = Encoding.UTF8.GetString(stream.ToArray()); + return response; + } + finally + { + easy.Dispose(); + } + } + } +} diff --git a/TwitchDownloaderCore/Tools/DownloadTools.cs b/TwitchDownloaderCore/Tools/DownloadTools.cs new file mode 100644 index 00000000..7c416ae2 --- /dev/null +++ b/TwitchDownloaderCore/Tools/DownloadTools.cs @@ -0,0 +1,494 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Extensions; +using TwitchDownloaderCore.Options; + +namespace TwitchDownloaderCore.Tools +{ + public class DownloadTools + { + private static readonly HttpClient HttpClient = new(); + public static async Task DownloadClipFileTaskAsync(string url, string destinationFile, int throttleKib, IProgress progress, CancellationToken cancellationToken) + { + var request = new HttpRequestMessage(HttpMethod.Get, url); + using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + var contentLength = response.Content.Headers.ContentLength; + + if (throttleKib == -1) + { + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); + await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken); + await contentStream.ProgressCopyToAsync(fs, contentLength, progress, cancellationToken).ConfigureAwait(false); + } + else + { + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); + await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken); + await using var throttledStream = new ThrottledStream(contentStream, throttleKib); + await throttledStream.ProgressCopyToAsync(fs, contentLength, progress, cancellationToken).ConfigureAwait(false); + } + } + + public static List> GenerateCroppedVideoList(List> videoList, VideoDownloadOptions downloadOptions) + { + List> returnList = new List>(videoList); + TimeSpan startCrop = TimeSpan.FromSeconds(downloadOptions.CropBeginningTime); + TimeSpan endCrop = TimeSpan.FromSeconds(downloadOptions.CropEndingTime); + + if (downloadOptions.CropBeginning) + { + double startTime = 0; + for (int i = 0; i < returnList.Count; i++) + { + if (startTime + returnList[i].Value < startCrop.TotalSeconds) + { + startTime += returnList[i].Value; + returnList.RemoveAt(i); + i--; + } + else + { + break; + } + } + } + + if (downloadOptions.CropEnding) + { + double endTime = 0.0; + videoList.ForEach(x => endTime += x.Value); + + for (int i = returnList.Count - 1; i >= 0; i--) + { + if (endTime - returnList[i].Value > endCrop.TotalSeconds) + { + endTime -= returnList[i].Value; + returnList.RemoveAt(i); + } + else + { + break; + } + } + } + + return returnList; + } + + public static void LogDownloadThreadExceptions(Dictionary downloadExceptions, IProgress progress) + { + if (downloadExceptions.Count == 0) + return; + + var culpritList = new List(); + var sb = new StringBuilder(); + foreach (var downloadException in downloadExceptions.Values) + { + var ex = downloadException switch + { + AggregateException { InnerException: { } innerException } => innerException, + _ => downloadException + }; + + // Try to only log exceptions from different sources + var culprit = ex.TargetSite?.Name; + if (string.IsNullOrEmpty(culprit) || culpritList.Contains(culprit)) + continue; + + sb.EnsureCapacity(sb.Capacity + ex.Message.Length + culprit.Length + 6); + sb.Append(", "); + sb.Append(ex.Message); + sb.Append(" at "); + sb.Append(culprit); + culpritList.Add(culprit); + } + + if (sb.Length == 0) + { + return; + } + + sb.Replace(",", $"{downloadExceptions.Count} errors were encountered while downloading:", 0, 1); + progress.Report(new ProgressReport(ReportType.Log, sb.ToString())); + } + + public static Task StartNewDownloadThread(ConcurrentQueue videoPartsQueue, VideoDownloadOptions downloadOptions, string baseUrl, string downloadFolder, double vodAge, CancellationToken cancellationToken) + { + return Task.Factory.StartNew(state => + { + var (partQueue, rootUrl, cacheFolder, videoAge, throttleKib, cancelToken) = + (Tuple, string, string, double, int, CancellationToken>)state; + + while (!partQueue.IsEmpty) + { + if (partQueue.TryDequeue(out var request)) + { + DownloadVideoPartAsync(rootUrl, downloadOptions, request, cacheFolder, videoAge, throttleKib, cancelToken).GetAwaiter().GetResult(); + } + + Task.Delay(77, cancelToken).GetAwaiter().GetResult(); + } + }, new Tuple, string, string, double, int, CancellationToken>( + videoPartsQueue, baseUrl, downloadFolder, vodAge, downloadOptions.ThrottleKib, cancellationToken), + cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current); + } + + public static async Task> WaitForDownloadThreads(Task[] tasks, VideoDownloadOptions downloadOptions, ConcurrentQueue videoPartsQueue, string baseUrl, string downloadFolder, double vodAge, int partCount, IProgress progress, CancellationToken cancellationToken) + { + var allThreadsExited = false; + var previousDoneCount = 0; + var restartedThreads = 0; + var maxRestartedThreads = Math.Max(downloadOptions.DownloadThreads, 10); + var downloadExceptions = new Dictionary(); + do + { + if (videoPartsQueue.Count != previousDoneCount) + { + previousDoneCount = videoPartsQueue.Count; + var percent = (int)((partCount - previousDoneCount) / (double)partCount * 100); + progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Downloading {percent}% [2/5]")); + progress.Report(new ProgressReport(percent)); + } + + allThreadsExited = true; + for (var t = 0; t < tasks.Length; t++) + { + var task = tasks[t]; + + if (task.IsFaulted) + { + downloadExceptions.TryAdd(task.Id, task.Exception); + + if (restartedThreads <= maxRestartedThreads) + { + tasks[t] = StartNewDownloadThread(videoPartsQueue, downloadOptions, baseUrl, downloadFolder, vodAge, cancellationToken); + restartedThreads++; + } + } + + if (allThreadsExited && !task.IsCompleted) + { + allThreadsExited = false; + } + } + + await Task.Delay(300, cancellationToken); + } while (!allThreadsExited); + + if (restartedThreads == maxRestartedThreads) + { + throw new AggregateException("The download thread restart limit was reached.", downloadExceptions.Values); + } + + return downloadExceptions; + } + + private static async Task DownloadVideoPartAsync(string baseUrl, VideoDownloadOptions downloadOptions, string videoPartName, string downloadFolder, double vodAge, int throttleKib, CancellationToken cancellationToken) + { + bool tryUnmute = vodAge < 24 && downloadOptions.VideoPlatform == VideoPlatform.Twitch; + int errorCount = 0; + int timeoutCount = 0; + while (true) + { + cancellationToken.ThrowIfCancellationRequested(); + + try + { + if (tryUnmute && videoPartName.Contains("-muted")) + { + await DownloadFileTaskAsync(baseUrl + videoPartName.Replace("-muted", ""), Path.Combine(downloadFolder, RemoveQueryString(videoPartName)), throttleKib, cancellationToken); + } + else + { + await DownloadFileTaskAsync(baseUrl + videoPartName, Path.Combine(downloadFolder, RemoveQueryString(videoPartName)), throttleKib, cancellationToken); + } + + return; + } + catch (HttpRequestException ex) when (tryUnmute && ex.StatusCode is HttpStatusCode.Forbidden) + { + tryUnmute = false; + } + catch (HttpRequestException) + { + if (++errorCount > 10) + { + throw new HttpRequestException($"Video part {videoPartName} failed after 10 retries"); + } + + await Task.Delay(1_000 * errorCount, cancellationToken); + } + catch (TaskCanceledException ex) when (ex.Message.Contains("HttpClient.Timeout")) + { + if (++timeoutCount > 3) + { + throw new HttpRequestException($"Video part {videoPartName} timed out 3 times"); + } + + await Task.Delay(5_000 * timeoutCount, cancellationToken); + } + } + } + + /// + /// Downloads the requested to the without storing it in memory. + /// + /// The url of the file to download. + /// The path to the file where download will be saved. + /// The maximum download speed in kibibytes per second, or -1 for no maximum. + /// The cancellation token to cancel the operation. + public static async Task DownloadFileTaskAsync(string url, string destinationFile, int throttleKib, CancellationToken cancellationToken = default) + { + var request = new HttpRequestMessage(HttpMethod.Get, url); + + using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); + response.EnsureSuccessStatusCode(); + + switch (throttleKib) + { + case -1: + { + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); + await response.Content.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); + break; + } + default: + { + try + { + await using var throttledStream = new ThrottledStream(await response.Content.ReadAsStreamAsync(cancellationToken), throttleKib); + await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); + await throttledStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); + } + catch (IOException e) when (e.Message.Contains("EOF")) + { + // The throttled stream throws when it reads an unexpected EOF, try again without the limiter + // TODO: Log this somehow + await Task.Delay(2_000, cancellationToken); + goto case -1; + } + break; + } + } + } + + public static async Task VerifyDownloadedParts(VideoDownloadOptions downloadOptions, List videoParts, string baseUrl, string downloadFolder, double vodAge, IProgress progress, CancellationToken cancellationToken) + { + var failedParts = new List(); + var partCount = videoParts.Count; + var doneCount = 0; + + foreach (var part in videoParts) + { + if (!VerifyVideoPart(downloadFolder, part)) + { + failedParts.Add(part); + } + + doneCount++; + var percent = (int)(doneCount / (double)partCount * 100); + progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Verifying Parts {percent}% [3/5]")); + progress.Report(new ProgressReport(percent)); + + cancellationToken.ThrowIfCancellationRequested(); + } + + if (failedParts.Count != 0) + { + if (failedParts.Count == videoParts.Count) + { + // Every video part returned corrupted, probably a false positive. + return; + } + + progress.Report(new ProgressReport(ReportType.Log, $"The following parts will be redownloaded: {string.Join(", ", failedParts)}")); + await DownloadVideoPartsAsync(downloadOptions, failedParts, baseUrl, downloadFolder, vodAge, progress, cancellationToken); + } + } + + public static async Task DownloadVideoPartsAsync(VideoDownloadOptions downloadOptions, List videoPartsList, string baseUrl, string downloadFolder, double vodAge, IProgress progress, CancellationToken cancellationToken) + { + var partCount = videoPartsList.Count; + var videoPartsQueue = new ConcurrentQueue(videoPartsList); + var downloadTasks = new Task[downloadOptions.DownloadThreads]; + + for (var i = 0; i < downloadOptions.DownloadThreads; i++) + { + downloadTasks[i] = DownloadTools.StartNewDownloadThread(videoPartsQueue, downloadOptions, baseUrl, downloadFolder, vodAge, cancellationToken); + } + + var downloadExceptions = await DownloadTools.WaitForDownloadThreads(downloadTasks, downloadOptions, videoPartsQueue, baseUrl, downloadFolder, vodAge, partCount, progress, cancellationToken); + + DownloadTools.LogDownloadThreadExceptions(downloadExceptions, progress); + } + + public static async Task CombineVideoParts(string downloadFolder, List videoParts, IProgress progress, CancellationToken cancellationToken) + { + DriveInfo outputDrive = DriveHelper.GetOutputDrive(downloadFolder); + string outputFile = Path.Combine(downloadFolder, "output.ts"); + + int partCount = videoParts.Count; + int doneCount = 0; + + await using var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None); + foreach (var part in videoParts) + { + await DriveHelper.WaitForDrive(outputDrive, progress, cancellationToken); + + string partFile = Path.Combine(downloadFolder, DownloadTools.RemoveQueryString(part)); + if (File.Exists(partFile)) + { + await using (var fs = File.Open(partFile, FileMode.Open, FileAccess.Read, FileShare.None)) + { + await fs.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); + } + + try + { + File.Delete(partFile); + } + catch { /* If we can't delete, oh well. It should get cleanup up later anyways */ } + } + + doneCount++; + int percent = (int)(doneCount / (double)partCount * 100); + progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Combining Parts {percent}% [4/5]")); + progress.Report(new ProgressReport(percent)); + + cancellationToken.ThrowIfCancellationRequested(); + } + } + + public static int RunFfmpegVideoCopy(VideoDownloadOptions downloadOptions, string downloadFolder, string metadataPath, double seekTime, double startOffset, double seekDuration, IProgress progress) + { + var process = new Process + { + StartInfo = + { + FileName = downloadOptions.FfmpegPath, + Arguments = string.Format( + "-hide_banner -stats -y -avoid_negative_ts make_zero " + (downloadOptions.CropBeginning ? "-ss {2} " : "") + "-i \"{0}\" -i \"{1}\" -map_metadata 1 -analyzeduration {3} -probesize {3} " + (downloadOptions.CropEnding ? "-t {4} " : "") + "-c copy \"{5}\"", + Path.Combine(downloadFolder, "output.ts"), metadataPath, (seekTime - startOffset).ToString(CultureInfo.InvariantCulture), int.MaxValue, seekDuration.ToString(CultureInfo.InvariantCulture), Path.GetFullPath(downloadOptions.Filename)), + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = false, + RedirectStandardOutput = true, + RedirectStandardError = true + } + }; + + var encodingTimeRegex = new Regex(@"(?<=time=)(\d\d):(\d\d):(\d\d)\.(\d\d)", RegexOptions.Compiled); + var logQueue = new ConcurrentQueue(); + + process.ErrorDataReceived += (sender, e) => + { + if (e.Data is null) + return; + + logQueue.Enqueue(e.Data); // We cannot use -report ffmpeg arg because it redirects stderr + + HandleFfmpegOutput(e.Data, encodingTimeRegex, seekDuration, progress); + }; + + process.Start(); + process.BeginErrorReadLine(); + + using var logWriter = File.AppendText(Path.Combine(downloadFolder, "ffmpegLog.txt")); + do // We cannot handle logging inside the ErrorDataReceived lambda because more than 1 can come in at once and cause a race condition. lay295#598 + { + Thread.Sleep(330); + while (!logQueue.IsEmpty && logQueue.TryDequeue(out var logMessage)) + { + logWriter.WriteLine(logMessage); + } + } while (!process.HasExited || !logQueue.IsEmpty); + + return process.ExitCode; + } + + private static void HandleFfmpegOutput(string output, Regex encodingTimeRegex, double videoLength, IProgress progress) + { + var encodingTimeMatch = encodingTimeRegex.Match(output); + if (!encodingTimeMatch.Success) + return; + + // TimeSpan.Parse insists that hours cannot be greater than 24, thus we must use the TimeSpan ctor. + if (!int.TryParse(encodingTimeMatch.Groups[1].ValueSpan, out var hours)) return; + if (!int.TryParse(encodingTimeMatch.Groups[2].ValueSpan, out var minutes)) return; + if (!int.TryParse(encodingTimeMatch.Groups[3].ValueSpan, out var seconds)) return; + if (!int.TryParse(encodingTimeMatch.Groups[4].ValueSpan, out var milliseconds)) return; + var encodingTime = new TimeSpan(0, hours, minutes, seconds, milliseconds); + + var percent = (int)Math.Round(encodingTime.TotalSeconds / videoLength * 100); + + // Apparently it is possible for the percent to not be within the range of 0-100. lay295#716 + if (percent is < 0 or > 100) + { + progress.Report(new ProgressReport(ReportType.SameLineStatus, "Finalizing Video... [4/4]")); + progress.Report(new ProgressReport(0)); + } + else + { + progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Finalizing Video {percent}% [4/4]")); + progress.Report(new ProgressReport(percent)); + } + } + + private static bool VerifyVideoPart(string downloadFolder, string part) + { + const int TS_PACKET_LENGTH = 188; // MPEG TS packets are made of a header and a body: [ 4B ][ 184B ] - https://tsduck.io/download/docs/mpegts-introduction.pdf + + var partFile = Path.Combine(downloadFolder, DownloadTools.RemoveQueryString(part)); + if (!File.Exists(partFile)) + { + return false; + } + + using var fs = File.Open(partFile, FileMode.Open, FileAccess.Read, FileShare.None); + var fileLength = fs.Length; + if (fileLength == 0 || fileLength % TS_PACKET_LENGTH != 0) + { + return false; + } + + return true; + } + + //Some old twitch VODs have files with a query string at the end such as 1.ts?offset=blah which isn't a valid filename + public static string RemoveQueryString(string inputString) + { + var queryIndex = inputString.IndexOf('?'); + if (queryIndex == -1) + { + return inputString; + } + + return inputString[..queryIndex]; + } + + public static void Cleanup(string downloadFolder) + { + try + { + if (Directory.Exists(downloadFolder)) + { + Directory.Delete(downloadFolder, true); + } + } + catch (IOException) { } // Directory is probably being used by another process + } + } +} diff --git a/TwitchDownloaderCore/Tools/DriveHelper.cs b/TwitchDownloaderCore/Tools/DriveHelper.cs index 886d2275..e83dbb8b 100644 --- a/TwitchDownloaderCore/Tools/DriveHelper.cs +++ b/TwitchDownloaderCore/Tools/DriveHelper.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Text; using System.Threading; using System.Threading.Tasks; +using TwitchDownloaderCore.Options; namespace TwitchDownloaderCore.Tools { @@ -46,5 +49,35 @@ public static async Task WaitForDrive(DriveInfo drive, IProgress } } } + + public static void CheckAvailableStorageSpace(VideoDownloadOptions downloadOptions, int bandwidth, TimeSpan videoLength, IProgress progress = null) + { + var videoSizeInBytes = VideoSizeEstimator.EstimateVideoSize(bandwidth, + downloadOptions.CropBeginning ? TimeSpan.FromSeconds(downloadOptions.CropBeginningTime) : TimeSpan.Zero, + downloadOptions.CropEnding ? TimeSpan.FromSeconds(downloadOptions.CropEndingTime) : videoLength); + var tempFolderDrive = DriveHelper.GetOutputDrive(downloadOptions.TempFolder); + var destinationDrive = DriveHelper.GetOutputDrive(downloadOptions.Filename); + + if (tempFolderDrive.Name == destinationDrive.Name) + { + if (tempFolderDrive.AvailableFreeSpace < videoSizeInBytes * 2) + { + progress?.Report(new ProgressReport(ReportType.Log, $"The drive '{tempFolderDrive.Name}' may not have enough free space to complete the download.")); + } + } + else + { + if (tempFolderDrive.AvailableFreeSpace < videoSizeInBytes) + { + // More drive space is needed by the raw ts files due to repeat metadata, but the amount of metadata packets can vary between files so we won't bother. + progress?.Report(new ProgressReport(ReportType.Log, $"The drive '{tempFolderDrive.Name}' may not have enough free space to complete the download.")); + } + + if (destinationDrive.AvailableFreeSpace < videoSizeInBytes) + { + progress?.Report(new ProgressReport(ReportType.Log, $"The drive '{destinationDrive.Name}' may not have enough free space to complete finalization.")); + } + } + } } } \ No newline at end of file diff --git a/TwitchDownloaderCore/Tools/FfmpegMetadata.cs b/TwitchDownloaderCore/Tools/FfmpegMetadata.cs index f8aa3851..e50f9d19 100644 --- a/TwitchDownloaderCore/Tools/FfmpegMetadata.cs +++ b/TwitchDownloaderCore/Tools/FfmpegMetadata.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using TwitchDownloaderCore.TwitchObjects.Gql; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; namespace TwitchDownloaderCore.Tools { diff --git a/TwitchDownloaderCore/Tools/HighlightIcons.cs b/TwitchDownloaderCore/Tools/HighlightIcons.cs index ee1bc761..5a1a1e77 100644 --- a/TwitchDownloaderCore/Tools/HighlightIcons.cs +++ b/TwitchDownloaderCore/Tools/HighlightIcons.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Text.RegularExpressions; -using TwitchDownloaderCore.TwitchObjects; +using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Tools { diff --git a/TwitchDownloaderCore/Tools/UrlParse.cs b/TwitchDownloaderCore/Tools/UrlParse.cs new file mode 100644 index 00000000..d5a50914 --- /dev/null +++ b/TwitchDownloaderCore/Tools/UrlParse.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.Tools +{ + public enum VideoPlatform + { + Twitch, + Kick, + Youtube + } + + public class UrlParse + { + public static bool TryParseClip(string url, out VideoPlatform videoPlatform, out string videoId) + { + var twitchClipIdRegex = new Regex(@"(?<=^|(?:clips\.)?twitch\.tv\/(?:\S+\/clip)?\/?)[\w-]+?(?=$|\?)"); + var twitchClipIdMatch = twitchClipIdRegex.Match(url); + + if (twitchClipIdMatch.Success) + { + videoPlatform = VideoPlatform.Twitch; + videoId = twitchClipIdMatch.Value; + return true; + } + + var kickClipIdRegex = new Regex(@"(?<=kick\.com\/\S+\?clip=)[\w-]+"); + var kickClipIdMatch = kickClipIdRegex.Match(url); + + if (kickClipIdMatch.Success) + { + videoPlatform = VideoPlatform.Kick; + videoId = kickClipIdMatch.Value; + return true; + } + + videoPlatform = VideoPlatform.Twitch; + videoId = "Don't ignore return value"; + return false; + } + + public static bool TryParseVod(string url, out VideoPlatform videoPlatform, out string videoId) + { + var twitchVodRegex = new Regex(@"(?<=^|twitch\.tv\/videos\/)\d+(?=$|\?)"); + var twitchVodIdMatch = twitchVodRegex.Match(url); + + if (twitchVodIdMatch.Success) + { + videoPlatform = VideoPlatform.Twitch; + videoId = twitchVodIdMatch.Value; + return true; + } + + var kickVodIdRegex = new Regex(@"(?<=kick\.com\/video\/)[\w-]+"); + var kickVodIdMatch = kickVodIdRegex.Match(url); + + if (kickVodIdMatch.Success) + { + videoPlatform = VideoPlatform.Kick; + videoId = kickVodIdMatch.Value; + return true; + } + + videoPlatform = VideoPlatform.Twitch; + videoId = "Don't ignore return value"; + return false; + } + } +} diff --git a/TwitchDownloaderCore/TwitchDownloaderCore.csproj b/TwitchDownloaderCore/TwitchDownloaderCore.csproj index 27ee1ec3..3e2c018d 100644 --- a/TwitchDownloaderCore/TwitchDownloaderCore.csproj +++ b/TwitchDownloaderCore/TwitchDownloaderCore.csproj @@ -22,6 +22,7 @@ + diff --git a/TwitchDownloaderCore/TwitchObjects/StvEmoteFlags.cs b/TwitchDownloaderCore/TwitchObjects/StvEmoteFlags.cs deleted file mode 100644 index fb5c8741..00000000 --- a/TwitchDownloaderCore/TwitchObjects/StvEmoteFlags.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; - -namespace TwitchDownloaderCore.TwitchObjects -{ - // https://github.com/SevenTV/Common/blob/4139fcc3eb8d79003573b26b552ef112ec85b8df/structures/v3/type.emote.go#L49 - [Flags] - public enum StvEmoteFlags - { - Private = 1 << 0, // The emote is private and can only be accessed by its owner, editors and moderators - Authentic = 1 << 1, // The emote was verified to be an original creation by the uploader - ZeroWidth = 1 << 8, // The emote is recommended to be enabled as Zero-Width - - - // Content Flags - - ContentSexual = 1 << 16, // Sexually Suggesive - ContentEpilepsy = 1 << 17, // Rapid flashing - ContentEdgy = 1 << 18, // Edgy or distasteful, may be offensive to some users - ContentTwitchDisallowed = 1 << 24, // Not allowed specifically on the Twitch platform - }; -} diff --git a/TwitchDownloaderCore/VideoDownloader.cs b/TwitchDownloaderCore/VideoDownloader.cs deleted file mode 100644 index cc0b7976..00000000 --- a/TwitchDownloaderCore/VideoDownloader.cs +++ /dev/null @@ -1,707 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; -using TwitchDownloaderCore.Options; -using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects.Gql; - -namespace TwitchDownloaderCore -{ - public sealed class VideoDownloader - { - private readonly VideoDownloadOptions downloadOptions; - private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(30) }; - private readonly IProgress _progress; - private bool _shouldClearCache = true; - - public VideoDownloader(VideoDownloadOptions videoDownloadOptions, IProgress progress) - { - downloadOptions = videoDownloadOptions; - downloadOptions.TempFolder = Path.Combine( - string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, - "TwitchDownloader"); - _progress = progress; - } - - public async Task DownloadAsync(CancellationToken cancellationToken) - { - TwitchHelper.CleanupUnmanagedCacheFiles(downloadOptions.TempFolder, _progress); - - string downloadFolder = Path.Combine( - downloadOptions.TempFolder, - $"{downloadOptions.Id}_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); - - _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Fetching Video Info [1/5]")); - - try - { - ServicePointManager.DefaultConnectionLimit = downloadOptions.DownloadThreads; - - GqlVideoResponse videoInfoResponse = await TwitchHelper.GetVideoInfo(downloadOptions.Id); - if (videoInfoResponse.data.video == null) - { - throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); - } - - GqlVideoChapterResponse videoChapterResponse = await TwitchHelper.GetVideoChapters(downloadOptions.Id); - - var (playlistUrl, bandwidth) = await GetPlaylistUrl(); - string baseUrl = playlistUrl.Substring(0, playlistUrl.LastIndexOf('/') + 1); - - var videoLength = TimeSpan.FromSeconds(videoInfoResponse.data.video.lengthSeconds); - CheckAvailableStorageSpace(bandwidth, videoLength); - - List> videoList = new List>(); - (List videoPartsList, double vodAge) = await GetVideoPartsList(playlistUrl, videoList, cancellationToken); - - if (Directory.Exists(downloadFolder)) - Directory.Delete(downloadFolder, true); - TwitchHelper.CreateDirectory(downloadFolder); - - _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Downloading 0% [2/5]")); - - await DownloadVideoPartsAsync(videoPartsList, baseUrl, downloadFolder, vodAge, cancellationToken); - - _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Verifying Parts 0% [3/5]" }); - - await VerifyDownloadedParts(videoPartsList, baseUrl, downloadFolder, vodAge, cancellationToken); - - _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Combining Parts 0% [4/5]" }); - - await CombineVideoParts(downloadFolder, videoPartsList, cancellationToken); - - _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Finalizing Video 0% [5/5]" }); - - double startOffset = 0.0; - - for (int i = 0; i < videoList.Count; i++) - { - if (videoList[i].Key == videoPartsList[0]) - break; - - startOffset += videoList[i].Value; - } - - double seekTime = downloadOptions.CropBeginningTime; - double seekDuration = Math.Round(downloadOptions.CropEndingTime - seekTime); - - string metadataPath = Path.Combine(downloadFolder, "metadata.txt"); - await FfmpegMetadata.SerializeAsync(metadataPath, videoInfoResponse.data.video.owner.displayName, downloadOptions.Id.ToString(), videoInfoResponse.data.video.title, - videoInfoResponse.data.video.createdAt, videoInfoResponse.data.video.viewCount, startOffset, videoChapterResponse.data.video.moments.edges, cancellationToken); - - var finalizedFileDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; - if (!finalizedFileDirectory.Exists) - { - TwitchHelper.CreateDirectory(finalizedFileDirectory.FullName); - } - - int ffmpegExitCode; - var ffmpegRetries = 0; - do - { - ffmpegExitCode = await Task.Run(() => RunFfmpegVideoCopy(downloadFolder, metadataPath, seekTime, startOffset, seekDuration), cancellationToken); - if (ffmpegExitCode != 0) - { - _progress.Report(new ProgressReport(ReportType.Log, $"Failed to finalize video (code {ffmpegExitCode}), retrying in 10 seconds...")); - await Task.Delay(10_000, cancellationToken); - } - } while (ffmpegExitCode != 0 && ffmpegRetries++ < 1); - - if (ffmpegExitCode != 0 || !File.Exists(downloadOptions.Filename)) - { - _shouldClearCache = false; - throw new Exception($"Failed to finalize video. The download cache has not been cleared and can be found at {downloadFolder} along with a log file."); - } - - _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Finalizing Video 100% [5/5]")); - _progress.Report(new ProgressReport(100)); - } - finally - { - if (_shouldClearCache) - { - Cleanup(downloadFolder); - } - } - } - - private void CheckAvailableStorageSpace(int bandwidth, TimeSpan videoLength) - { - var videoSizeInBytes = VideoSizeEstimator.EstimateVideoSize(bandwidth, - downloadOptions.CropBeginning ? TimeSpan.FromSeconds(downloadOptions.CropBeginningTime) : TimeSpan.Zero, - downloadOptions.CropEnding ? TimeSpan.FromSeconds(downloadOptions.CropEndingTime) : videoLength); - var tempFolderDrive = DriveHelper.GetOutputDrive(downloadOptions.TempFolder); - var destinationDrive = DriveHelper.GetOutputDrive(downloadOptions.Filename); - - if (tempFolderDrive.Name == destinationDrive.Name) - { - if (tempFolderDrive.AvailableFreeSpace < videoSizeInBytes * 2) - { - _progress.Report(new ProgressReport(ReportType.Log, $"The drive '{tempFolderDrive.Name}' may not have enough free space to complete the download.")); - } - } - else - { - if (tempFolderDrive.AvailableFreeSpace < videoSizeInBytes) - { - // More drive space is needed by the raw ts files due to repeat metadata, but the amount of metadata packets can vary between files so we won't bother. - _progress.Report(new ProgressReport(ReportType.Log, $"The drive '{tempFolderDrive.Name}' may not have enough free space to complete the download.")); - } - - if (destinationDrive.AvailableFreeSpace < videoSizeInBytes) - { - _progress.Report(new ProgressReport(ReportType.Log, $"The drive '{destinationDrive.Name}' may not have enough free space to complete finalization.")); - } - } - } - - private async Task DownloadVideoPartsAsync(List videoPartsList, string baseUrl, string downloadFolder, double vodAge, CancellationToken cancellationToken) - { - var partCount = videoPartsList.Count; - var videoPartsQueue = new ConcurrentQueue(videoPartsList); - var downloadTasks = new Task[downloadOptions.DownloadThreads]; - - for (var i = 0; i < downloadOptions.DownloadThreads; i++) - { - downloadTasks[i] = StartNewDownloadThread(videoPartsQueue, baseUrl, downloadFolder, vodAge, cancellationToken); - } - - var downloadExceptions = await WaitForDownloadThreads(downloadTasks, videoPartsQueue, baseUrl, downloadFolder, vodAge, partCount, cancellationToken); - - LogDownloadThreadExceptions(downloadExceptions); - } - - private Task StartNewDownloadThread(ConcurrentQueue videoPartsQueue, string baseUrl, string downloadFolder, double vodAge, CancellationToken cancellationToken) - { - return Task.Factory.StartNew(state => - { - var (partQueue, rootUrl, cacheFolder, videoAge, throttleKib, cancelToken) = - (Tuple, string, string, double, int, CancellationToken>)state; - - while (!partQueue.IsEmpty) - { - if (partQueue.TryDequeue(out var request)) - { - DownloadVideoPartAsync(rootUrl, request, cacheFolder, videoAge, throttleKib, cancelToken).GetAwaiter().GetResult(); - } - - Task.Delay(77, cancelToken).GetAwaiter().GetResult(); - } - }, new Tuple, string, string, double, int, CancellationToken>( - videoPartsQueue, baseUrl, downloadFolder, vodAge, downloadOptions.ThrottleKib, cancellationToken), - cancellationToken, TaskCreationOptions.LongRunning, TaskScheduler.Current); - } - - private async Task> WaitForDownloadThreads(Task[] tasks, ConcurrentQueue videoPartsQueue, string baseUrl, string downloadFolder, double vodAge, int partCount, CancellationToken cancellationToken) - { - var allThreadsExited = false; - var previousDoneCount = 0; - var restartedThreads = 0; - var maxRestartedThreads = Math.Max(downloadOptions.DownloadThreads, 10); - var downloadExceptions = new Dictionary(); - do - { - if (videoPartsQueue.Count != previousDoneCount) - { - previousDoneCount = videoPartsQueue.Count; - var percent = (int)((partCount - previousDoneCount) / (double)partCount * 100); - _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Downloading {percent}% [2/5]")); - _progress.Report(new ProgressReport(percent)); - } - - allThreadsExited = true; - for (var t = 0; t < tasks.Length; t++) - { - var task = tasks[t]; - - if (task.IsFaulted) - { - downloadExceptions.TryAdd(task.Id, task.Exception); - - if (restartedThreads <= maxRestartedThreads) - { - tasks[t] = StartNewDownloadThread(videoPartsQueue, baseUrl, downloadFolder, vodAge, cancellationToken); - restartedThreads++; - } - } - - if (allThreadsExited && !task.IsCompleted) - { - allThreadsExited = false; - } - } - - await Task.Delay(300, cancellationToken); - } while (!allThreadsExited); - - if (restartedThreads == maxRestartedThreads) - { - throw new AggregateException("The download thread restart limit was reached.", downloadExceptions.Values); - } - - return downloadExceptions; - } - - private void LogDownloadThreadExceptions(Dictionary downloadExceptions) - { - if (downloadExceptions.Count == 0) - return; - - var culpritList = new List(); - var sb = new StringBuilder(); - foreach (var downloadException in downloadExceptions.Values) - { - var ex = downloadException switch - { - AggregateException { InnerException: { } innerException } => innerException, - _ => downloadException - }; - - // Try to only log exceptions from different sources - var culprit = ex.TargetSite?.Name; - if (string.IsNullOrEmpty(culprit) || culpritList.Contains(culprit)) - continue; - - sb.EnsureCapacity(sb.Capacity + ex.Message.Length + culprit.Length + 6); - sb.Append(", "); - sb.Append(ex.Message); - sb.Append(" at "); - sb.Append(culprit); - culpritList.Add(culprit); - } - - if (sb.Length == 0) - { - return; - } - - sb.Replace(",", $"{downloadExceptions.Count} errors were encountered while downloading:", 0, 1); - _progress.Report(new ProgressReport(ReportType.Log, sb.ToString())); - } - - private async Task VerifyDownloadedParts(List videoParts, string baseUrl, string downloadFolder, double vodAge, CancellationToken cancellationToken) - { - var failedParts = new List(); - var partCount = videoParts.Count; - var doneCount = 0; - - foreach (var part in videoParts) - { - if (!VerifyVideoPart(downloadFolder, part)) - { - failedParts.Add(part); - } - - doneCount++; - var percent = (int)(doneCount / (double)partCount * 100); - _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Verifying Parts {percent}% [3/5]")); - _progress.Report(new ProgressReport(percent)); - - cancellationToken.ThrowIfCancellationRequested(); - } - - if (failedParts.Count != 0) - { - if (failedParts.Count == videoParts.Count) - { - // Every video part returned corrupted, probably a false positive. - return; - } - - _progress.Report(new ProgressReport(ReportType.Log, $"The following parts will be redownloaded: {string.Join(", ", failedParts)}")); - await DownloadVideoPartsAsync(failedParts, baseUrl, downloadFolder, vodAge, cancellationToken); - } - } - - private static bool VerifyVideoPart(string downloadFolder, string part) - { - const int TS_PACKET_LENGTH = 188; // MPEG TS packets are made of a header and a body: [ 4B ][ 184B ] - https://tsduck.io/download/docs/mpegts-introduction.pdf - - var partFile = Path.Combine(downloadFolder, RemoveQueryString(part)); - if (!File.Exists(partFile)) - { - return false; - } - - using var fs = File.Open(partFile, FileMode.Open, FileAccess.Read, FileShare.None); - var fileLength = fs.Length; - if (fileLength == 0 || fileLength % TS_PACKET_LENGTH != 0) - { - return false; - } - - return true; - } - - private int RunFfmpegVideoCopy(string downloadFolder, string metadataPath, double seekTime, double startOffset, double seekDuration) - { - var process = new Process - { - StartInfo = - { - FileName = downloadOptions.FfmpegPath, - Arguments = string.Format( - "-hide_banner -stats -y -avoid_negative_ts make_zero " + (downloadOptions.CropBeginning ? "-ss {2} " : "") + "-i \"{0}\" -i \"{1}\" -map_metadata 1 -analyzeduration {3} -probesize {3} " + (downloadOptions.CropEnding ? "-t {4} " : "") + "-c:v copy \"{5}\"", - Path.Combine(downloadFolder, "output.ts"), metadataPath, (seekTime - startOffset).ToString(CultureInfo.InvariantCulture), int.MaxValue, seekDuration.ToString(CultureInfo.InvariantCulture), Path.GetFullPath(downloadOptions.Filename)), - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardInput = false, - RedirectStandardOutput = true, - RedirectStandardError = true - } - }; - - var encodingTimeRegex = new Regex(@"(?<=time=)(\d\d):(\d\d):(\d\d)\.(\d\d)", RegexOptions.Compiled); - var logQueue = new ConcurrentQueue(); - - process.ErrorDataReceived += (sender, e) => - { - if (e.Data is null) - return; - - logQueue.Enqueue(e.Data); // We cannot use -report ffmpeg arg because it redirects stderr - - HandleFfmpegOutput(e.Data, encodingTimeRegex, seekDuration, _progress); - }; - - process.Start(); - process.BeginErrorReadLine(); - - using var logWriter = File.AppendText(Path.Combine(downloadFolder, "ffmpegLog.txt")); - do // We cannot handle logging inside the ErrorDataReceived lambda because more than 1 can come in at once and cause a race condition. lay295#598 - { - Thread.Sleep(330); - while (!logQueue.IsEmpty && logQueue.TryDequeue(out var logMessage)) - { - logWriter.WriteLine(logMessage); - } - } while (!process.HasExited || !logQueue.IsEmpty); - - return process.ExitCode; - } - - private static void HandleFfmpegOutput(string output, Regex encodingTimeRegex, double videoLength, IProgress progress) - { - var encodingTimeMatch = encodingTimeRegex.Match(output); - if (!encodingTimeMatch.Success) - return; - - // TimeSpan.Parse insists that hours cannot be greater than 24, thus we must use the TimeSpan ctor. - if (!int.TryParse(encodingTimeMatch.Groups[1].ValueSpan, out var hours)) return; - if (!int.TryParse(encodingTimeMatch.Groups[2].ValueSpan, out var minutes)) return; - if (!int.TryParse(encodingTimeMatch.Groups[3].ValueSpan, out var seconds)) return; - if (!int.TryParse(encodingTimeMatch.Groups[4].ValueSpan, out var milliseconds)) return; - var encodingTime = new TimeSpan(0, hours, minutes, seconds, milliseconds); - - var percent = (int)Math.Round(encodingTime.TotalSeconds / videoLength * 100); - - // Apparently it is possible for the percent to not be within the range of 0-100. lay295#716 - if (percent is < 0 or > 100) - { - progress.Report(new ProgressReport(ReportType.SameLineStatus, "Finalizing Video... [4/4]")); - progress.Report(new ProgressReport(0)); - } - else - { - progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Finalizing Video {percent}% [4/4]")); - progress.Report(new ProgressReport(percent)); - } - } - - private async Task DownloadVideoPartAsync(string baseUrl, string videoPartName, string downloadFolder, double vodAge, int throttleKib, CancellationToken cancellationToken) - { - bool tryUnmute = vodAge < 24; - int errorCount = 0; - int timeoutCount = 0; - while (true) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - if (tryUnmute && videoPartName.Contains("-muted")) - { - await DownloadFileTaskAsync(baseUrl + videoPartName.Replace("-muted", ""), Path.Combine(downloadFolder, RemoveQueryString(videoPartName)), throttleKib, cancellationToken); - } - else - { - await DownloadFileTaskAsync(baseUrl + videoPartName, Path.Combine(downloadFolder, RemoveQueryString(videoPartName)), throttleKib, cancellationToken); - } - - return; - } - catch (HttpRequestException ex) when (tryUnmute && ex.StatusCode is HttpStatusCode.Forbidden) - { - tryUnmute = false; - } - catch (HttpRequestException) - { - if (++errorCount > 10) - { - throw new HttpRequestException($"Video part {videoPartName} failed after 10 retries"); - } - - await Task.Delay(1_000 * errorCount, cancellationToken); - } - catch (TaskCanceledException ex) when (ex.Message.Contains("HttpClient.Timeout")) - { - if (++timeoutCount > 3) - { - throw new HttpRequestException($"Video part {videoPartName} timed out 3 times"); - } - - await Task.Delay(5_000 * timeoutCount, cancellationToken); - } - } - } - - private async Task<(List videoParts, double vodAge)> GetVideoPartsList(string playlistUrl, List> videoList, CancellationToken cancellationToken) - { - string[] videoChunks = (await _httpClient.GetStringAsync(playlistUrl, cancellationToken)).Split('\n'); - - double vodAge = 25; - - try - { - vodAge = (DateTimeOffset.UtcNow - DateTimeOffset.Parse(videoChunks.First(x => x.StartsWith("#ID3-EQUIV-TDTG:")).Replace("#ID3-EQUIV-TDTG:", ""))).TotalHours; - } - catch { } - - for (int i = 0; i < videoChunks.Length; i++) - { - if (videoChunks[i].StartsWith("#EXTINF")) - { - if (videoChunks[i + 1].StartsWith("#EXT-X-BYTERANGE")) - { - if (videoList.Any(x => x.Key == videoChunks[i + 2])) - { - KeyValuePair pair = videoList.Where(x => x.Key == videoChunks[i + 2]).First(); - pair = new KeyValuePair(pair.Key, pair.Value + Double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture)); - } - else - { - videoList.Add(new KeyValuePair(videoChunks[i + 2], Double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); - } - } - else - { - videoList.Add(new KeyValuePair(videoChunks[i + 1], Double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); - } - } - } - - List> videoListCropped = GenerateCroppedVideoList(videoList, downloadOptions); - - List videoParts = new List(videoListCropped.Count); - foreach (var part in videoListCropped) - { - videoParts.Add(part.Key); - } - - return (videoParts, vodAge); - } - - private async Task<(string url, int bandwidth)> GetPlaylistUrl() - { - GqlVideoTokenResponse accessToken = await TwitchHelper.GetVideoToken(downloadOptions.Id, downloadOptions.Oauth); - - if (accessToken.data.videoPlaybackAccessToken is null) - { - throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); - } - - string[] videoPlaylist = await TwitchHelper.GetVideoPlaylist(downloadOptions.Id, accessToken.data.videoPlaybackAccessToken.value, accessToken.data.videoPlaybackAccessToken.signature); - if (videoPlaylist[0].Contains("vod_manifest_restricted")) - { - throw new NullReferenceException("Insufficient access to VOD, OAuth may be required."); - } - - var videoQualities = new List>(); - - for (int i = 0; i < videoPlaylist.Length; i++) - { - if (videoPlaylist[i].Contains("#EXT-X-MEDIA")) - { - string lastPart = videoPlaylist[i].Substring(videoPlaylist[i].IndexOf("NAME=\"") + 6); - string stringQuality = lastPart.Substring(0, lastPart.IndexOf('"')); - - var bandwidthStartIndex = videoPlaylist[i + 1].IndexOf("BANDWIDTH=") + 10; - var bandwidthEndIndex = videoPlaylist[i + 1].IndexOf(',') - bandwidthStartIndex; - int.TryParse(videoPlaylist[i + 1].Substring(bandwidthStartIndex, bandwidthEndIndex), out var bandwidth); - - if (!videoQualities.Any(x => x.Key.Equals(stringQuality))) - { - videoQualities.Add(new KeyValuePair(stringQuality, (videoPlaylist[i + 2], bandwidth))); - } - } - } - - if (downloadOptions.Quality != null && videoQualities.Any(x => x.Key.StartsWith(downloadOptions.Quality))) - { - return videoQualities.Last(x => x.Key.StartsWith(downloadOptions.Quality)).Value; - } - - // Unable to find specified quality, defaulting to highest quality - return videoQualities.First().Value; - } - - /// - /// Downloads the requested to the without storing it in memory. - /// - /// The url of the file to download. - /// The path to the file where download will be saved. - /// The maximum download speed in kibibytes per second, or -1 for no maximum. - /// The cancellation token to cancel the operation. - private async Task DownloadFileTaskAsync(string url, string destinationFile, int throttleKib, CancellationToken cancellationToken = default) - { - var request = new HttpRequestMessage(HttpMethod.Get, url); - - using var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - - switch (throttleKib) - { - case -1: - { - await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); - await response.Content.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); - break; - } - default: - { - try - { - await using var throttledStream = new ThrottledStream(await response.Content.ReadAsStreamAsync(cancellationToken), throttleKib); - await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); - await throttledStream.CopyToAsync(fs, cancellationToken).ConfigureAwait(false); - } - catch (IOException e) when (e.Message.Contains("EOF")) - { - // The throttled stream throws when it reads an unexpected EOF, try again without the limiter - // TODO: Log this somehow - await Task.Delay(2_000, cancellationToken); - goto case -1; - } - break; - } - } - } - - private async Task CombineVideoParts(string downloadFolder, List videoParts, CancellationToken cancellationToken) - { - DriveInfo outputDrive = DriveHelper.GetOutputDrive(downloadFolder); - string outputFile = Path.Combine(downloadFolder, "output.ts"); - - int partCount = videoParts.Count; - int doneCount = 0; - - await using var outputStream = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None); - foreach (var part in videoParts) - { - await DriveHelper.WaitForDrive(outputDrive, _progress, cancellationToken); - - string partFile = Path.Combine(downloadFolder, RemoveQueryString(part)); - if (File.Exists(partFile)) - { - await using (var fs = File.Open(partFile, FileMode.Open, FileAccess.Read, FileShare.None)) - { - await fs.CopyToAsync(outputStream, cancellationToken).ConfigureAwait(false); - } - - try - { - File.Delete(partFile); - } - catch { /* If we can't delete, oh well. It should get cleanup up later anyways */ } - } - - doneCount++; - int percent = (int)(doneCount / (double)partCount * 100); - _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Combining Parts {percent}% [4/5]")); - _progress.Report(new ProgressReport(percent)); - - cancellationToken.ThrowIfCancellationRequested(); - } - } - - //Some old twitch VODs have files with a query string at the end such as 1.ts?offset=blah which isn't a valid filename - private static string RemoveQueryString(string inputString) - { - var queryIndex = inputString.IndexOf('?'); - if (queryIndex == -1) - { - return inputString; - } - - return inputString[..queryIndex]; - } - - private static void Cleanup(string downloadFolder) - { - try - { - if (Directory.Exists(downloadFolder)) - { - Directory.Delete(downloadFolder, true); - } - } - catch (IOException) { } // Directory is probably being used by another process - } - - private static List> GenerateCroppedVideoList(List> videoList, VideoDownloadOptions downloadOptions) - { - List> returnList = new List>(videoList); - TimeSpan startCrop = TimeSpan.FromSeconds(downloadOptions.CropBeginningTime); - TimeSpan endCrop = TimeSpan.FromSeconds(downloadOptions.CropEndingTime); - - if (downloadOptions.CropBeginning) - { - double startTime = 0; - for (int i = 0; i < returnList.Count; i++) - { - if (startTime + returnList[i].Value < startCrop.TotalSeconds) - { - startTime += returnList[i].Value; - returnList.RemoveAt(i); - i--; - } - else - { - break; - } - } - } - - if (downloadOptions.CropEnding) - { - double endTime = 0.0; - videoList.ForEach(x => endTime += x.Value); - - for (int i = returnList.Count - 1; i >= 0; i--) - { - if (endTime - returnList[i].Value > endCrop.TotalSeconds) - { - endTime -= returnList[i].Value; - returnList.RemoveAt(i); - } - else - { - break; - } - } - } - - return returnList; - } - } -} \ No newline at end of file diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/ChatDownloaderFactory.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/ChatDownloaderFactory.cs new file mode 100644 index 00000000..f0697359 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/ChatDownloaderFactory.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public class ChatDownloaderFactory + { + public Progress _progress { get; } + + public ChatDownloaderFactory(Progress progress) + { + _progress = progress; + } + + public IChatDownloader Create(ChatDownloadOptions downloadOptions) + { + if (downloadOptions.VideoPlatform == VideoPlatform.Twitch) + { + return new TwitchChatDownloader(downloadOptions, _progress); + } + + if (downloadOptions.VideoPlatform == VideoPlatform.Kick) + { + return new KickChatDownloader(downloadOptions, _progress); + } + + throw new NotImplementedException(); + } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/ClipDownloaderFactory.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/ClipDownloaderFactory.cs new file mode 100644 index 00000000..8d1a06cf --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/ClipDownloaderFactory.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public class ClipDownloaderFactory + { + public Progress _progress { get; } + + public ClipDownloaderFactory(Progress progress) + { + _progress = progress; + } + + public IClipDownloader Create(ClipDownloadOptions downloadOptions) + { + if (downloadOptions.VideoPlatform == VideoPlatform.Twitch) + { + return new TwitchClipDownloader(downloadOptions, _progress); + } + + if (downloadOptions.VideoPlatform == VideoPlatform.Kick) + { + return new KickClipDownloader(downloadOptions, _progress); + } + + throw new NotImplementedException(); + } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/IChatDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IChatDownloader.cs new file mode 100644 index 00000000..ce832051 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IChatDownloader.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public interface IChatDownloader + { + Task DownloadAsync(CancellationToken cancellationToken); + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/IClipDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IClipDownloader.cs new file mode 100644 index 00000000..d38075c0 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IClipDownloader.cs @@ -0,0 +1,10 @@ +using System.Threading; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public interface IClipDownloader + { + Task DownloadAsync(CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoDownloader.cs new file mode 100644 index 00000000..703957a8 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoDownloader.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public interface IVideoDownloader + { + Task DownloadAsync(CancellationToken cancellationToken); + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoInfo.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoInfo.cs new file mode 100644 index 00000000..ce6c7103 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/IVideoInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public interface IVideoInfo + { + public string ThumbnailUrl { get; } + public DateTime CreatedAt { get; } + public string StreamerName { get; } + public string Title { get; } + public int Duration { get; } + public int ViewCount { get; } + public string Game { get; } + public string VideoUrl { get; } + public List VideoQualities { get; set; } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoDownloaderFactory.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoDownloaderFactory.cs new file mode 100644 index 00000000..c14bffcf --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoDownloaderFactory.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public class VideoDownloaderFactory + { + public Progress _progress { get; } + + public VideoDownloaderFactory(Progress progress) + { + _progress = progress; + } + + public IVideoDownloader Create(VideoDownloadOptions downloadOptions) + { + if (downloadOptions.VideoPlatform == VideoPlatform.Twitch) + { + return new TwitchVideoDownloader(downloadOptions, _progress); + } + + if (downloadOptions.VideoPlatform == VideoPlatform.Kick) + { + return new KickVideoDownloader(downloadOptions, _progress); + } + + throw new NotImplementedException(); + } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoQuality.cs b/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoQuality.cs new file mode 100644 index 00000000..4d48993e --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Interfaces/VideoQuality.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.VideoPlatforms.Interfaces +{ + public class VideoQuality + { + public string Quality { get; set; } + public double Framerate { get; set; } + public string SourceUrl { get; set; } + public int Bandwidth { get; set; } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickChatDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickChatDownloader.cs new file mode 100644 index 00000000..32f0cc96 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickChatDownloader.cs @@ -0,0 +1,409 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Chat; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using System.Text.Json; +using Microsoft.Extensions.FileSystemGlobbing.Internal; +using System.Globalization; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders +{ + public sealed class KickChatDownloader : IChatDownloader + { + private readonly ChatDownloadOptions downloadOptions; + private readonly IProgress _progress; + + private static readonly HttpClient HttpClient = new(); + private static readonly string emotePattern = @"\[emote:(\d+):([^\]]+)\]"; + + public int StreamerId { get; set; } + public string VideoId { get; set; } + + public KickChatDownloader(ChatDownloadOptions chatDownloadOptions, IProgress progress) + { + downloadOptions = chatDownloadOptions; + downloadOptions.TempFolder = Path.Combine( + string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, + "TwitchDownloader"); + _progress = progress; + + VideoId = downloadOptions.Id; + } + + private async Task> DownloadSection(int streamerId, DateTime videoCreatedAt, double videoStart, double videoEnd, IProgress progress, ChatFormat format, CancellationToken cancellationToken) + { + var comments = new List(); + double videoDuration = videoEnd - videoStart; + double latestMessage = videoStart - 1; + string cursor = ""; + int errorCount = 0; + + while (latestMessage < videoEnd) + { + cancellationToken.ThrowIfCancellationRequested(); + + KickChatResponse chatResponse; + try + { + DateTime dateTime; + if (String.IsNullOrWhiteSpace(cursor)) + { + dateTime = videoCreatedAt.AddSeconds(videoStart); + } + else + { + DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(cursor) / 1000); + dateTime = dateTimeOffset.UtcDateTime; + } + + string formattedTime = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ"); + string response = await Task.Run(() => CurlImpersonate.GetCurlReponse($"https://kick.com/api/v2/channels/{streamerId}/messages?start_time={formattedTime}")); + chatResponse = JsonSerializer.Deserialize(response); + Console.WriteLine(formattedTime); + + if (chatResponse.status.error) + { + throw new Exception("Kick API Error: " + chatResponse.status.message); + } + + errorCount = 0; + } + catch (Exception) + { + if (++errorCount > 10) + { + throw; + } + + await Task.Delay(1_000 * errorCount, cancellationToken); + continue; + } + + cursor = chatResponse.data.cursor; + + var convertedComments = ConvertComments(chatResponse.data.messages, videoCreatedAt, format); + comments.EnsureCapacity(Math.Min(0, comments.Capacity + convertedComments.Count)); + foreach (var comment in convertedComments) + { + if (latestMessage < videoEnd && comment.content_offset_seconds > videoStart) + comments.Add(comment); + + latestMessage = comment.content_offset_seconds; + } + + Console.WriteLine(latestMessage); + + if (progress != null) + { + int percent = (int)Math.Floor((latestMessage - videoStart) / videoDuration * 100); + progress.Report(new ProgressReport() { ReportType = ReportType.Percent, Data = percent }); + } + } + + return comments; + } + + private List ConvertComments(List messages, DateTime videoCreatedAt, ChatFormat format) + { + List returnList = new List(messages.Count); + videoCreatedAt = videoCreatedAt.ToUniversalTime(); + foreach (var comment in messages) + { + var newComment = new Comment + { + _id = comment.id, + created_at = comment.created_at, + channel_id = StreamerId.ToString(), + content_type = "video", + content_id = VideoId, + content_offset_seconds = comment.created_at.ToUniversalTime().Subtract(videoCreatedAt).TotalSeconds, + commenter = new Commenter + { + display_name = comment.sender.username, + _id = comment.sender.id.ToString(), + name = comment.sender.slug + } + }; + + newComment.message = new() { emoticons = new(), fragments = new(), user_badges = new() }; + + List stringsInfoList = new List(); + StringBuilder replacedStringBuilder = new StringBuilder(); + int lastMatchEnd = 0; + + foreach (Match match in Regex.Matches(comment.content, emotePattern)) + { + if (lastMatchEnd != match.Index) + { + string unmatchedString = comment.content.Substring(lastMatchEnd, match.Index - lastMatchEnd); + stringsInfoList.Add(new KickStringInfo + { + Value = unmatchedString, + StartIndex = replacedStringBuilder.Length, + EndIndex = replacedStringBuilder.Length + unmatchedString.Length + }); + replacedStringBuilder.Append(unmatchedString); + } + + string emoteName = match.Groups[2].Value; + int emoteId = int.Parse(match.Groups[1].Value); + + stringsInfoList.Add(new KickStringInfo + { + Value = emoteName, + StartIndex = replacedStringBuilder.Length, + EndIndex = replacedStringBuilder.Length + emoteName.Length, + EmoteId = emoteId + }); + replacedStringBuilder.Append(emoteName + " "); + + lastMatchEnd = match.Index + match.Length; + } + + if (lastMatchEnd < comment.content.Length) + { + string remainingString = comment.content.Substring(lastMatchEnd); + stringsInfoList.Add(new KickStringInfo + { + Value = remainingString, + StartIndex = replacedStringBuilder.Length, + EndIndex = replacedStringBuilder.Length + remainingString.Length + }); + replacedStringBuilder.Append(remainingString); + } + + string replacedString = replacedStringBuilder.ToString(); + + newComment.message.body = replacedString; + newComment.message.user_color = comment.sender.identity.color; + + foreach (var fragment in stringsInfoList) + { + newComment.message.fragments.Add(new Fragment() { text = fragment.Value, emoticon = new() { emoticon_id = fragment.EmoteId?.ToString() } }); + + if (fragment.EmoteId != null) + newComment.message.emoticons.Add(new Emoticon2() { _id = fragment.EmoteId?.ToString(), begin = fragment.StartIndex, end = fragment.EndIndex }); + } + + returnList.Add(newComment); + } + + return returnList; + } + + public async Task DownloadAsync(CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(downloadOptions.Id)) + { + throw new NullReferenceException("Null or empty video/clip ID"); + } + + if (downloadOptions.DownloadFormat == ChatFormat.Html) + { + throw new NotImplementedException("Kick chat download as HTML is not currently supported"); + } + + bool vodParsed = UrlParse.TryParseVod(downloadOptions.Id, out VideoPlatform videoPlatformVod, out string vodId); + + ChatRoot chatRoot = new() + { + FileInfo = new ChatRootInfo { Version = ChatRootVersion.CurrentVersion, CreatedAt = DateTime.Now }, + streamer = new(), + video = new(), + comments = new List(), + videoPlatform = VideoPlatform.Kick + }; + + string videoId = downloadOptions.Id; + string videoTitle; + DateTime videoCreatedAt; + double videoStart = 0.0; + double videoEnd = 0.0; + double videoDuration = 0.0; + double videoTotalLength; + int viewCount; + string game; + + if (downloadOptions.DownloadType == ChatDownloadType.Video) + { + KickVideoResponse videoInfo = await KickHelper.GetVideoInfo(videoId); + if (videoInfo.id == 0) + { + throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); + } + + chatRoot.streamer.name = videoInfo.StreamerName; + chatRoot.streamer.id = videoInfo.livestream.channel.id; + StreamerId = videoInfo.livestream.channel.id; + videoTitle = videoInfo.Title; + videoCreatedAt = videoInfo.CreatedAt; + videoStart = downloadOptions.CropBeginning ? downloadOptions.CropBeginningTime : 0.0; + videoEnd = downloadOptions.CropEnding ? downloadOptions.CropEndingTime : videoInfo.Duration; + videoTotalLength = videoInfo.Duration; + viewCount = videoInfo.ViewCount; + game = videoInfo.Game ?? "Unknown"; + } + else + { + throw new NotImplementedException(); + GqlClipResponse clipInfoResponse = await TwitchHelper.GetClipInfo(videoId); + if (clipInfoResponse.data.clip.video == null || clipInfoResponse.data.clip.videoOffsetSeconds == null) + { + throw new NullReferenceException("Invalid VOD for clip, deleted/expired VOD possibly?"); + } + + videoId = clipInfoResponse.data.clip.video.id; + downloadOptions.CropBeginning = true; + downloadOptions.CropBeginningTime = (int)clipInfoResponse.data.clip.videoOffsetSeconds; + downloadOptions.CropEnding = true; + downloadOptions.CropEndingTime = downloadOptions.CropBeginningTime + clipInfoResponse.data.clip.durationSeconds; + chatRoot.streamer.name = clipInfoResponse.data.clip.broadcaster.displayName; + chatRoot.streamer.id = int.Parse(clipInfoResponse.data.clip.broadcaster.id); + videoTitle = clipInfoResponse.data.clip.title; + videoCreatedAt = clipInfoResponse.data.clip.createdAt; + videoStart = (int)clipInfoResponse.data.clip.videoOffsetSeconds; + videoEnd = (int)clipInfoResponse.data.clip.videoOffsetSeconds + clipInfoResponse.data.clip.durationSeconds; + videoTotalLength = clipInfoResponse.data.clip.durationSeconds; + viewCount = clipInfoResponse.data.clip.viewCount; + game = clipInfoResponse.data.clip.game?.displayName ?? "Unknown"; + } + + chatRoot.video.id = videoId; + chatRoot.video.title = videoTitle; + chatRoot.video.created_at = videoCreatedAt; + chatRoot.video.start = videoStart; + chatRoot.video.end = videoEnd; + chatRoot.video.length = videoTotalLength; + chatRoot.video.viewCount = viewCount; + chatRoot.video.game = game; + videoDuration = videoEnd - videoStart; + + int downloadChunks = 100; + var tasks = new List>>>(); + var percentages = new int[downloadChunks]; + + double chunk = videoDuration / downloadChunks; + for (int i = 0; i < downloadChunks; i++) + { + int tc = i; + + Progress taskProgress = null; + if (!downloadOptions.Silent) + { + taskProgress = new Progress(progressReport => + { + if (progressReport.ReportType != ReportType.Percent) + { + _progress.Report(progressReport); + } + else + { + var percent = (int)progressReport.Data; + if (percent > 100) + { + percent = 100; + } + + percentages[tc] = percent; + + percent = 0; + for (int j = 0; j < downloadChunks; j++) + { + percent += percentages[j]; + } + + percent /= downloadChunks; + + _progress.Report(new ProgressReport() { ReportType = ReportType.SameLineStatus, Data = $"Downloading {percent}%" }); + _progress.Report(new ProgressReport() { ReportType = ReportType.Percent, Data = percent }); + } + }); + } + + double start = videoStart + chunk * i; + tasks.Add(() => DownloadSection(StreamerId, videoCreatedAt, start, start + chunk, taskProgress, downloadOptions.DownloadFormat, cancellationToken)); + } + + /* Back to using a semaphore, at least for Kick chat downloading. + * Ran into issues just having number of tasks equaling number of connection count + * due to long running stragglers (last 10% took longer than first 90%) */ + var results = await RunTasksWithLimitedConcurrency(downloadOptions.ConnectionCount, tasks); + + var sortedComments = new List(results.Length); + foreach (var commentTask in results) + { + sortedComments.AddRange(commentTask); + } + + sortedComments.Sort(new SortedCommentComparer()); + + chatRoot.comments = sortedComments.DistinctBy(x => x._id).ToList(); + + if (downloadOptions.EmbedData && downloadOptions.DownloadFormat is ChatFormat.Json or ChatFormat.Html) + { + //TODO: Implement emote embeds + } + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Writing output file")); + switch (downloadOptions.DownloadFormat) + { + case ChatFormat.Json: + await ChatJson.SerializeAsync(downloadOptions.Filename, chatRoot, downloadOptions.Compression, cancellationToken); + break; + case ChatFormat.Html: + await ChatHtml.SerializeAsync(downloadOptions.Filename, chatRoot, downloadOptions.EmbedData, cancellationToken); + break; + case ChatFormat.Text: + await ChatText.SerializeAsync(downloadOptions.Filename, chatRoot, downloadOptions.TimeFormat); + break; + default: + throw new NotSupportedException($"{downloadOptions.DownloadFormat} is not a supported output format."); + } + } + + static async Task[]> RunTasksWithLimitedConcurrency(int degreeOfParallelism, List>>> tasks) + { + var semaphore = new SemaphoreSlim(degreeOfParallelism); + var taskList = new List>>(); + + foreach (var task in tasks) + { + await semaphore.WaitAsync(); + + taskList.Add(Task.Run(async () => + { + try + { + return await task(); + } + finally + { + semaphore.Release(); + } + })); + } + + var results = await Task.WhenAll(taskList); + return results; + } + } + + public class KickStringInfo + { + public string Value { get; set; } + public int StartIndex { get; set; } + public int EndIndex { get; set; } + public int? EmoteId { get; set; } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickClipDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickClipDownloader.cs new file mode 100644 index 00000000..3355345e --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickClipDownloader.cs @@ -0,0 +1,153 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Extensions; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders +{ + public sealed class KickClipDownloader : IClipDownloader + { + private readonly ClipDownloadOptions downloadOptions; + private readonly IProgress _progress; + private static readonly HttpClient HttpClient = new(); + + public KickClipDownloader(ClipDownloadOptions clipDownloadOptions, IProgress progress) + { + downloadOptions = clipDownloadOptions; + _progress = progress; + downloadOptions.TempFolder = Path.Combine( + string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, + "TwitchDownloader"); + } + + public async Task DownloadAsync(CancellationToken cancellationToken) + { + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Fetching Clip Info")); + + cancellationToken.ThrowIfCancellationRequested(); + + KickClipResponse response = await KickHelper.GetClipInfo(downloadOptions.Id); + bool alreadyEncoded = response.VideoUrl.EndsWith(".mp4"); // Kick clips can point to an m3u8 playlist or an already encoded mp4 + + cancellationToken.ThrowIfCancellationRequested(); + + var clipDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; + if (!clipDirectory.Exists) + { + TwitchHelper.CreateDirectory(clipDirectory.FullName); + } + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Downloading Clip 0%")); + + void DownloadProgressHandler(StreamCopyProgress streamProgress) + { + var percent = (int)(streamProgress.BytesCopied / (double)streamProgress.SourceLength * 100); + _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Downloading Clip {percent}%")); + _progress.Report(new ProgressReport(percent)); + } + + if (!downloadOptions.EncodeMetadata && alreadyEncoded) + { + await DownloadTools.DownloadClipFileTaskAsync(response.VideoUrl, downloadOptions.Filename, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); + return; + } + + if (!Directory.Exists(downloadOptions.TempFolder)) + { + TwitchHelper.CreateDirectory(downloadOptions.TempFolder); + } + + var tempDownloadFolder = Path.Combine(downloadOptions.TempFolder, $"clip_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}_{Path.GetRandomFileName()}"); + TwitchHelper.CreateDirectory(tempDownloadFolder); + var tempFile = Path.Combine(tempDownloadFolder, $"clip_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}_{Path.GetRandomFileName()}"); + try + { + if (!alreadyEncoded) + { + string playlistData = await KickHelper.GetPlaylistData(response.VideoUrl); + List downloadUrls = KickHelper.GetDownloadUrls(response.VideoUrl, playlistData); + + await using var outputStream = new FileStream(tempFile, FileMode.Create, FileAccess.Write, FileShare.None); + for (int i = 0; i < downloadUrls.Count; i++) + { + string downloadPath = Path.Combine(tempDownloadFolder, Path.GetFileName(downloadUrls[i].DownloadUrl)); + await DownloadTools.DownloadClipFileTaskAsync(downloadUrls[i].DownloadUrl, downloadPath, downloadOptions.ThrottleKib, null, cancellationToken); + await using (var fs = File.Open(downloadPath, FileMode.Open, FileAccess.Read, FileShare.None)) + { + fs.Seek(downloadUrls[i].StartByteOffset, SeekOrigin.Begin); + byte[] buffer = new byte[downloadUrls[i].ByteRangeLength + 1]; + await fs.ReadAsync(buffer, 0, downloadUrls[i].ByteRangeLength); + await outputStream.WriteAsync(buffer, cancellationToken); + } + var percent = (int)((i+1) / (double)downloadUrls.Count * 100); + _progress.Report(new ProgressReport(ReportType.SameLineStatus, $"Downloading Clip {percent}%")); + _progress.Report(new ProgressReport(percent)); + } + } + else + { + await DownloadTools.DownloadClipFileTaskAsync(response.VideoUrl, tempFile, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); + } + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Encoding Clip Metadata 0%")); + _progress.Report(new ProgressReport(0)); + + await EncodeClipMetadata(tempFile, downloadOptions.Filename, response, cancellationToken); + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Encoding Clip Metadata 100%")); + _progress.Report(new ProgressReport(100)); + } + finally + { + File.Delete(tempFile); + } + } + + private Action DownloadProgressHandler(int i) + { + throw new NotImplementedException(); + } + + private async Task EncodeClipMetadata(string inputFile, string destinationFile, KickClipResponse clipInfo, CancellationToken cancellationToken) + { + var metadataFile = $"{Path.GetFileNameWithoutExtension(inputFile)}_metadata{Path.GetExtension(inputFile)}"; + + try + { + await FfmpegMetadata.SerializeAsync(metadataFile, clipInfo.StreamerName, downloadOptions.Id, clipInfo.Title, clipInfo.CreatedAt, + clipInfo.ViewCount, cancellationToken: cancellationToken); + + var process = new Process + { + StartInfo = + { + FileName = downloadOptions.FfmpegPath, + Arguments = $"-i \"{inputFile}\" -i \"{metadataFile}\" -map_metadata 1 -y -c copy \"{destinationFile}\"", + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = false, + RedirectStandardOutput = true, + RedirectStandardError = true + } + }; + + process.Start(); + await process.WaitForExitAsync(cancellationToken); + } + finally + { + File.Delete(metadataFile); + } + } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickVideoDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickVideoDownloader.cs new file mode 100644 index 00000000..52b41cc7 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/Downloaders/KickVideoDownloader.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick.Downloaders +{ + public class KickVideoDownloader : IVideoDownloader + { + private readonly VideoDownloadOptions downloadOptions; + private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(30) }; + private readonly IProgress _progress; + private bool _shouldClearCache = true; + + public KickVideoDownloader(VideoDownloadOptions videoDownloadOptions, IProgress progress) + { + downloadOptions = videoDownloadOptions; + downloadOptions.TempFolder = Path.Combine( + string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, + "TwitchDownloader"); + _progress = progress; + } + + public async Task DownloadAsync(CancellationToken cancellationToken) + { + TwitchHelper.CleanupUnmanagedCacheFiles(downloadOptions.TempFolder, _progress); + + string downloadFolder = Path.Combine( + downloadOptions.TempFolder, + $"{downloadOptions.Id}_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Fetching Video Info [1/5]")); + + try + { + ServicePointManager.DefaultConnectionLimit = downloadOptions.DownloadThreads; + IVideoInfo videoInfo = await KickHelper.GetVideoInfo(downloadOptions.Id); + var (playlistUrl, bandwidth) = GetPlaylistUrl(videoInfo); + string baseUrl = playlistUrl.Substring(0, playlistUrl.LastIndexOf('/') + 1); + + var videoLength = TimeSpan.FromSeconds(videoInfo.Duration); + DriveHelper.CheckAvailableStorageSpace(downloadOptions, bandwidth, videoLength, _progress); + + List> videoList = new List>(); + List videoPartsList = await GetVideoPartsList(playlistUrl, videoList, cancellationToken); + + if (Directory.Exists(downloadFolder)) + Directory.Delete(downloadFolder, true); + TwitchHelper.CreateDirectory(downloadFolder); + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Downloading 0% [2/5]")); + + await DownloadTools.DownloadVideoPartsAsync(downloadOptions, videoPartsList, baseUrl, downloadFolder, 0, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Verifying Parts 0% [3/5]" }); + + await DownloadTools.VerifyDownloadedParts(downloadOptions, videoPartsList, baseUrl, downloadFolder, 0, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Combining Parts 0% [4/5]" }); + + await DownloadTools.CombineVideoParts(downloadFolder, videoPartsList, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Finalizing Video 0% [5/5]" }); + + double startOffset = 0.0; + + for (int i = 0; i < videoList.Count; i++) + { + if (videoList[i].Key == videoPartsList[0]) + break; + + startOffset += videoList[i].Value; + } + + double seekTime = downloadOptions.CropBeginningTime; + double seekDuration = Math.Round(downloadOptions.CropEndingTime - seekTime); + + string metadataPath = Path.Combine(downloadFolder, "metadata.txt"); + await FfmpegMetadata.SerializeAsync(metadataPath, videoInfo.StreamerName, downloadOptions.Id.ToString(), videoInfo.Title, + videoInfo.CreatedAt, videoInfo.ViewCount, startOffset, null, cancellationToken); + + var finalizedFileDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; + if (!finalizedFileDirectory.Exists) + { + TwitchHelper.CreateDirectory(finalizedFileDirectory.FullName); + } + + int ffmpegExitCode; + var ffmpegRetries = 0; + do + { + ffmpegExitCode = await Task.Run(() => DownloadTools.RunFfmpegVideoCopy(downloadOptions, downloadFolder, metadataPath, seekTime, startOffset, seekDuration, _progress), cancellationToken); + if (ffmpegExitCode != 0) + { + _progress.Report(new ProgressReport(ReportType.Log, $"Failed to finalize video (code {ffmpegExitCode}), retrying in 10 seconds...")); + await Task.Delay(10_000, cancellationToken); + } + } while (ffmpegExitCode != 0 && ffmpegRetries++ < 1); + + if (ffmpegExitCode != 0 || !File.Exists(downloadOptions.Filename)) + { + _shouldClearCache = false; + throw new Exception($"Failed to finalize video. The download cache has not been cleared and can be found at {downloadFolder} along with a log file."); + } + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Finalizing Video 100% [5/5]")); + _progress.Report(new ProgressReport(100)); + } + finally + { + if (_shouldClearCache) + { + DownloadTools.Cleanup(downloadFolder); + } + } + } + + private async Task> GetVideoPartsList(string playlistUrl, List> videoList, CancellationToken cancellationToken) + { + string[] videoChunks = (await _httpClient.GetStringAsync(playlistUrl, cancellationToken)).Split('\n'); + + for (int i = 0; i < videoChunks.Length; i++) + { + if (videoChunks[i].StartsWith("#EXTINF")) + { + if (videoChunks[i + 1].StartsWith("#EXT-X-BYTERANGE")) + { + if (videoList.Any(x => x.Key == videoChunks[i + 2])) + { + KeyValuePair pair = videoList.Where(x => x.Key == videoChunks[i + 2]).First(); + pair = new KeyValuePair(pair.Key, pair.Value + double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture)); + } + else + { + videoList.Add(new KeyValuePair(videoChunks[i + 2], double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); + } + } + else + { + videoList.Add(new KeyValuePair(videoChunks[i + 1], double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); + } + } + } + + List> videoListCropped = DownloadTools.GenerateCroppedVideoList(videoList, downloadOptions); + + List videoParts = new List(videoListCropped.Count); + foreach (var part in videoListCropped) + { + videoParts.Add(part.Key); + } + + return videoParts; + } + + private (string url, int bandwidth) GetPlaylistUrl(IVideoInfo videoInfo) + { + if (downloadOptions.Quality != null && videoInfo.VideoQualities.Any(x => x.Quality.StartsWith(downloadOptions.Quality))) + { + VideoQuality quality = videoInfo.VideoQualities.Last(x => x.Quality.StartsWith(downloadOptions.Quality)); + return (quality.SourceUrl, quality.Bandwidth); + } + + // Unable to find specified quality, defaulting to highest quality + VideoQuality firstQuality = videoInfo.VideoQualities.First(); + return (firstQuality.SourceUrl, firstQuality.Bandwidth); + } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/KickChatResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/KickChatResponse.cs new file mode 100644 index 00000000..28fd025c --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/KickChatResponse.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick +{ + public class KickChatData + { + public List messages { get; set; } + public string cursor { get; set; } + public object pinned_message { get; set; } + } + + public class KickIdentity + { + public string color { get; set; } + public List badges { get; set; } + } + + public class KickMessage + { + public string id { get; set; } + public int chat_id { get; set; } + public int user_id { get; set; } + public string content { get; set; } + public string type { get; set; } + public object metadata { get; set; } + public DateTime created_at { get; set; } + public KickSender sender { get; set; } + } + + public class KickChatResponse + { + public KickChatResponseStatus status { get; set; } + public KickChatData data { get; set; } + } + + public class KickSender + { + public int id { get; set; } + public string slug { get; set; } + public string username { get; set; } + public KickIdentity identity { get; set; } + } + + public class KickChatResponseStatus + { + public bool error { get; set; } + public int code { get; set; } + public string message { get; set; } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipResponse.cs new file mode 100644 index 00000000..19c85548 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipResponse.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick +{ + public class Category + { + public int id { get; set; } + public string name { get; set; } + public string slug { get; set; } + public string responsive { get; set; } + public string banner { get; set; } + public string parent_category { get; set; } + } + + public class Channel + { + public int id { get; set; } + public string username { get; set; } + public string slug { get; set; } + public string profile_picture { get; set; } + } + + public class Clip + { + public string id { get; set; } + public string livestream_id { get; set; } + public string category_id { get; set; } + public int channel_id { get; set; } + public int user_id { get; set; } + public string title { get; set; } + public string clip_url { get; set; } + public string thumbnail_url { get; set; } + public string privacy { get; set; } + public int likes { get; set; } + public bool liked { get; set; } + public int views { get; set; } + public int duration { get; set; } + public DateTime started_at { get; set; } + public DateTime created_at { get; set; } + public bool is_mature { get; set; } + public string video_url { get; set; } + public int view_count { get; set; } + public int likes_count { get; set; } + public Category category { get; set; } + public Creator creator { get; set; } + public Channel channel { get; set; } + } + + public class Creator + { + public int id { get; set; } + public string username { get; set; } + public string slug { get; set; } + public object profile_picture { get; set; } + } + + public class KickClipResponse : IVideoInfo + { + public Clip clip { get; set; } + + public string message { get; set; } + + public string ThumbnailUrl => clip?.thumbnail_url; + + public DateTime CreatedAt => clip?.created_at ?? DateTime.MinValue; + + public string StreamerName => clip?.channel?.username; + + public string Title => clip?.title; + + public int Duration => clip?.duration ?? 0; + + public int ViewCount => clip?.views ?? 0; + + public string Game => clip?.category?.name; + + public string VideoUrl => clip?.video_url; + + public List VideoQualities { get; set; } + } +} diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipSegment.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipSegment.cs new file mode 100644 index 00000000..ccbb4f96 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/KickClipSegment.cs @@ -0,0 +1,9 @@ +namespace TwitchDownloaderCore.VideoPlatforms.Kick +{ + public class KickClipSegment + { + public string DownloadUrl { get; set; } + public int StartByteOffset { get; set; } + public int ByteRangeLength { get; set; } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/KickHelper.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/KickHelper.cs new file mode 100644 index 00000000..b28ba43c --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/KickHelper.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick +{ + public class KickHelper + { + private static readonly HttpClient HttpClient = new(); + public static async Task GetClipInfo(string clipId) + { + string response = await Task.Run(() => CurlImpersonate.GetCurlReponse($"https://kick.com/api/v2/clips/{clipId}")); + KickClipResponse clipResponse = JsonSerializer.Deserialize(response); + + if (clipResponse.clip == null) + { + throw new Exception(clipResponse?.message ?? "Unable to get clip info"); + } + + return clipResponse; + } + + public static async Task GetPlaylistData(string url) + { + var request = new HttpRequestMessage(HttpMethod.Get, url); + using var response = await HttpClient.SendAsync(request); + response.EnsureSuccessStatusCode(); + + return await response.Content.ReadAsStringAsync(); + } + + public static List GetDownloadUrls(string url, string playlistData) + { + string baseUrl = url.Substring(0, url.LastIndexOf("/")) + "/"; + List playlistLines = new List(playlistData.Split('\n')); + + List returnList = new List(); + KickClipSegment latestSegment = null; + + for (int i = 0; i < playlistLines.Count; i++) + { + if (string.IsNullOrWhiteSpace(playlistLines[i])) + continue; + + if (!playlistLines[i].StartsWith('#')) + { + if (latestSegment?.DownloadUrl == baseUrl + playlistLines[i]) + { + for (int k = i - 1; k >= 0; k--) + { + if (playlistLines[k].StartsWith("#EXT-X-BYTERANGE:")) + { + string byteRange = playlistLines[k].Substring("#EXT-X-BYTERANGE:".Length); + latestSegment.ByteRangeLength += int.Parse(byteRange.Split('@')[0]); + break; + } + } + } + else + { + if (latestSegment != null) returnList.Add(latestSegment); + latestSegment = new KickClipSegment(); + latestSegment.DownloadUrl = baseUrl + playlistLines[i]; + + for (int k = i - 1; k >= 0; k--) + { + if (playlistLines[k].StartsWith("#EXT-X-BYTERANGE:")) + { + string byteRange = playlistLines[k].Substring("#EXT-X-BYTERANGE:".Length); + latestSegment.StartByteOffset = int.Parse(byteRange.Split('@')[1]); + latestSegment.ByteRangeLength = int.Parse(byteRange.Split('@')[0]); + break; + } + } + } + } + } + + if (!string.IsNullOrEmpty(latestSegment.DownloadUrl)) + { + returnList.Add(latestSegment); + } + + return returnList; + } + + public static async Task GetVideoInfo(string videoId) + { + string response = await Task.Run(() => CurlImpersonate.GetCurlReponse($"https://kick.com/api/v1/video/{videoId}")); + KickVideoResponse videoResponse = JsonSerializer.Deserialize(response); + + if (videoResponse.id == 0) + { + throw new Exception("Unable to get video info"); + } + + string baseUrl = videoResponse.source.Substring(0, videoResponse.source.LastIndexOf('/') + 1); + + string[] playlist = (await HttpClient.GetStringAsync(videoResponse.source)).Split('\n'); + videoResponse.VideoQualities = new List(); + + for (int i = 0; i < playlist.Length; i++) + { + if (playlist[i].Contains("#EXT-X-MEDIA")) + { + string lastPart = playlist[i].Substring(playlist[i].IndexOf("NAME=\"") + 6); + string stringQuality = lastPart.Substring(0, lastPart.IndexOf('"')); + + var bandwidthStartIndex = playlist[i + 1].IndexOf("BANDWIDTH=") + 10; + var bandwidthEndIndex = playlist[i + 1].Substring(bandwidthStartIndex).IndexOf(','); + int.TryParse(playlist[i + 1].Substring(bandwidthStartIndex, bandwidthEndIndex), out var bandwidth); + + videoResponse.VideoQualities.Add(new VideoQuality { Quality = stringQuality, SourceUrl = baseUrl + playlist[i + 2], Bandwidth = bandwidth }); + } + } + + return videoResponse; + } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/VideoPlatforms/Kick/KickVideoResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Kick/KickVideoResponse.cs new file mode 100644 index 00000000..43a0af0c --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Kick/KickVideoResponse.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; + +namespace TwitchDownloaderCore.VideoPlatforms.Kick +{ + public class KickCategory + { + public int id { get; set; } + public int category_id { get; set; } + public string name { get; set; } + public string slug { get; set; } + public List tags { get; set; } + public string description { get; set; } + public string deleted_at { get; set; } + public int viewers { get; set; } + public KickCategory2 category { get; set; } + } + + public class KickCategory2 + { + public int id { get; set; } + public string name { get; set; } + public string slug { get; set; } + public string icon { get; set; } + } + + public class KickChannel + { + public int id { get; set; } + public int user_id { get; set; } + public string slug { get; set; } + public bool is_banned { get; set; } + public string playback_url { get; set; } + public string name_updated_at { get; set; } + public bool vod_enabled { get; set; } + public bool subscription_enabled { get; set; } + public int followersCount { get; set; } + public KickUser user { get; set; } + public bool can_host { get; set; } + public KickVerified verified { get; set; } + } + + public class KickLivestream + { + public int id { get; set; } + public string slug { get; set; } + public int channel_id { get; set; } + public string created_at { get; set; } + public string session_title { get; set; } + public bool is_live { get; set; } + public string risk_level_id { get; set; } + public DateTime start_time { get; set; } + public string source { get; set; } + public string twitch_channel { get; set; } + public int duration { get; set; } + public string language { get; set; } + public bool is_mature { get; set; } + public int viewer_count { get; set; } + public string thumbnail { get; set; } + public Channel channel { get; set; } + public List categories { get; set; } + } + + public class KickVideoResponse : IVideoInfo + { + public int id { get; set; } + public int live_stream_id { get; set; } + public string slug { get; set; } + public string thumb { get; set; } + public object s3 { get; set; } + public string trading_platform_id { get; set; } + public DateTime created_at { get; set; } + public DateTime updated_at { get; set; } + public string uuid { get; set; } + public int views { get; set; } + public DateTime? deleted_at { get; set; } + public string source { get; set; } + public KickLivestream livestream { get; set; } + + public string ThumbnailUrl => livestream?.thumbnail; + + public DateTime CreatedAt => livestream.start_time; + + public string StreamerName => livestream?.channel?.username; + + public string Title => livestream?.session_title; + + public int Duration => livestream?.duration == null ? 0 : livestream.duration / 1000; + + public int ViewCount => livestream?.viewer_count ?? 0; + + public string Game => livestream?.categories?.FirstOrDefault().name; + + public string VideoUrl => null; + public List VideoQualities { get; set; } + } + + public class KickUser + { + public string profilepic { get; set; } + public string bio { get; set; } + public string twitter { get; set; } + public string facebook { get; set; } + public string instagram { get; set; } + public string youtube { get; set; } + public string discord { get; set; } + public string tiktok { get; set; } + public string username { get; set; } + } + + public class KickVerified + { + public int id { get; set; } + public int channel_id { get; set; } + public DateTime created_at { get; set; } + public DateTime updated_at { get; set; } + } +} diff --git a/TwitchDownloaderCore/TwitchObjects/Api/BTTVChannelEmoteResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/BTTVChannelEmoteResponse.cs similarity index 93% rename from TwitchDownloaderCore/TwitchObjects/Api/BTTVChannelEmoteResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Api/BTTVChannelEmoteResponse.cs index 2c91158f..bacd6011 100644 --- a/TwitchDownloaderCore/TwitchObjects/Api/BTTVChannelEmoteResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/BTTVChannelEmoteResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Api +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Api { public class BTTVChannelEmoteResponse { diff --git a/TwitchDownloaderCore/TwitchObjects/Api/FFZEmote.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/FFZEmote.cs similarity index 93% rename from TwitchDownloaderCore/TwitchObjects/Api/FFZEmote.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Api/FFZEmote.cs index 76f414d6..9c62756c 100644 --- a/TwitchDownloaderCore/TwitchObjects/Api/FFZEmote.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/FFZEmote.cs @@ -1,6 +1,6 @@ using System.Text.Json.Serialization; -namespace TwitchDownloaderCore.TwitchObjects.Api +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Api { public class FFZEmote diff --git a/TwitchDownloaderCore/TwitchObjects/Api/STVChannelEmoteResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVChannelEmoteResponse.cs similarity index 97% rename from TwitchDownloaderCore/TwitchObjects/Api/STVChannelEmoteResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVChannelEmoteResponse.cs index 2ff6ad14..ccf1f3d9 100644 --- a/TwitchDownloaderCore/TwitchObjects/Api/STVChannelEmoteResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVChannelEmoteResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Api +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Api { public class STVConnection { diff --git a/TwitchDownloaderCore/TwitchObjects/Api/STVGlobalEmoteResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVGlobalEmoteResponse.cs similarity index 97% rename from TwitchDownloaderCore/TwitchObjects/Api/STVGlobalEmoteResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVGlobalEmoteResponse.cs index dbe6b7b7..7f31e4e1 100644 --- a/TwitchDownloaderCore/TwitchObjects/Api/STVGlobalEmoteResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Api/STVGlobalEmoteResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Api +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Api { public class STVData { diff --git a/TwitchDownloaderCore/TwitchObjects/ChatBadge.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatBadge.cs similarity index 96% rename from TwitchDownloaderCore/TwitchObjects/ChatBadge.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/ChatBadge.cs index 0b0cbd80..11f13da9 100644 --- a/TwitchDownloaderCore/TwitchObjects/ChatBadge.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatBadge.cs @@ -5,7 +5,7 @@ using System.IO; using System.Text.Json.Serialization; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { [Flags] public enum ChatBadgeType @@ -80,7 +80,7 @@ public void Resize(double newScale) } } -#region ImplementIDisposable + #region ImplementIDisposable public void Dispose() { @@ -110,6 +110,6 @@ private void Dispose(bool isDisposing) } } -#endregion + #endregion } } diff --git a/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRoot.cs similarity index 97% rename from TwitchDownloaderCore/TwitchObjects/ChatRoot.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRoot.cs index 7413b469..98ccbc7c 100644 --- a/TwitchDownloaderCore/TwitchObjects/ChatRoot.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRoot.cs @@ -2,8 +2,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text.Json.Serialization; +using TwitchDownloaderCore.Tools; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class Streamer { @@ -202,7 +203,7 @@ public class Video public string game { get; set; } public List chapters { get; set; } = new(); -#region DeprecatedProperties + #region DeprecatedProperties /// Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string duration { get; set; } = null; @@ -212,7 +213,7 @@ public class Video /// Deprecated. Used only by chats from before 8d521f7a78222bec187b56c3c747909d240add21. [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public string user_name { get; set; } = null; -#endregion + #endregion } [DebuggerDisplay("{name}")] @@ -273,5 +274,6 @@ public class ChatRoot public Video video { get; set; } public List comments { get; set; } public EmbeddedData embeddedData { get; set; } + public VideoPlatform videoPlatform { get; set; } = VideoPlatform.Twitch; } } \ No newline at end of file diff --git a/TwitchDownloaderCore/TwitchObjects/ChatRootInfo.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRootInfo.cs similarity index 95% rename from TwitchDownloaderCore/TwitchObjects/ChatRootInfo.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRootInfo.cs index e4b60225..a5f43b4e 100644 --- a/TwitchDownloaderCore/TwitchObjects/ChatRootInfo.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/ChatRootInfo.cs @@ -1,6 +1,6 @@ using System; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class ChatRootInfo { @@ -18,7 +18,7 @@ public class ChatRootVersion public int Minor { get; set; } = 0; public int Patch { get; set; } = 0; - public static ChatRootVersion CurrentVersion { get; } = new(1, 3, 1); + public static ChatRootVersion CurrentVersion { get; } = new(1, 3, 2); // Constructors /// @@ -96,9 +96,9 @@ public override bool Equals(object obj) => !(left == right); public static bool operator >=(ChatRootVersion left, ChatRootVersion right) - => (left > right) || (left == right); + => left > right || left == right; public static bool operator <=(ChatRootVersion left, ChatRootVersion right) - => (left < right) || (left == right); + => left < right || left == right; } } diff --git a/TwitchDownloaderCore/TwitchObjects/CheerEmote.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/CheerEmote.cs similarity index 93% rename from TwitchDownloaderCore/TwitchObjects/CheerEmote.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/CheerEmote.cs index 9547bb22..1e217cc3 100644 --- a/TwitchDownloaderCore/TwitchObjects/CheerEmote.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/CheerEmote.cs @@ -3,7 +3,7 @@ using System.Diagnostics; using System.Linq; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { [DebuggerDisplay("{prefix}")] public sealed class CheerEmote : IDisposable @@ -33,7 +33,7 @@ public void Resize(double newScale) } } -#region ImplementIDisposable + #region ImplementIDisposable public void Dispose() { @@ -63,6 +63,6 @@ private void Dispose(bool isDisposing) } } -#endregion + #endregion } } diff --git a/TwitchDownloaderCore/TwitchObjects/CommentSection.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/CommentSection.cs similarity index 87% rename from TwitchDownloaderCore/TwitchObjects/CommentSection.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/CommentSection.cs index ea675ebf..54eacc9a 100644 --- a/TwitchDownloaderCore/TwitchObjects/CommentSection.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/CommentSection.cs @@ -1,7 +1,7 @@ using SkiaSharp; using System.Collections.Generic; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class CommentSection { diff --git a/TwitchDownloaderCore/ChatDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchChatDownloader.cs similarity index 93% rename from TwitchDownloaderCore/ChatDownloader.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchChatDownloader.cs index e4f2a0dc..510fba13 100644 --- a/TwitchDownloaderCore/ChatDownloader.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchChatDownloader.cs @@ -11,14 +11,16 @@ using TwitchDownloaderCore.Chat; using TwitchDownloaderCore.Options; using TwitchDownloaderCore.Tools; -using TwitchDownloaderCore.TwitchObjects; -using TwitchDownloaderCore.TwitchObjects.Gql; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; -namespace TwitchDownloaderCore +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders { - public sealed class ChatDownloader + public sealed class TwitchChatDownloader : IChatDownloader { private readonly ChatDownloadOptions downloadOptions; + private readonly IProgress _progress; private static readonly HttpClient HttpClient = new() { @@ -35,12 +37,13 @@ private enum DownloadType Video } - public ChatDownloader(ChatDownloadOptions chatDownloadOptions) + public TwitchChatDownloader(ChatDownloadOptions chatDownloadOptions, IProgress progress) { downloadOptions = chatDownloadOptions; downloadOptions.TempFolder = Path.Combine( string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, "TwitchDownloader"); + _progress = progress; } private static async Task> DownloadSection(double videoStart, double videoEnd, string videoId, IProgress progress, ChatFormat format, CancellationToken cancellationToken) @@ -245,7 +248,7 @@ private static List ConvertComments(CommentVideo video, ChatFormat form return returnList; } - public async Task DownloadAsync(IProgress progress, CancellationToken cancellationToken) + public async Task DownloadAsync(CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(downloadOptions.Id)) { @@ -259,7 +262,8 @@ public async Task DownloadAsync(IProgress progress, Cancellation FileInfo = new ChatRootInfo { Version = ChatRootVersion.CurrentVersion, CreatedAt = DateTime.Now }, streamer = new(), video = new(), - comments = new List() + comments = new List(), + videoPlatform = VideoPlatform.Twitch }; string videoId = downloadOptions.Id; @@ -359,7 +363,7 @@ public async Task DownloadAsync(IProgress progress, Cancellation { if (progressReport.ReportType != ReportType.Percent) { - progress.Report(progressReport); + _progress.Report(progressReport); } else { @@ -379,8 +383,8 @@ public async Task DownloadAsync(IProgress progress, Cancellation percent /= connectionCount; - progress.Report(new ProgressReport() { ReportType = ReportType.SameLineStatus, Data = $"Downloading {percent}%" }); - progress.Report(new ProgressReport() { ReportType = ReportType.Percent, Data = percent }); + _progress.Report(new ProgressReport() { ReportType = ReportType.SameLineStatus, Data = $"Downloading {percent}%" }); + _progress.Report(new ProgressReport() { ReportType = ReportType.Percent, Data = percent }); } }); } @@ -401,9 +405,9 @@ public async Task DownloadAsync(IProgress progress, Cancellation chatRoot.comments = sortedComments.DistinctBy(x => x._id).ToList(); - if (downloadOptions.EmbedData && (downloadOptions.DownloadFormat is ChatFormat.Json or ChatFormat.Html)) + if (downloadOptions.EmbedData && downloadOptions.DownloadFormat is ChatFormat.Json or ChatFormat.Html) { - progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Downloading + Embedding Images" }); + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Downloading + Embedding Images" }); chatRoot.embeddedData = new EmbeddedData(); // This is the exact same process as in ChatUpdater.cs but not in a task oriented manner @@ -466,7 +470,7 @@ public async Task DownloadAsync(IProgress progress, Cancellation if (downloadOptions.DownloadFormat is ChatFormat.Json) { //Best effort, but if we fail oh well - progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Backfilling commenter info" }); + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Backfilling commenter info" }); List userList = chatRoot.comments.DistinctBy(x => x.commenter._id).Select(x => x.commenter._id).ToList(); Dictionary userInfo = new Dictionary(); int batchSize = 100; @@ -487,7 +491,7 @@ public async Task DownloadAsync(IProgress progress, Cancellation if (failedInfo) { - progress.Report(new ProgressReport() { ReportType = ReportType.Log, Data = "Failed to backfill some commenter info" }); + _progress.Report(new ProgressReport() { ReportType = ReportType.Log, Data = "Failed to backfill some commenter info" }); } foreach (var comment in chatRoot.comments) @@ -502,7 +506,7 @@ public async Task DownloadAsync(IProgress progress, Cancellation } } - progress.Report(new ProgressReport(ReportType.NewLineStatus, "Writing output file")); + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Writing output file")); switch (downloadOptions.DownloadFormat) { case ChatFormat.Json: diff --git a/TwitchDownloaderCore/ClipDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchClipDownloader.cs similarity index 72% rename from TwitchDownloaderCore/ClipDownloader.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchClipDownloader.cs index bfcbe3e5..26644213 100644 --- a/TwitchDownloaderCore/ClipDownloader.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchClipDownloader.cs @@ -9,16 +9,16 @@ using TwitchDownloaderCore.Extensions; using TwitchDownloaderCore.Options; using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; -namespace TwitchDownloaderCore +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders { - public sealed class ClipDownloader + public sealed class TwitchClipDownloader : IClipDownloader { private readonly ClipDownloadOptions downloadOptions; private readonly IProgress _progress; - private static readonly HttpClient HttpClient = new(); - public ClipDownloader(ClipDownloadOptions clipDownloadOptions, IProgress progress) + public TwitchClipDownloader(ClipDownloadOptions clipDownloadOptions, IProgress progress) { downloadOptions = clipDownloadOptions; _progress = progress; @@ -52,7 +52,7 @@ void DownloadProgressHandler(StreamCopyProgress streamProgress) if (!downloadOptions.EncodeMetadata) { - await DownloadFileTaskAsync(downloadUrl, downloadOptions.Filename, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); + await DownloadTools.DownloadClipFileTaskAsync(downloadUrl, downloadOptions.Filename, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); return; } @@ -64,7 +64,7 @@ void DownloadProgressHandler(StreamCopyProgress streamProgress) var tempFile = Path.Combine(downloadOptions.TempFolder, $"clip_{DateTimeOffset.Now.ToUnixTimeMilliseconds()}_{Path.GetRandomFileName()}"); try { - await DownloadFileTaskAsync(downloadUrl, tempFile, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); + await DownloadTools.DownloadClipFileTaskAsync(downloadUrl, tempFile, downloadOptions.ThrottleKib, new Progress(DownloadProgressHandler), cancellationToken); _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Encoding Clip Metadata 0%")); _progress.Report(new ProgressReport(0)); @@ -112,29 +112,6 @@ private async Task GetDownloadUrl() return downloadUrl + "?sig=" + listLinks[0].data.clip.playbackAccessToken.signature + "&token=" + HttpUtility.UrlEncode(listLinks[0].data.clip.playbackAccessToken.value); } - private static async Task DownloadFileTaskAsync(string url, string destinationFile, int throttleKib, IProgress progress, CancellationToken cancellationToken) - { - var request = new HttpRequestMessage(HttpMethod.Get, url); - using var response = await HttpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false); - response.EnsureSuccessStatusCode(); - - var contentLength = response.Content.Headers.ContentLength; - - if (throttleKib == -1) - { - await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); - await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken); - await contentStream.ProgressCopyToAsync(fs, contentLength, progress, cancellationToken).ConfigureAwait(false); - } - else - { - await using var fs = new FileStream(destinationFile, FileMode.Create, FileAccess.Write, FileShare.Read); - await using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken); - await using var throttledStream = new ThrottledStream(contentStream, throttleKib); - await throttledStream.ProgressCopyToAsync(fs, contentLength, progress, cancellationToken).ConfigureAwait(false); - } - } - private async Task EncodeClipMetadata(string inputFile, string destinationFile, CancellationToken cancellationToken) { var metadataFile = $"{Path.GetFileNameWithoutExtension(inputFile)}_metadata{Path.GetExtension(inputFile)}"; diff --git a/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchVideoDownloader.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchVideoDownloader.cs new file mode 100644 index 00000000..1ea808b0 --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Downloaders/TwitchVideoDownloader.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; +using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.Tools; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; + +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders +{ + public sealed class TwitchVideoDownloader : IVideoDownloader + { + private readonly VideoDownloadOptions downloadOptions; + private readonly HttpClient _httpClient = new() { Timeout = TimeSpan.FromSeconds(30) }; + private readonly IProgress _progress; + private bool _shouldClearCache = true; + + public TwitchVideoDownloader(VideoDownloadOptions videoDownloadOptions, IProgress progress) + { + downloadOptions = videoDownloadOptions; + downloadOptions.TempFolder = Path.Combine( + string.IsNullOrWhiteSpace(downloadOptions.TempFolder) ? Path.GetTempPath() : downloadOptions.TempFolder, + "TwitchDownloader"); + _progress = progress; + } + + public async Task DownloadAsync(CancellationToken cancellationToken) + { + TwitchHelper.CleanupUnmanagedCacheFiles(downloadOptions.TempFolder, _progress); + + string downloadFolder = Path.Combine( + downloadOptions.TempFolder, + $"{downloadOptions.Id}_{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}"); + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Fetching Video Info [1/5]")); + + try + { + ServicePointManager.DefaultConnectionLimit = downloadOptions.DownloadThreads; + + GqlVideoResponse videoInfoResponse = await TwitchHelper.GetVideoInfo(int.Parse(downloadOptions.Id)); + if (videoInfoResponse.data.video == null) + { + throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); + } + + GqlVideoChapterResponse videoChapterResponse = await TwitchHelper.GetVideoChapters(int.Parse(downloadOptions.Id)); + + var (playlistUrl, bandwidth) = await GetPlaylistUrl(); + string baseUrl = playlistUrl.Substring(0, playlistUrl.LastIndexOf('/') + 1); + + var videoLength = TimeSpan.FromSeconds(videoInfoResponse.data.video.lengthSeconds); + DriveHelper.CheckAvailableStorageSpace(downloadOptions, bandwidth, videoLength, _progress); + + List> videoList = new List>(); + (List videoPartsList, double vodAge) = await GetVideoPartsList(playlistUrl, videoList, cancellationToken); + + if (Directory.Exists(downloadFolder)) + Directory.Delete(downloadFolder, true); + TwitchHelper.CreateDirectory(downloadFolder); + + _progress.Report(new ProgressReport(ReportType.NewLineStatus, "Downloading 0% [2/5]")); + + await DownloadTools.DownloadVideoPartsAsync(downloadOptions, videoPartsList, baseUrl, downloadFolder, vodAge, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Verifying Parts 0% [3/5]" }); + + await DownloadTools.VerifyDownloadedParts(downloadOptions, videoPartsList, baseUrl, downloadFolder, vodAge, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Combining Parts 0% [4/5]" }); + + await DownloadTools.CombineVideoParts(downloadFolder, videoPartsList, _progress, cancellationToken); + + _progress.Report(new ProgressReport() { ReportType = ReportType.NewLineStatus, Data = "Finalizing Video 0% [5/5]" }); + + double startOffset = 0.0; + + for (int i = 0; i < videoList.Count; i++) + { + if (videoList[i].Key == videoPartsList[0]) + break; + + startOffset += videoList[i].Value; + } + + double seekTime = downloadOptions.CropBeginningTime; + double seekDuration = Math.Round(downloadOptions.CropEndingTime - seekTime); + + string metadataPath = Path.Combine(downloadFolder, "metadata.txt"); + await FfmpegMetadata.SerializeAsync(metadataPath, videoInfoResponse.data.video.owner.displayName, downloadOptions.Id.ToString(), videoInfoResponse.data.video.title, + videoInfoResponse.data.video.createdAt, videoInfoResponse.data.video.viewCount, startOffset, videoChapterResponse.data.video.moments.edges, cancellationToken); + + var finalizedFileDirectory = Directory.GetParent(Path.GetFullPath(downloadOptions.Filename))!; + if (!finalizedFileDirectory.Exists) + { + TwitchHelper.CreateDirectory(finalizedFileDirectory.FullName); + } + + int ffmpegExitCode; + var ffmpegRetries = 0; + do + { + ffmpegExitCode = await Task.Run(() => DownloadTools.RunFfmpegVideoCopy(downloadOptions, downloadFolder, metadataPath, seekTime, startOffset, seekDuration, _progress), cancellationToken); + if (ffmpegExitCode != 0) + { + _progress.Report(new ProgressReport(ReportType.Log, $"Failed to finalize video (code {ffmpegExitCode}), retrying in 10 seconds...")); + await Task.Delay(10_000, cancellationToken); + } + } while (ffmpegExitCode != 0 && ffmpegRetries++ < 1); + + if (ffmpegExitCode != 0 || !File.Exists(downloadOptions.Filename)) + { + _shouldClearCache = false; + throw new Exception($"Failed to finalize video. The download cache has not been cleared and can be found at {downloadFolder} along with a log file."); + } + + _progress.Report(new ProgressReport(ReportType.SameLineStatus, "Finalizing Video 100% [5/5]")); + _progress.Report(new ProgressReport(100)); + } + finally + { + if (_shouldClearCache) + { + DownloadTools.Cleanup(downloadFolder); + } + } + } + + private async Task<(List videoParts, double vodAge)> GetVideoPartsList(string playlistUrl, List> videoList, CancellationToken cancellationToken) + { + string[] videoChunks = (await _httpClient.GetStringAsync(playlistUrl, cancellationToken)).Split('\n'); + + double vodAge = 25; + + try + { + vodAge = (DateTimeOffset.UtcNow - DateTimeOffset.Parse(videoChunks.First(x => x.StartsWith("#ID3-EQUIV-TDTG:")).Replace("#ID3-EQUIV-TDTG:", ""))).TotalHours; + } + catch { } + + for (int i = 0; i < videoChunks.Length; i++) + { + if (videoChunks[i].StartsWith("#EXTINF")) + { + if (videoChunks[i + 1].StartsWith("#EXT-X-BYTERANGE")) + { + if (videoList.Any(x => x.Key == videoChunks[i + 2])) + { + KeyValuePair pair = videoList.Where(x => x.Key == videoChunks[i + 2]).First(); + pair = new KeyValuePair(pair.Key, pair.Value + double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture)); + } + else + { + videoList.Add(new KeyValuePair(videoChunks[i + 2], double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); + } + } + else + { + videoList.Add(new KeyValuePair(videoChunks[i + 1], double.Parse(videoChunks[i].Remove(0, 8).TrimEnd(','), CultureInfo.InvariantCulture))); + } + } + } + + List> videoListCropped = DownloadTools.GenerateCroppedVideoList(videoList, downloadOptions); + + List videoParts = new List(videoListCropped.Count); + foreach (var part in videoListCropped) + { + videoParts.Add(part.Key); + } + + return (videoParts, vodAge); + } + + private async Task<(string url, int bandwidth)> GetPlaylistUrl() + { + GqlVideoTokenResponse accessToken = await TwitchHelper.GetVideoToken(int.Parse(downloadOptions.Id), downloadOptions.Oauth); + + if (accessToken.data.videoPlaybackAccessToken is null) + { + throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); + } + + string[] videoPlaylist = await TwitchHelper.GetVideoPlaylist(int.Parse(downloadOptions.Id), accessToken.data.videoPlaybackAccessToken.value, accessToken.data.videoPlaybackAccessToken.signature); + if (videoPlaylist[0].Contains("vod_manifest_restricted")) + { + throw new NullReferenceException("Insufficient access to VOD, OAuth may be required."); + } + + var videoQualities = new List>(); + + for (int i = 0; i < videoPlaylist.Length; i++) + { + if (videoPlaylist[i].Contains("#EXT-X-MEDIA")) + { + string lastPart = videoPlaylist[i].Substring(videoPlaylist[i].IndexOf("NAME=\"") + 6); + string stringQuality = lastPart.Substring(0, lastPart.IndexOf('"')); + + var bandwidthStartIndex = videoPlaylist[i + 1].IndexOf("BANDWIDTH=") + 10; + var bandwidthEndIndex = videoPlaylist[i + 1].IndexOf(',') - bandwidthStartIndex; + int.TryParse(videoPlaylist[i + 1].Substring(bandwidthStartIndex, bandwidthEndIndex), out var bandwidth); + + if (!videoQualities.Any(x => x.Key.Equals(stringQuality))) + { + videoQualities.Add(new KeyValuePair(stringQuality, (videoPlaylist[i + 2], bandwidth))); + } + } + } + + if (downloadOptions.Quality != null && videoQualities.Any(x => x.Key.StartsWith(downloadOptions.Quality))) + { + return videoQualities.Last(x => x.Key.StartsWith(downloadOptions.Quality)).Value; + } + + // Unable to find specified quality, defaulting to highest quality + return videoQualities.First().Value; + } + } +} \ No newline at end of file diff --git a/TwitchDownloaderCore/TwitchObjects/EmoteResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponse.cs similarity index 87% rename from TwitchDownloaderCore/TwitchObjects/EmoteResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponse.cs index 581796df..b1e051c8 100644 --- a/TwitchDownloaderCore/TwitchObjects/EmoteResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class EmoteResponse { diff --git a/TwitchDownloaderCore/TwitchObjects/EmoteResponseItem.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponseItem.cs similarity index 87% rename from TwitchDownloaderCore/TwitchObjects/EmoteResponseItem.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponseItem.cs index a610fa26..7407e89e 100644 --- a/TwitchDownloaderCore/TwitchObjects/EmoteResponseItem.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/EmoteResponseItem.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class EmoteResponseItem { diff --git a/TwitchDownloaderCore/TwitchObjects/GifEmote.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/GifEmote.cs similarity index 97% rename from TwitchDownloaderCore/TwitchObjects/GifEmote.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/GifEmote.cs index 595e6110..26f19382 100644 --- a/TwitchDownloaderCore/TwitchObjects/GifEmote.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/GifEmote.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Text; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class GifEmote { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlBadgeResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlBadgeResponse.cs similarity index 95% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlBadgeResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlBadgeResponse.cs index f64e2a61..0a222cd9 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlBadgeResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlBadgeResponse.cs @@ -5,7 +5,7 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class GqlGlobalBadgeResponse { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlCheerResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCheerResponse.cs similarity index 94% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlCheerResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCheerResponse.cs index 21feda0c..dad702bf 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlCheerResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCheerResponse.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class Tier { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipResponse.cs similarity index 55% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlClipResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipResponse.cs index 0ee116c8..7f959848 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipResponse.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class ClipBroadcaster { @@ -37,9 +39,18 @@ public class ClipData public Clip clip { get; set; } } - public class GqlClipResponse + public class GqlClipResponse : IVideoInfo { public ClipData data { get; set; } public Extensions extensions { get; set; } + public string ThumbnailUrl { get => data?.clip?.thumbnailURL; } + public DateTime CreatedAt { get => data?.clip?.createdAt ?? DateTime.MinValue; } + public string StreamerName { get => data?.clip?.broadcaster?.displayName; } + public string Title { get => data?.clip?.title; } + public int Duration { get => data?.clip?.durationSeconds ?? 0; } + public int ViewCount { get => data?.clip?.viewCount ?? 0; } + public string Game { get => data?.clip?.game?.displayName; } + public string VideoUrl { get => null; } + public List VideoQualities { get; set; } } } diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipSearchResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipSearchResponse.cs similarity index 95% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlClipSearchResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipSearchResponse.cs index b6c5b2eb..109dc8f4 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipSearchResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipSearchResponse.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class ClipNodeGame { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipTokenResponse.cs similarity index 85% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipTokenResponse.cs index d0325514..c37a524b 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlClipTokenResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlClipTokenResponse.cs @@ -4,13 +4,13 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class ClipToken { public string id { get; set; } public PlaybackAccessToken playbackAccessToken { get; set; } - public List videoQualities { get; set; } + public List videoQualities { get; set; } public string __typename { get; set; } } @@ -32,7 +32,7 @@ public class GqlClipTokenResponse public Extensions extensions { get; set; } } - public class VideoQuality + public class GqlVideoQuality { public int frameRate { get; set; } public string quality { get; set; } diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlCommentResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCommentResponse.cs similarity index 98% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlCommentResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCommentResponse.cs index 165a4348..2a511152 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlCommentResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlCommentResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class CommentChannel { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlUserInfoResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlUserInfoResponse.cs similarity index 92% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlUserInfoResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlUserInfoResponse.cs index bff2cbaf..f56a9321 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlUserInfoResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlUserInfoResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class UserInfoData { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoChapterResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoChapterResponse.cs similarity index 96% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoChapterResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoChapterResponse.cs index a2dadfd2..0886c4b6 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoChapterResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoChapterResponse.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class VideoMomentEdgeVideo { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoResponse.cs similarity index 53% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoResponse.cs index d1489901..5826b840 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoResponse.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Linq; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class VideoOwner { @@ -31,9 +33,26 @@ public class VideoData public VideoInfo video { get; set; } } - public class GqlVideoResponse + public class GqlVideoResponse : IVideoInfo { public VideoData data { get; set; } public Extensions extensions { get; set; } + + public string ThumbnailUrl => data?.video?.thumbnailURLs?.FirstOrDefault(); + + public DateTime CreatedAt => data?.video?.createdAt ?? DateTime.MinValue; + + public string StreamerName => data?.video?.owner?.displayName; + + public string Title => data?.video?.title; + + public int Duration => data?.video?.lengthSeconds ?? 0; + + public int ViewCount => data?.video?.viewCount ?? 0; + + public string Game => data?.video?.game?.displayName; + + public string VideoUrl => null; + public List VideoQualities { get; set; } } } diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoSearchResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoSearchResponse.cs similarity index 96% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoSearchResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoSearchResponse.cs index 99b0902d..1b53fa0a 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoSearchResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoSearchResponse.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class VideoNodeGame { diff --git a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoTokenResponse.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoTokenResponse.cs similarity index 91% rename from TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoTokenResponse.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoTokenResponse.cs index d223a73d..77831b08 100644 --- a/TwitchDownloaderCore/TwitchObjects/Gql/GqlVideoTokenResponse.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/Gql/GqlVideoTokenResponse.cs @@ -4,7 +4,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects.Gql +namespace TwitchDownloaderCore.VideoPlatforms.Twitch.Gql { public class GqlVideoData { diff --git a/TwitchDownloaderCore/VideoPlatforms/Twitch/StvEmoteFlags.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/StvEmoteFlags.cs new file mode 100644 index 00000000..46ce7acb --- /dev/null +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/StvEmoteFlags.cs @@ -0,0 +1,21 @@ +using System; + +namespace TwitchDownloaderCore.VideoPlatforms.Twitch +{ + // https://github.com/SevenTV/Common/blob/4139fcc3eb8d79003573b26b552ef112ec85b8df/structures/v3/type.emote.go#L49 + [Flags] + public enum StvEmoteFlags + { + Private = 1 << 0, // The emote is private and can only be accessed by its owner, editors and moderators + Authentic = 1 << 1, // The emote was verified to be an original creation by the uploader + ZeroWidth = 1 << 8, // The emote is recommended to be enabled as Zero-Width + + + // Content Flags + + ContentSexual = 1 << 16, // Sexually Suggesive + ContentEpilepsy = 1 << 17, // Rapid flashing + ContentEdgy = 1 << 18, // Edgy or distasteful, may be offensive to some users + ContentTwitchDisallowed = 1 << 24, // Not allowed specifically on the Twitch platform + }; +} diff --git a/TwitchDownloaderCore/TwitchObjects/TwitchComment.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchComment.cs similarity index 88% rename from TwitchDownloaderCore/TwitchObjects/TwitchComment.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchComment.cs index 2a13c886..7de7bedf 100644 --- a/TwitchDownloaderCore/TwitchObjects/TwitchComment.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchComment.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Text; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class TwitchComment { diff --git a/TwitchDownloaderCore/TwitchObjects/TwitchEmote.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchEmote.cs similarity index 97% rename from TwitchDownloaderCore/TwitchObjects/TwitchEmote.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchEmote.cs index f8d922df..ace9b776 100644 --- a/TwitchDownloaderCore/TwitchObjects/TwitchEmote.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchEmote.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.IO; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public enum EmoteProvider { @@ -113,7 +113,7 @@ public void Resize(double newScale) } } -#region ImplementIDisposable + #region ImplementIDisposable public void Dispose() { @@ -145,6 +145,6 @@ private void Dispose(bool isDisposing) } } -#endregion + #endregion } } diff --git a/TwitchDownloaderCore/TwitchHelper.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchHelper.cs similarity index 90% rename from TwitchDownloaderCore/TwitchHelper.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchHelper.cs index 23a54736..b05bce37 100644 --- a/TwitchDownloaderCore/TwitchHelper.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/TwitchHelper.cs @@ -14,18 +14,18 @@ using System.Threading; using System.Threading.Tasks; using TwitchDownloaderCore.Chat; -using TwitchDownloaderCore.TwitchObjects; -using TwitchDownloaderCore.TwitchObjects.Api; -using TwitchDownloaderCore.TwitchObjects.Gql; +using TwitchDownloaderCore.VideoPlatforms.Interfaces; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Api; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; -namespace TwitchDownloaderCore +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public static class TwitchHelper { private static readonly HttpClient httpClient = new HttpClient(); private static readonly string[] bttvZeroWidth = { "SoSnowy", "IceCold", "SantaHat", "TopHat", "ReinDeer", "CandyCane", "cvMask", "cvHazmat" }; - public static async Task GetVideoInfo(int videoId) + public static async Task GetVideoInfo(int videoId, string Oauth = null) { var request = new HttpRequestMessage() { @@ -36,7 +36,37 @@ public static async Task GetVideoInfo(int videoId) request.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"); using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); response.EnsureSuccessStatusCode(); - return await response.Content.ReadFromJsonAsync(); + GqlVideoResponse res = await response.Content.ReadFromJsonAsync(); + + GqlVideoTokenResponse accessToken = await TwitchHelper.GetVideoToken(videoId, Oauth); + if (accessToken is null) + { + throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); + } + + string[] playlist = await TwitchHelper.GetVideoPlaylist(videoId, accessToken.data.videoPlaybackAccessToken.value, accessToken.data.videoPlaybackAccessToken.signature); + if (playlist[0].Contains("vod_manifest_restricted")) + { + throw new NullReferenceException("Insufficient access. OAuth may be required."); + } + res.VideoQualities = new List(); + + for (int i = 0; i < playlist.Length; i++) + { + if (playlist[i].Contains("#EXT-X-MEDIA")) + { + string lastPart = playlist[i].Substring(playlist[i].IndexOf("NAME=\"") + 6); + string stringQuality = lastPart.Substring(0, lastPart.IndexOf('"')); + + var bandwidthStartIndex = playlist[i + 1].IndexOf("BANDWIDTH=") + 10; + var bandwidthEndIndex = playlist[i + 1].IndexOf(',') - bandwidthStartIndex; + int.TryParse(playlist[i + 1].Substring(bandwidthStartIndex, bandwidthEndIndex), out var bandwidth); + + res.VideoQualities.Add(new VideoQuality { Quality = stringQuality, SourceUrl = playlist[i + 2], Bandwidth = bandwidth }); + } + } + + return res; } public static async Task GetVideoToken(int videoId, string authToken) @@ -115,7 +145,7 @@ public static async Task GetGqlClips(string channelName, { RequestUri = new Uri("https://gql.twitch.tv/gql"), Method = HttpMethod.Post, - Content = new StringContent("{\"query\":\"query{user(login:\\\"" + channelName + "\\\"){clips(first: " + limit + (cursor == "" ? "" : ", after: \\\"" + cursor + "\\\"") +", criteria: { period: " + period + " }) { edges { cursor, node { id, slug, title, createdAt, durationSeconds, thumbnailURL, viewCount, game { id, displayName } } }, pageInfo { hasNextPage, hasPreviousPage } }}}\",\"variables\":{}}", Encoding.UTF8, "application/json") + Content = new StringContent("{\"query\":\"query{user(login:\\\"" + channelName + "\\\"){clips(first: " + limit + (cursor == "" ? "" : ", after: \\\"" + cursor + "\\\"") + ", criteria: { period: " + period + " }) { edges { cursor, node { id, slug, title, createdAt, durationSeconds, thumbnailURL, viewCount, game { id, displayName } } }, pageInfo { hasNextPage, hasPreviousPage } }}}\",\"variables\":{}}", Encoding.UTF8, "application/json") }; request.Headers.Add("Client-ID", "kd1unb4b3q4t58fwlpcbzcbnm76a8fp"); using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); @@ -320,13 +350,13 @@ private static async Task GetStvEmoteData(int streamerId, List Regex.IsMatch(comment.message.body, pattern)) - select emote; + where !alreadyAdded.Contains(emote.Code) + let pattern = $@"(?<=^|\s){Regex.Escape(emote.Code)}(?=$|\s)" + where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) + select emote; foreach (var emote in emoteResponseItemsQuery) { @@ -347,13 +377,13 @@ where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) if (ffz) { if (!Directory.Exists(ffzFolder)) - TwitchHelper.CreateDirectory(ffzFolder); + CreateDirectory(ffzFolder); var emoteResponseItemsQuery = from emote in emoteDataResponse.FFZ - where !alreadyAdded.Contains(emote.Code) - let pattern = $@"(?<=^|\s){Regex.Escape(emote.Code)}(?=$|\s)" - where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) - select emote; + where !alreadyAdded.Contains(emote.Code) + let pattern = $@"(?<=^|\s){Regex.Escape(emote.Code)}(?=$|\s)" + where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) + select emote; foreach (var emote in emoteResponseItemsQuery) { @@ -372,13 +402,13 @@ where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) if (stv) { if (!Directory.Exists(stvFolder)) - TwitchHelper.CreateDirectory(stvFolder); + CreateDirectory(stvFolder); var emoteResponseItemsQuery = from emote in emoteDataResponse.STV - where !alreadyAdded.Contains(emote.Code) - let pattern = $@"(?<=^|\s){Regex.Escape(emote.Code)}(?=$|\s)" - where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) - select emote; + where !alreadyAdded.Contains(emote.Code) + let pattern = $@"(?<=^|\s){Regex.Escape(emote.Code)}(?=$|\s)" + where comments.Any(comment => Regex.IsMatch(comment.message.body, pattern)) + select emote; foreach (var emote in emoteResponseItemsQuery) { @@ -405,7 +435,7 @@ public static async Task> GetEmotes(List comments, st string emoteFolder = Path.Combine(cacheFolder, "emotes"); if (!Directory.Exists(emoteFolder)) - TwitchHelper.CreateDirectory(emoteFolder); + CreateDirectory(emoteFolder); // Load our embedded emotes if (embeddedData?.firstParty != null) @@ -485,7 +515,7 @@ public static async Task> GetEmotes(List comments, st var nameList = comments.Where(comment => comment.message.user_badges != null) .SelectMany(comment => comment.message.user_badges) - .Where(badge => !String.IsNullOrWhiteSpace(badge._id)) + .Where(badge => !string.IsNullOrWhiteSpace(badge._id)) .Where(badge => globalBadges.ContainsKey(badge._id) || subBadges.ContainsKey(badge._id)) .Select(badge => badge._id).Distinct(); @@ -551,9 +581,9 @@ public static async Task> GetChatBadges(List comments, string badgeFolder = Path.Combine(cacheFolder, "badges"); if (!Directory.Exists(badgeFolder)) - TwitchHelper.CreateDirectory(badgeFolder); + CreateDirectory(badgeFolder); - foreach(var badge in badgesData) + foreach (var badge in badgesData) { try { @@ -692,7 +722,7 @@ public static async Task> GetBits(List comments, strin string bitFolder = Path.Combine(cacheFolder, "bits"); if (!Directory.Exists(bitFolder)) - TwitchHelper.CreateDirectory(bitFolder); + CreateDirectory(bitFolder); if (cheerResponse?.data != null) { @@ -716,12 +746,12 @@ public static async Task> GetBits(List comments, strin string templateURL = cheerGroup.templateURL; var cheerNodesQuery = from node in cheerGroup.nodes - where !alreadyAdded.Contains(node.prefix) - let pattern = $@"(?<=^|\s){Regex.Escape(node.prefix)}(?=[1-9])" - where comments - .Where(comment => comment.message.bits_spent > 0) - .Any(comment => Regex.IsMatch(comment.message.body, pattern)) - select node; + where !alreadyAdded.Contains(node.prefix) + let pattern = $@"(?<=^|\s){Regex.Escape(node.prefix)}(?=[1-9])" + where comments + .Where(comment => comment.message.bits_spent > 0) + .Any(comment => Regex.IsMatch(comment.message.body, pattern)) + select node; foreach (CheerNode node in cheerNodesQuery) { @@ -784,10 +814,10 @@ public static void CleanupUnmanagedCacheFiles(string cacheFolder, IProgress 0) { @@ -857,7 +887,7 @@ public static async Task GetUserInfo(List idList) { RequestUri = new Uri("https://gql.twitch.tv/gql"), Method = HttpMethod.Post, - Content = new StringContent("{\"query\":\"query{users(ids:[" + String.Join(",", idList.Select(x => "\\\"" + x + "\\\"").ToArray()) + "]){id,login,createdAt,updatedAt,description,profileImageURL(width:300)}}\",\"variables\":{}}", Encoding.UTF8, "application/json") + Content = new StringContent("{\"query\":\"query{users(ids:[" + string.Join(",", idList.Select(x => "\\\"" + x + "\\\"").ToArray()) + "]){id,login,createdAt,updatedAt,description,profileImageURL(width:300)}}\",\"variables\":{}}", Encoding.UTF8, "application/json") }; request.Headers.Add("Client-ID", "kimne78kx3ncx6brgo4mv6wki5h1ko"); using var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead); diff --git a/TwitchDownloaderCore/TwitchObjects/UpdateFrame.cs b/TwitchDownloaderCore/VideoPlatforms/Twitch/UpdateFrame.cs similarity index 87% rename from TwitchDownloaderCore/TwitchObjects/UpdateFrame.cs rename to TwitchDownloaderCore/VideoPlatforms/Twitch/UpdateFrame.cs index 2f91e0b5..b3737969 100644 --- a/TwitchDownloaderCore/TwitchObjects/UpdateFrame.cs +++ b/TwitchDownloaderCore/VideoPlatforms/Twitch/UpdateFrame.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; -namespace TwitchDownloaderCore.TwitchObjects +namespace TwitchDownloaderCore.VideoPlatforms.Twitch { public class UpdateFrame { diff --git a/TwitchDownloaderWPF/Curl-Impersonate/curl-ca-bundle.crt b/TwitchDownloaderWPF/Curl-Impersonate/curl-ca-bundle.crt new file mode 100644 index 00000000..2ae7b6cb --- /dev/null +++ b/TwitchDownloaderWPF/Curl-Impersonate/curl-ca-bundle.crt @@ -0,0 +1,3372 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Jan 10 04:12:06 2023 GMT +## +## This is a bundle of X.509 certificates of public Certificate Authorities +## (CA). These were automatically extracted from Mozilla's root certificates +## file (certdata.txt). This file can be found in the mozilla source tree: +## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt +## +## It contains the certificates in PEM format and therefore +## can be directly used with curl / libcurl / php_curl, or with +## an Apache+mod_ssl webserver for SSL client authentication. +## Just configure this file as the SSLCACertificateFile. +## +## Conversion done with mk-ca-bundle.pl version 1.29. +## SHA256: 90c470e705b4b5f36f09684dc50e2b79c8b86989a848b62cd1a7bd6460ee65f6 +## + + +GlobalSign Root CA +================== +-----BEGIN CERTIFICATE----- +MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx +GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds +b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD +VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa +DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc +THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb +Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP +c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX +gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV +HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF +AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj +Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG +j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH +hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC +X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ +KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy +T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf +zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT +J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e +nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE= +-----END CERTIFICATE----- + +Baltimore CyberTrust Root +========================= +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE +ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li +ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC +SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs +dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME +uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB +UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C +G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 +XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr +l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI +VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB +BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh +cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 +hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa +Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H +RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp +-----END CERTIFICATE----- + +Entrust Root Certification Authority +==================================== +-----BEGIN CERTIFICATE----- +MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw +b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG +A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 +MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu +MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v +dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz +A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww +Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 +j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN +rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 +MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH +hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA +A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM +Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa +v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS +W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 +tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 +-----END CERTIFICATE----- + +Comodo AAA Services root +======================== +-----BEGIN CERTIFICATE----- +MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw +MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl +c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV +BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG +C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs +i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW +Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH +Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK +Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f +BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl +cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz +LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm +7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz +Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z +8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C +12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +XRamp Global CA Root +==================== +-----BEGIN CERTIFICATE----- +MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE +BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj +dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx +HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg +U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu +IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx +foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE +zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs +AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry +xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap +oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC +AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc +/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt +qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n +nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz +8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= +-----END CERTIFICATE----- + +Go Daddy Class 2 CA +=================== +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY +VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG +A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g +RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD +ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv +2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 +qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j +YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY +vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O +BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o +atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu +MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG +A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim +PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt +I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI +Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b +vZ8= +-----END CERTIFICATE----- + +Starfield Class 2 CA +==================== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc +U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo +MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG +A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG +SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY +bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ +JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm +epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN +F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF +MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f +hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo +bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g +QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs +afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM +PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl +xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD +KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 +QBFGmh95DmK/D5fs4C8fF5Q= +-----END CERTIFICATE----- + +DigiCert Assured ID Root CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx +MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO +9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy +UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW +/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy +oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf +GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF +66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq +hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc +EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn +SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i +8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe ++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== +-----END CERTIFICATE----- + +DigiCert Global Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw +MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn +TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 +BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H +4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y +7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB +o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm +8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF +BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr +EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt +tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 +UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk +CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= +-----END CERTIFICATE----- + +DigiCert High Assurance EV Root CA +================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw +KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw +MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ +MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu +Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t +Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS +OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 +MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ +NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe +h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB +Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY +JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ +V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp +myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK +mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe +vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SecureTrust CA +============== +-----BEGIN CERTIFICATE----- +MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy +dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe +BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX +OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t +DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH +GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b +01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH +ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj +aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu +SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf +mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ +nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR +3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= +-----END CERTIFICATE----- + +Secure Global CA +================ +-----BEGIN CERTIFICATE----- +MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH +bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg +MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg +Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx +YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ +bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g +8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV +HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi +0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud +EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn +oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA +MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ +OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn +CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 +3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc +f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW +-----END CERTIFICATE----- + +COMODO Certification Authority +============================== +-----BEGIN CERTIFICATE----- +MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb +MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD +T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH ++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww +xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV +4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA +1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI +rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k +b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC +AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP +OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ +RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc +IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN ++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== +-----END CERTIFICATE----- + +COMODO ECC Certification Authority +================================== +-----BEGIN CERTIFICATE----- +MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix +GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo +b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X +4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni +wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E +BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG +FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA +U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= +-----END CERTIFICATE----- + +Certigna +======== +-----BEGIN CERTIFICATE----- +MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw +EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 +MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI +Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q +XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH +GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p +ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg +DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf +Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ +tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ +BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J +SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA +hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ +ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu +PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY +1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw +WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== +-----END CERTIFICATE----- + +ePKI Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg +Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx +MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq +MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs +IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi +lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv +qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX +12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O +WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ +ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao +lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ +vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi +Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi +MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH +ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 +1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq +KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV +xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP +NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r +GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE +xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx +gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy +sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD +BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= +-----END CERTIFICATE----- + +certSIGN ROOT CA +================ +-----BEGIN CERTIFICATE----- +MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD +VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa +Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE +CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I +JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH +rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 +ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD +0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 +AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B +Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB +AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 +SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 +x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt +vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz +TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD +-----END CERTIFICATE----- + +NetLock Arany (Class Gold) Főtanúsítvány +======================================== +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G +A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 +dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB +cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx +MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO +ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv +biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 +c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu +0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw +/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk +H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw +fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 +neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB +BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW +qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta +YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC +bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna +NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu +dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER +MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv +c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o +dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE +BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt +U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA +fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG +0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA +pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm +1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC +AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf +QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE +FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o +lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX +I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 +tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 +yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi +LXpUq3DDfSJlgnCW +-----END CERTIFICATE----- + +GlobalSign Root CA - R3 +======================= +-----BEGIN CERTIFICATE----- +MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt +iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ +0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 +rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl +OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 +xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 +lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 +EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E +bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 +YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r +kpeDMdmztcpHWD9f +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Go Daddy Root Certificate Authority - G2 +======================================== +-----BEGIN CERTIFICATE----- +MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu +MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 +MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 +b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G +A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq +9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD ++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd +fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl +NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 +BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac +vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r +5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV +N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO +LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 +-----END CERTIFICATE----- + +Starfield Root Certificate Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 +eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw +DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg +VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB +dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv +W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs +bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk +N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf +ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU +JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol +TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx +4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw +F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K +pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ +c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 +-----END CERTIFICATE----- + +Starfield Services Root Certificate Authority - G2 +================================================== +-----BEGIN CERTIFICATE----- +MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s +b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl +IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV +BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT +dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 +h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa +hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP +LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB +rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG +SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP +E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy +xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd +iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza +YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 +-----END CERTIFICATE----- + +AffirmTrust Commercial +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw +MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb +DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV +C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 +BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww +MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV +HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG +hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi +qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv +0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh +sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= +-----END CERTIFICATE----- + +AffirmTrust Networking +====================== +-----BEGIN CERTIFICATE----- +MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw +MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly +bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE +Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI +dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 +/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb +h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV +HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu +UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 +12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 +WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 +/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= +-----END CERTIFICATE----- + +AffirmTrust Premium +=================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS +BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy +OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy +dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn +BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV +5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs ++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd +GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R +p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI +S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 +6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 +/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo ++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv +MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg +Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC +6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S +L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK ++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV +BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg +IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 +g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb +zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== +-----END CERTIFICATE----- + +AffirmTrust Premium ECC +======================= +-----BEGIN CERTIFICATE----- +MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV +BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx +MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U +cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ +N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW +BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK +BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X +57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM +eQ== +-----END CERTIFICATE----- + +Certum Trusted Network CA +========================= +-----BEGIN CERTIFICATE----- +MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK +ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy +MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU +ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC +l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J +J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 +fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 +cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB +Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw +DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj +jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 +mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj +Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI +03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= +-----END CERTIFICATE----- + +TWCA Root Certification Authority +================================= +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ +VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG +EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB +IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK +AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx +QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC +oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP +4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r +y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB +BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG +9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC +mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW +QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY +T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny +Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== +-----END CERTIFICATE----- + +Security Communication RootCA2 +============================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC +SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy +aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ ++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R +3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV +spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K +EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 +QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB +CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj +u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk +3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q +tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 +mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 +-----END CERTIFICATE----- + +Actalis Authentication Root CA +============================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Buypass Class 2 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X +DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 +g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn +9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b +/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU +CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff +awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI +zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn +Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX +Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs +M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s +A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI +osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S +aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd +DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD +LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 +oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC +wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS +CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN +rJgWVqA= +-----END CERTIFICATE----- + +Buypass Class 3 Root CA +======================= +-----BEGIN CERTIFICATE----- +MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X +DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 +eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH +sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR +5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh +7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ +ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH +2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV +/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ +RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA +Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq +j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF +AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV +cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G +uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG +Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 +ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 +KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz +6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug +UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe +eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi +Cp/HuZc= +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 3 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx +MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK +9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU +NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF +iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W +0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr +AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb +fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT +ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h +P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml +e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 2009 +============================== +-----BEGIN CERTIFICATE----- +MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe +Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE +LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw +DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD +ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA +BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv +KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z +p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC +AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ +4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y +eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw +MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G +PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw +OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm +2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 +o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV +dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph +X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I= +-----END CERTIFICATE----- + +D-TRUST Root Class 3 CA 2 EV 2009 +================================= +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK +DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw +OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS +egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh +zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T +7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60 +sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35 +11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv +cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v +ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El +MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp +b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh +c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+ +PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 +nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX +ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA +NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv +w9y4AyHqnxbxLFS1 +-----END CERTIFICATE----- + +CA Disig Root R2 +================ +-----BEGIN CERTIFICATE----- +MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw +EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp +ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx +EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp +c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC +w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia +xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7 +A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S +GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV +g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa +5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE +koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A +Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i +Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV +HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u +Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM +tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV +sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je +dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8 +1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx +mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01 +utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0 +sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg +UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV +7+ZtsH8tZ/3zbBt1RqPlShfppNcL +-----END CERTIFICATE----- + +ACCVRAIZ1 +========= +-----BEGIN CERTIFICATE----- +MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB +SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1 +MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH +UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM +jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0 +RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD +aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ +0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG +WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7 +8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR +5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J +9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK +Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw +Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu +Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 +VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM +Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA +QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh +AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA +YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj +AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA +IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk +aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0 +dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2 +MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI +hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E +R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN +YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49 +nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ +TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3 +sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h +I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg +Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd +3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p +EfbRD0tVNEYqi4Y7 +-----END CERTIFICATE----- + +TWCA Global Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT +CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD +QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK +EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg +Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C +nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV +r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR +Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV +tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W +KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99 +sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p +yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn +kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI +zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g +cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn +LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M +8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg +/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg +lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP +A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m +i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8 +EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3 +zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0= +-----END CERTIFICATE----- + +TeliaSonera Root CA v1 +====================== +-----BEGIN CERTIFICATE----- +MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE +CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4 +MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW +VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+ +6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA +3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k +B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn +Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH +oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3 +F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ +oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7 +gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc +TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB +AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW +DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm +zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx +0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW +pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV +G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc +c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT +JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2 +qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6 +Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems +WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= +-----END CERTIFICATE----- + +E-Tugra Certification Authority +=============================== +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w +DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls +ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN +ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw +NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx +QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl +cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD +DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd +hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K +CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g +ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ +BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0 +E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz +rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq +jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn +rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5 +dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB +/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG +MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK +kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO +XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807 +VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo +a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc +dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV +KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT +Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0 +8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G +C7TbO6Orb1wdtn7os4I07QZcJA== +-----END CERTIFICATE----- + +T-TeleSec GlobalRoot Class 2 +============================ +-----BEGIN CERTIFICATE----- +MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM +IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU +cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx +MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz +dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD +ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ +SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F +vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970 +2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV +WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy +YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4 +r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf +vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR +3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN +9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg== +-----END CERTIFICATE----- + +Atos TrustedRoot 2011 +===================== +-----BEGIN CERTIFICATE----- +MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU +cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4 +MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG +A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV +hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr +54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+ +DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320 +HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR +z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R +l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ +bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h +k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh +TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9 +61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G +3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed +-----END CERTIFICATE----- + +QuoVadis Root CA 1 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE +PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm +PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6 +Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN +ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l +g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV +7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX +9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f +iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg +t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI +hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC +MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3 +GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct +Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP ++V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh +3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa +wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6 +O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0 +FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV +hMJKzRwuJIczYOXD +-----END CERTIFICATE----- + +QuoVadis Root CA 2 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh +ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY +NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t +oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o +MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l +V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo +L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ +sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD +6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh +lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI +hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 +AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K +pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9 +x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz +dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X +U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw +mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD +zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN +JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr +O3jtZsSOeWmD3n+M +-----END CERTIFICATE----- + +QuoVadis Root CA 3 G3 +===================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG +A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv +b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN +MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg +RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286 +IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL +Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe +6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3 +I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U +VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7 +5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi +Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM +dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt +rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI +hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px +KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS +t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ +TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du +DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib +Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD +hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX +0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW +dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2 +PpxxVJkES/1Y+Zj0 +-----END CERTIFICATE----- + +DigiCert Assured ID Root G2 +=========================== +-----BEGIN CERTIFICATE----- +MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw +IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw +MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL +ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH +35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq +bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw +VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP +YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn +lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO +w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv +0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz +d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW +hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M +jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo +IhNzbM8m9Yop5w== +-----END CERTIFICATE----- + +DigiCert Assured ID Root G3 +=========================== +-----BEGIN CERTIFICATE----- +MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD +VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb +RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs +KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF +UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy +YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy +1vUhZscv6pZjamVFkpUBtA== +-----END CERTIFICATE----- + +DigiCert Global Root G2 +======================= +-----BEGIN CERTIFICATE----- +MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw +HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx +MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 +dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ +kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO +3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV +BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM +UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB +o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu +5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr +F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U +WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH +QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/ +iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl +MrY= +-----END CERTIFICATE----- + +DigiCert Global Root G3 +======================= +-----BEGIN CERTIFICATE----- +MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV +UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD +VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw +MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k +aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C +AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O +YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp +Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y +3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34 +VOKa5Vt8sycX +-----END CERTIFICATE----- + +DigiCert Trusted Root G4 +======================== +-----BEGIN CERTIFICATE----- +MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG +EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw +HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1 +MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp +pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o +k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa +vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY +QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6 +MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm +mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7 +f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH +dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8 +oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD +ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY +ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr +yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy +7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah +ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN +5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb +/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa +5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK +G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP +82Z+ +-----END CERTIFICATE----- + +COMODO RSA Certification Authority +================================== +-----BEGIN CERTIFICATE----- +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 +LaZRfyHBNVOFBkpdn627G190 +-----END CERTIFICATE----- + +USERTrust RSA Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +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 +Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9 +-----END CERTIFICATE----- + +USERTrust ECC Certification Authority +===================================== +-----BEGIN CERTIFICATE----- +MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC +VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU +aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2 +0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez +nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV +HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB +HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu +9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R5 +=========================== +-----BEGIN CERTIFICATE----- +MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb +R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD +EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6 +SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS +h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx +uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7 +yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3 +-----END CERTIFICATE----- + +IdenTrust Commercial Root CA 1 +============================== +-----BEGIN CERTIFICATE----- +MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS +b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES +MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB +IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld +hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/ +mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi +1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C +XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl +3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy +NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV +WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg +xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix +uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI +hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH +6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg +ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt +ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV +YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX +feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro +kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe +2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz +Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R +cGzM7vRX+Bi6hG6H +-----END CERTIFICATE----- + +IdenTrust Public Sector Root CA 1 +================================= +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG +EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv +ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV +UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS +b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy +P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6 +Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI +rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf +qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS +mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn +ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh +LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v +iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL +4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B +Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw +DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj +t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A +mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt +GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt +m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx +NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4 +Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI +ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC +ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ +3Wl9af0AVqW3rLatt8o+Ae+c +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G2 +========================================= +-----BEGIN CERTIFICATE----- +MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV +BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy +bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug +b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw +HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT +DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx +OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s +eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP +/vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz +HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU +s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y +TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx +AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6 +0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z +iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ +Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi +nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+ +vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO +e4pIb4tF9g== +-----END CERTIFICATE----- + +Entrust Root Certification Authority - EC1 +========================================== +-----BEGIN CERTIFICATE----- +MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn +YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl +ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs +LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg +dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt +IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy +AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef +9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE +FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h +vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8 +kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G +-----END CERTIFICATE----- + +CFCA EV ROOT +============ +-----BEGIN CERTIFICATE----- +MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE +CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB +IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw +MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD +DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV +BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD +7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN +uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW +ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7 +xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f +py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K +gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol +hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ +tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf +BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB +/wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB +ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q +ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua +4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG +E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX +BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn +aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy +PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX +kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C +ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GB CA +=============================== +-----BEGIN CERTIFICATE----- +MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG +EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl +ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw +MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD +VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds +b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX +scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP +rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk +9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o +Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg +GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI +hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD +dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0 +VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui +HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic +Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM= +-----END CERTIFICATE----- + +SZAFIR ROOT CA2 +=============== +-----BEGIN CERTIFICATE----- +MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG +A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV +BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ +BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD +VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q +qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK +DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE +2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ +ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi +ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P +AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC +AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5 +O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67 +oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul +4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6 ++/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw== +-----END CERTIFICATE----- + +Certum Trusted Network CA 2 +=========================== +-----BEGIN CERTIFICATE----- +MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE +BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1 +bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y +ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ +TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB +IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9 +7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o +CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b +Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p +uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130 +GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ +9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB +Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye +hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM +BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI +hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW +Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA +L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo +clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM +pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb +w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo +J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm +ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX +is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7 +zAYspsbiDrW5viSP +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2015 +======================================================= +-----BEGIN CERTIFICATE----- +MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT +BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0 +aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl +YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx +MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg +QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV +BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw +MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv +bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh +iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+ +6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd +FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr +i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F +GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2 +fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu +iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc +Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI +hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+ +D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM +d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y +d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn +82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb +davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F +Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt +J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa +JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q +p/UsQu0yrbYhnr68 +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions ECC RootCA 2015 +=========================================================== +-----BEGIN CERTIFICATE----- +MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0 +aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj +aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw +MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj +IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD +VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290 +Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP +dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK +Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O +BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA +GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn +dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR +-----END CERTIFICATE----- + +ISRG Root X1 +============ +-----BEGIN CERTIFICATE----- +MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE +BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD +EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG +EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT +DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r +Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1 +3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K +b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN +Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ +4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf +1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu +hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH +usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r +OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G +A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY +9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL +ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV +0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt +hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw +TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx +e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA +JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD +YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n +JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ +m+kXQ99b21/+jh5Xos1AnX5iItreGCc= +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM +================ +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT +AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw +MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD +TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf +qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr +btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL +j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou +08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw +WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT +tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ +47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC +ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa +i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE +FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o +dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD +nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s +D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ +j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT +Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW ++YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7 +Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d +8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm +5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG +rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM= +-----END CERTIFICATE----- + +Amazon Root CA 1 +================ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1 +MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH +FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ +gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t +dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce +VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3 +DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM +CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy +8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa +2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2 +xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- + +Amazon Root CA 2 +================ +-----BEGIN CERTIFICATE----- +MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD +VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1 +MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv +bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC +ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4 +kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp +N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9 +AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd +fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx +kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS +btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0 +Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN +c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+ +3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw +DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA +A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY ++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE +YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW +xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ +gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW +aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV +Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3 +KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi +JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw= +-----END CERTIFICATE----- + +Amazon Root CA 3 +================ +-----BEGIN CERTIFICATE----- +MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB +f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr +Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43 +rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc +eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw== +-----END CERTIFICATE----- + +Amazon Root CA 4 +================ +-----BEGIN CERTIFICATE----- +MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG +EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy +NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ +MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN +/sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri +83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA +MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1 +AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA== +-----END CERTIFICATE----- + +TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT +D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr +IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g +TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp +ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD +VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt +c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth +bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11 +IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8 +6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc +wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0 +3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9 +WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU +ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh +AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc +lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R +e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j +q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM= +-----END CERTIFICATE----- + +GDCA TrustAUTH R5 ROOT +====================== +-----BEGIN CERTIFICATE----- +MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCQ04xMjAw +BgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8wHQYDVQQD +DBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVow +YjELMAkGA1UEBhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ +IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJjDp6L3TQs +AlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBjTnnEt1u9ol2x8kECK62p +OqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+uKU49tm7srsHwJ5uu4/Ts765/94Y9cnrr +pftZTqfrlYwiOXnhLQiPzLyRuEH3FMEjqcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ +9Cy5WmYqsBebnh52nUpmMUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQ +xXABZG12ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloPzgsM +R6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3GkL30SgLdTMEZeS1SZ +D2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeCjGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4 +oR24qoAATILnsn8JuLwwoC8N9VKejveSswoAHQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx +9hoh49pwBiFYFIeFd3mqgnkCAwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlR +MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg +p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZmDRd9FBUb1Ov9 +H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5COmSdI31R9KrO9b7eGZONn35 +6ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ryL3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd ++PwyvzeG5LuOmCd+uh8W4XAR8gPfJWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQ +HtZa37dG/OaG+svgIHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBD +F8Io2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV09tL7ECQ +8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQXR4EzzffHqhmsYzmIGrv +/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrqT8p+ck0LcIymSLumoRT2+1hEmRSuqguT +aaApJUqlyyvdimYHFngVV3Eb7PVHhPOeMTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g== +-----END CERTIFICATE----- + +SSL.com Root Certification Authority RSA +======================================== +-----BEGIN CERTIFICATE----- +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 +WuuA8ShYIc2wBlX7Jz9TkHCpBB5XJ7k= +-----END CERTIFICATE----- + +SSL.com Root Certification Authority ECC +======================================== +-----BEGIN CERTIFICATE----- +MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xMTAv +BgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEy +MTgxNDAzWhcNNDEwMjEyMTgxNDAzWjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAO +BgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv +bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI7Z4INcgn64mMU1jrYor+ +8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPgCemB+vNH06NjMGEwHQYDVR0OBBYEFILR +hXMw5zUE044CkvvlpNHEIejNMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTT +jgKS++Wk0cQh6M0wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCW +e+0F+S8Tkdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+gA0z +5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority RSA R2 +============================================== +-----BEGIN CERTIFICATE----- +MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNVBAYTAlVTMQ4w +DAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9u +MTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy +MB4XDTE3MDUzMTE4MTQzN1oXDTQyMDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQI +DAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYD +VQQDDC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvqM0fNTPl9fb69LT3w23jh +hqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssufOePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7w +cXHswxzpY6IXFJ3vG2fThVUCAtZJycxa4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTO +Zw+oz12WGQvE43LrrdF9HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+ +B6KjBSYRaZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcAb9Zh +CBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQGp8hLH94t2S42Oim +9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQVPWKchjgGAGYS5Fl2WlPAApiiECto +RHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMOpgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+Slm +JuwgUHfbSguPvuUCYHBBXtSuUDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48 ++qvWBkofZ6aYMBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV +HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa49QaAJadz20Zp +qJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBWs47LCp1Jjr+kxJG7ZhcFUZh1 +++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nx +Y/hoLVUE0fKNsKTPvDxeH3jnpaAgcLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2G +guDKBAdRUNf/ktUM79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDz +OFSz/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXtll9ldDz7 +CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEmKf7GUmG6sXP/wwyc5Wxq +lD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKKQbNmC1r7fSOl8hqw/96bg5Qu0T/fkreR +rwU7ZcegbLHNYhLDkBvjJc40vG93drEQw/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1 +hlMYegouCRw2n5H9gooiS9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX +9hwJ1C07mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w== +-----END CERTIFICATE----- + +SSL.com EV Root Certification Authority ECC +=========================================== +-----BEGIN CERTIFICATE----- +MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMCVVMxDjAMBgNV +BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9yYXRpb24xNDAy +BgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYw +MjEyMTgxNTIzWhcNNDEwMjEyMTgxNTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMx +EDAOBgNVBAcMB0hvdXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NM +LmNvbSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB +BAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMAVIbc/R/fALhBYlzccBYy +3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1KthkuWnBaBu2+8KGwytAJKaNjMGEwHQYDVR0O +BBYEFFvKXuXe0oGqzagtZFG22XKbl+ZPMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe +5d7SgarNqC1kUbbZcpuX5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJ +N+vp1RPZytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZgh5Mm +m7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg== +-----END CERTIFICATE----- + +GlobalSign Root CA - R6 +======================= +-----BEGIN CERTIFICATE----- +MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEgMB4GA1UECxMX +R2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQxMjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9i +YWxTaWduIFJvb3QgQ0EgLSBSNjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFs +U2lnbjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQss +grRIxutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1kZguSgMpE +3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxDaNc9PIrFsmbVkJq3MQbF +vuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJwLnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqM +PKq0pPbzlUoSB239jLKJz9CgYXfIWHSw1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+ +azayOeSsJDa38O+2HBNXk7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05O +WgtH8wY2SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/hbguy +CLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4nWUx2OVvq+aWh2IMP +0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpYrZxCRXluDocZXFSxZba/jJvcE+kN +b7gu3GduyYsRtYQUigAZcIN5kZeR1BonvzceMgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQE +AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNV +HSMEGDAWgBSubAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN +nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGtIxg93eFyRJa0 +lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr6155wsTLxDKZmOMNOsIeDjHfrY +BzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLjvUYAGm0CuiVdjaExUd1URhxN25mW7xocBFym +Fe944Hn+Xds+qkxV/ZoVqW/hpvvfcDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr +3TsTjxKM4kEaSHpzoHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB1 +0jZpnOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfspA9MRf/T +uTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+vJJUEeKgDu+6B5dpffItK +oZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+t +JDfLRVpOoERIyNiwmcUVhAn21klJwGW45hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA= +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GC CA +=============================== +-----BEGIN CERTIFICATE----- +MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQswCQYDVQQGEwJD +SDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEo +MCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRa +Fw00MjA1MDkwOTU4MzNaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQL +ExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh +bCBSb290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4nieUqjFqdr +VCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4Wp2OQ0jnUsYd4XxiWD1Ab +NTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd +BgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7TrYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0E +AwMDaAAwZQIwJsdpW9zV57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtk +AjEA2zQgMgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9 +-----END CERTIFICATE----- + +UCA Global G2 Root +================== +-----BEGIN CERTIFICATE----- +MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9MQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBHbG9iYWwgRzIgUm9vdDAeFw0x +NjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0xCzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlU +cnVzdDEbMBkGA1UEAwwSVUNBIEdsb2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEAxeYrb3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmT +oni9kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzmVHqUwCoV +8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/RVogvGjqNO7uCEeBHANBS +h6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDcC/Vkw85DvG1xudLeJ1uK6NjGruFZfc8o +LTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIjtm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/ +R+zvWr9LesGtOxdQXGLYD0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBe +KW4bHAyvj5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6DlNaBa +4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6iIis7nCs+dwp4wwc +OxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznPO6Q0ibd5Ei9Hxeepl2n8pndntd97 +8XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O +BBYEFIHEjMz15DD/pQwIX4wVZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo +5sOASD0Ee/ojL3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5 +1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl1qnN3e92mI0A +Ds0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oUb3n09tDh05S60FdRvScFDcH9 +yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LVPtateJLbXDzz2K36uGt/xDYotgIVilQsnLAX +c47QN6MUPJiVAAwpBVueSUmxX8fjy88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHo +jhJi6IjMtX9Gl8CbEGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZk +bxqgDMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI+Vg7RE+x +ygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGyYiGqhkCyLmTTX8jjfhFn +RR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bXUB+K+wb1whnw0A== +-----END CERTIFICATE----- + +UCA Extended Validation Root +============================ +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQG +EwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9u +IFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMxMDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8G +A1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrs +iWogD4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvSsPGP2KxF +Rv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aopO2z6+I9tTcg1367r3CTu +eUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dksHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR +59mzLC52LqGj3n5qiAno8geK+LLNEOfic0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH +0mK1lTnj8/FtDw5lhIpjVMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KR +el7sFsLzKuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/TuDv +B0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41Gsx2VYVdWf6/wFlth +WG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs1+lvK9JKBZP8nm9rZ/+I8U6laUpS +NwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQDfwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS +3H5aBZ8eNJr34RQwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQEL +BQADggIBADaNl8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR +ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQVBcZEhrxH9cM +aVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5c6sq1WnIeJEmMX3ixzDx/BR4 +dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb ++7lsq+KePRXBOy5nAliRn+/4Qh8st2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOW +F3sGPjLtx7dCvHaj2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwi +GpWOvpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2CxR9GUeOc +GMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmxcmtpzyKEC2IPrNkZAJSi +djzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbMfjKaiJUINlK73nZfdklJrX+9ZSCyycEr +dhh2n1ax +-----END CERTIFICATE----- + +Certigna Root CA +================ +-----BEGIN CERTIFICATE----- +MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAwWjELMAkGA1UE +BhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAwMiA0ODE0NjMwODEwMDAzNjEZ +MBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0xMzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjda +MFoxCzAJBgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYz +MDgxMDAwMzYxGTAXBgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4IC +DwAwggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sOty3tRQgX +stmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9MCiBtnyN6tMbaLOQdLNyz +KNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPuI9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8 +JXrJhFwLrN1CTivngqIkicuQstDuI7pmTLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16 +XdG+RCYyKfHx9WzMfgIhC59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq +4NYKpkDfePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3YzIoej +wpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWTCo/1VTp2lc5ZmIoJ +lXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1kJWumIWmbat10TWuXekG9qxf5kBdI +jzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp/ +/TBt2dzhauH8XwIDAQABo4IBGjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw +HQYDVR0OBBYEFBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of +1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczovL3d3d3cuY2Vy +dGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilodHRwOi8vY3JsLmNlcnRpZ25h +LmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYraHR0cDovL2NybC5kaGlteW90aXMuY29tL2Nl +cnRpZ25hcm9vdGNhLmNybDANBgkqhkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOIt +OoldaDgvUSILSo3L6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxP +TGRGHVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH60BGM+RFq +7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncBlA2c5uk5jR+mUYyZDDl3 +4bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdio2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd +8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS +6Cvu5zHbugRqh5jnxV/vfaci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaY +tlu3zM63Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayhjWZS +aX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw3kAP+HwV96LOPNde +E4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0= +-----END CERTIFICATE----- + +emSign Root CA - G1 +=================== +-----BEGIN CERTIFICATE----- +MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYDVQQGEwJJTjET +MBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRl +ZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBHMTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgx +ODMwMDBaMGcxCzAJBgNVBAYTAklOMRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVk +aHJhIFRlY2hub2xvZ2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQzf2N4aLTN +LnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO8oG0x5ZOrRkVUkr+PHB1 +cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aqd7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHW +DV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhMtTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ +6DqS0hdW5TUaQBw+jSztOd9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrH +hQIDAQABo0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQDAgEG +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31xPaOfG1vR2vjTnGs2 +vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjMwiI/aTvFthUvozXGaCocV685743Q +NcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6dGNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q ++Mri/Tm3R7nrft8EI6/6nAYH6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeih +U80Bv2noWgbyRQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx +iN66zB+Afko= +-----END CERTIFICATE----- + +emSign ECC Root CA - G3 +======================= +-----BEGIN CERTIFICATE----- +MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQGEwJJTjETMBEG +A1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEg +MB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4 +MTgzMDAwWjBrMQswCQYDVQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11 +ZGhyYSBUZWNobm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g +RzMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0WXTsuwYc +58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xySfvalY8L1X44uT6EYGQIr +MgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuBzhccLikenEhjQjAOBgNVHQ8BAf8EBAMC +AQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+D +CBeQyh+KTOgNG3qxrdWBCUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7 +jHvrZQnD+JbNR6iC8hZVdyR+EhCVBCyj +-----END CERTIFICATE----- + +emSign Root CA - C1 +=================== +-----BEGIN CERTIFICATE----- +MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkGA1UEBhMCVVMx +EzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNp +Z24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQD +ExNlbVNpZ24gUm9vdCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+up +ufGZBczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZHdPIWoU/ +Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH3DspVpNqs8FqOp099cGX +OFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvHGPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4V +I5b2P/AgNBbeCsbEBEV5f6f9vtKppa+cxSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleooms +lMuoaJuvimUnzYnu3Yy1aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+ +XJGFehiqTbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87/kOXSTKZEhVb3xEp +/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4kqNPEjE2NuLe/gDEo2APJ62gsIq1 +NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrGYQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9 +wC68AivTxEDkigcxHpvOJpkT+xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQ +BmIMMMAVSKeoWXzhriKi4gp6D/piq1JM4fHfyr6DDUI= +-----END CERTIFICATE----- + +emSign ECC Root CA - C3 +======================= +-----BEGIN CERTIFICATE----- +MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQGEwJVUzETMBEG +A1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMxIDAeBgNVBAMTF2VtU2lnbiBF +Q0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAwMFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UE +BhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQD +ExdlbVNpZ24gRUNDIFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd +6bciMK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4OjavtisIGJAnB9 +SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0OBBYEFPtaSNCAIEDyqOkA +B2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gA +MGUCMQC02C8Cif22TGK6Q04ThHK1rt0c3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwU +ZOR8loMRnLDRWmFLpg9J0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ== +-----END CERTIFICATE----- + +Hongkong Post Root CA 3 +======================= +-----BEGIN CERTIFICATE----- +MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQELBQAwbzELMAkG +A1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJSG9uZyBLb25nMRYwFAYDVQQK +Ew1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25na29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2 +MDMwMjI5NDZaFw00MjA2MDMwMjI5NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtv +bmcxEjAQBgNVBAcTCUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMX +SG9uZ2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz +iNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFOdem1p+/l6TWZ5Mwc50tf +jTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mIVoBc+L0sPOFMV4i707mV78vH9toxdCim +5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOe +sL4jpNrcyCse2m5FHomY2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj +0mRiikKYvLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+TtbNe/ +JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZbx39ri1UbSsUgYT2u +y1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+l2oBlKN8W4UdKjk60FSh0Tlxnf0h ++bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YKTE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsG +xVd7GYYKecsAyVKvQv83j+GjHno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwID +AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e +i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEwDQYJKoZIhvcN +AQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG7BJ8dNVI0lkUmcDrudHr9Egw +W62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCkMpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWld +y8joRTnU+kLBEUx3XZL7av9YROXrgZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov ++BS5gLNdTaqX4fnkGMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDc +eqFS3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJmOzj/2ZQw +9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+l6mc1X5VTMbeRRAc6uk7 +nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6cJfTzPV4e0hz5sy229zdcxsshTrD3mUcY +hcErulWuBurQB7Lcq9CClnXO0lD+mefPL5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB +60PZ2Pierc+xYw5F9KBaLJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fq +dBb9HxEGmpv0 +-----END CERTIFICATE----- + +Entrust Root Certification Authority - G4 +========================================= +-----BEGIN CERTIFICATE----- +MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAwgb4xCzAJBgNV +BAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1 +dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1 +dGhvcml0eSAtIEc0MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYT +AlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 +L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eSAtIEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3D +umSXbcr3DbVZwbPLqGgZ2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV +3imz/f3ET+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j5pds +8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAMC1rlLAHGVK/XqsEQ +e9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73TDtTUXm6Hnmo9RR3RXRv06QqsYJn7 +ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNXwbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5X +xNMhIWNlUpEbsZmOeX7m640A2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV +7rtNOzK+mndmnqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8 +dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwlN4y6mACXi0mW +Hv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNjc0kCAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9n +MA0GCSqGSIb3DQEBCwUAA4ICAQAS5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4Q +jbRaZIxowLByQzTSGwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht +7LGrhFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/B7NTeLUK +YvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uIAeV8KEsD+UmDfLJ/fOPt +jqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbwH5Lk6rWS02FREAutp9lfx1/cH6NcjKF+ +m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKW +RGhXxNUzzxkvFMSUHHuk2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjA +JOgc47OlIQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk5F6G ++TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuYn/PIjhs4ViFqUZPT +kcpG2om3PVODLAgfi49T3f+sHw== +-----END CERTIFICATE----- + +Microsoft ECC Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV +UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQgRUND +IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4 +MjMxNjA0WjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw +NAYDVQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQ +BgcqhkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZRogPZnZH6 +thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYbhGBKia/teQ87zvH2RPUB +eMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTIy5lycFIM ++Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlf +Xu5gKcs68tvWMoQZP3zVL8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaR +eNtUjGUBiudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M= +-----END CERTIFICATE----- + +Microsoft RSA Root Certificate Authority 2017 +============================================= +-----BEGIN CERTIFICATE----- +MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBlMQswCQYDVQQG +EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNyb3NvZnQg +UlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIw +NzE4MjMwMDIzWjBlMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u +MTYwNAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcw +ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZNt9GkMml +7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0ZdDMbRnMlfl7rEqUrQ7e +S0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw7 +1VdyvD/IybLeS2v4I2wDwAW9lcfNcztmgGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+ +dkC0zVJhUXAoP8XFWvLJjEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49F +yGcohJUcaDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaGYaRS +MLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6W6IYZVcSn2i51BVr +lMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4KUGsTuqwPN1q3ErWQgR5WrlcihtnJ +0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJ +ClTUFLkqqNfs+avNJVgyeY+QW5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC +NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZCLgLNFgVZJ8og +6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OCgMNPOsduET/m4xaRhPtthH80 +dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk ++ONVFT24bcMKpBLBaYVu32TxU5nhSnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex +/2kskZGT4d9Mozd2TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDy +AmH3pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGRxpl/j8nW +ZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiAppGWSZI1b7rCoucL5mxAyE +7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKT +c0QWbej09+CVgI+WXTik9KveCjCHk9hNAHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D +5KbvtwEwXlGjefVwaaZBRA+GsCyRxj3qrg+E +-----END CERTIFICATE----- + +e-Szigno Root CA 2017 +===================== +-----BEGIN CERTIFICATE----- +MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNVBAYTAkhVMREw +DwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUt +MjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJvb3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZa +Fw00MjA4MjIxMjA3MDZaMHExCzAJBgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UE +CgwNTWljcm9zZWMgTHRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3pp +Z25vIFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtvxie+RJCx +s1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+HWyx7xf58etqjYzBhMA8G +A1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSHERUI0arBeAyxr87GyZDv +vzAEwDAfBgNVHSMEGDAWgBSHERUI0arBeAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEA +tVfd14pVCzbhhkT61NlojbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxO +svxyqltZ+efcMQ== +-----END CERTIFICATE----- + +certSIGN Root CA G2 +=================== +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNVBAYTAlJPMRQw +EgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjAeFw0xNzAy +MDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJBgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lH +TiBTQTEcMBoGA1UECxMTY2VydFNJR04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAMDFdRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05 +N0IwvlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZuIt4Imfk +abBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhpn+Sc8CnTXPnGFiWeI8Mg +wT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKscpc/I1mbySKEwQdPzH/iV8oScLumZfNp +dWO9lfsbl83kqK/20U6o2YpxJM02PbyWxPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91Qqh +ngLjYl/rNUssuHLoPj1PrCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732 +jcZZroiFDsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fxDTvf +95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgyLcsUDFDYg2WD7rlc +z8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6CeWRgKRM+o/1Pcmqr4tTluCRVLERL +iohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1Ud +DgQWBBSCIS1mxteg4BXrzkwJd8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOB +ywaK8SJJ6ejqkX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC +b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQlqiCA2ClV9+BB +/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0OJD7uNGzcgbJceaBxXntC6Z5 +8hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+cNywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5 +BiKDUyUM/FHE5r7iOZULJK2v0ZXkltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklW +atKcsWMy5WHgUyIOpwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tU +Sxfj03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZkPuXaTH4M +NMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE1LlSVHJ7liXMvGnjSG4N +0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MXQRBdJ3NghVdJIgc= +-----END CERTIFICATE----- + +Trustwave Global Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +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 +29FpHOTKyeC2nOnOcXHebD8WpHk= +-----END CERTIFICATE----- + +Trustwave Global ECC P256 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDI1 +NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABH77bOYj +43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoNFWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqm +P62jQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt +0UrrdaVKEJmzsaGLSvcwCgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjz +RM4q3wghDDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7 +-----END CERTIFICATE----- + +Trustwave Global ECC P384 Certification Authority +================================================= +-----BEGIN CERTIFICATE----- +MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYDVQQGEwJVUzER +MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0d2F2ZSBI +b2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYD +VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRy +dXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBFQ0MgUDM4 +NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuBBAAiA2IABGvaDXU1CDFH +Ba5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJj9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr +/TklZvFe/oyujUF5nQlgziip04pt89ZF1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNV +HQ8BAf8EBQMDBwYAMB0GA1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNn +ADBkAjA3AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsCMGcl +CrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVuSw== +-----END CERTIFICATE----- + +NAVER Global Root Certification Authority +========================================= +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIUAZQwHqIL3fXFMyqxQ0Rx+NZQTQ0wDQYJKoZIhvcNAQEMBQAwaTELMAkG +A1UEBhMCS1IxJjAkBgNVBAoMHU5BVkVSIEJVU0lORVNTIFBMQVRGT1JNIENvcnAuMTIwMAYDVQQD +DClOQVZFUiBHbG9iYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MTgwODU4 +NDJaFw0zNzA4MTgyMzU5NTlaMGkxCzAJBgNVBAYTAktSMSYwJAYDVQQKDB1OQVZFUiBCVVNJTkVT +UyBQTEFURk9STSBDb3JwLjEyMDAGA1UEAwwpTkFWRVIgR2xvYmFsIFJvb3QgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC21PGTXLVAiQqrDZBb +UGOukJR0F0Vy1ntlWilLp1agS7gvQnXp2XskWjFlqxcX0TM62RHcQDaH38dq6SZeWYp34+hInDEW ++j6RscrJo+KfziFTowI2MMtSAuXaMl3Dxeb57hHHi8lEHoSTGEq0n+USZGnQJoViAbbJAh2+g1G7 +XNr4rRVqmfeSVPc0W+m/6imBEtRTkZazkVrd/pBzKPswRrXKCAfHcXLJZtM0l/aM9BhK4dA9WkW2 +aacp+yPOiNgSnABIqKYPszuSjXEOdMWLyEz59JuOuDxp7W87UC9Y7cSw0BwbagzivESq2M0UXZR4 +Yb8ObtoqvC8MC3GmsxY/nOb5zJ9TNeIDoKAYv7vxvvTWjIcNQvcGufFt7QSUqP620wbGQGHfnZ3z +VHbOUzoBppJB7ASjjw2i1QnK1sua8e9DXcCrpUHPXFNwcMmIpi3Ua2FzUCaGYQ5fG8Ir4ozVu53B +A0K6lNpfqbDKzE0K70dpAy8i+/Eozr9dUGWokG2zdLAIx6yo0es+nPxdGoMuK8u180SdOqcXYZai +cdNwlhVNt0xz7hlcxVs+Qf6sdWA7G2POAN3aCJBitOUt7kinaxeZVL6HSuOpXgRM6xBtVNbv8ejy +YhbLgGvtPe31HzClrkvJE+2KAQHJuFFYwGY6sWZLxNUxAmLpdIQM201GLQIDAQABo0IwQDAdBgNV +HQ4EFgQU0p+I36HNLL3s9TsBAZMzJ7LrYEswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMB +Af8wDQYJKoZIhvcNAQEMBQADggIBADLKgLOdPVQG3dLSLvCkASELZ0jKbY7gyKoNqo0hV4/GPnrK +21HUUrPUloSlWGB/5QuOH/XcChWB5Tu2tyIvCZwTFrFsDDUIbatjcu3cvuzHV+YwIHHW1xDBE1UB +jCpD5EHxzzp6U5LOogMFDTjfArsQLtk70pt6wKGm+LUx5vR1yblTmXVHIloUFcd4G7ad6Qz4G3bx +hYTeodoS76TiEJd6eN4MUZeoIUCLhr0N8F5OSza7OyAfikJW4Qsav3vQIkMsRIz75Sq0bBwcupTg +E34h5prCy8VCZLQelHsIJchxzIdFV4XTnyliIoNRlwAYl3dqmJLJfGBs32x9SuRwTMKeuB330DTH +D8z7p/8Dvq1wkNoL3chtl1+afwkyQf3NosxabUzyqkn+Zvjp2DXrDige7kgvOtB5CTh8piKCk5XQ +A76+AqAF3SAi428diDRgxuYKuQl1C/AH6GmWNcf7I4GOODm4RStDeKLRLBT/DShycpWbXgnbiUSY +qqFJu3FS8r/2/yehNq+4tneI3TqkbZs0kNwUXTC/t+sX5Ie3cdCh13cV1ELX8vMxmV2b3RZtP+oG +I/hGoiLtk/bdmuYqh7GYVPEi92tF4+KOdh2ajcQGjTa3FPOdVGm3jjzVpG2Tgbet9r1ke8LJaDmg +kpzNNIaRkPpkUZ3+/uul9XXeifdy +-----END CERTIFICATE----- + +AC RAIZ FNMT-RCM SERVIDORES SEGUROS +=================================== +-----BEGIN CERTIFICATE----- +MIICbjCCAfOgAwIBAgIQYvYybOXE42hcG2LdnC6dlTAKBggqhkjOPQQDAzB4MQswCQYDVQQGEwJF +UzERMA8GA1UECgwIRk5NVC1SQ00xDjAMBgNVBAsMBUNlcmVzMRgwFgYDVQRhDA9WQVRFUy1RMjgy +NjAwNEoxLDAqBgNVBAMMI0FDIFJBSVogRk5NVC1SQ00gU0VSVklET1JFUyBTRUdVUk9TMB4XDTE4 +MTIyMDA5MzczM1oXDTQzMTIyMDA5MzczM1oweDELMAkGA1UEBhMCRVMxETAPBgNVBAoMCEZOTVQt +UkNNMQ4wDAYDVQQLDAVDZXJlczEYMBYGA1UEYQwPVkFURVMtUTI4MjYwMDRKMSwwKgYDVQQDDCNB +QyBSQUlaIEZOTVQtUkNNIFNFUlZJRE9SRVMgU0VHVVJPUzB2MBAGByqGSM49AgEGBSuBBAAiA2IA +BPa6V1PIyqvfNkpSIeSX0oNnnvBlUdBeh8dHsVnyV0ebAAKTRBdp20LHsbI6GA60XYyzZl2hNPk2 +LEnb80b8s0RpRBNm/dfF/a82Tc4DTQdxz69qBdKiQ1oKUm8BA06Oi6NCMEAwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFAG5L++/EYZg8k/QQW6rcx/n0m5JMAoGCCqG +SM49BAMDA2kAMGYCMQCuSuMrQMN0EfKVrRYj3k4MGuZdpSRea0R7/DjiT8ucRRcRTBQnJlU5dUoD +zBOQn5ICMQD6SmxgiHPz7riYYqnOK8LZiqZwMR2vsJRM60/G49HzYqc8/5MuB1xJAWdpEgJyv+c= +-----END CERTIFICATE----- + +GlobalSign Root R46 +=================== +-----BEGIN CERTIFICATE----- +MIIFWjCCA0KgAwIBAgISEdK7udcjGJ5AXwqdLdDfJWfRMA0GCSqGSIb3DQEBDAUAMEYxCzAJBgNV +BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJv +b3QgUjQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAX +BgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBSNDYwggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCsrHQy6LNl5brtQyYdpokNRbopiLKkHWPd08Es +CVeJOaFV6Wc0dwxu5FUdUiXSE2te4R2pt32JMl8Nnp8semNgQB+msLZ4j5lUlghYruQGvGIFAha/ +r6gjA7aUD7xubMLL1aa7DOn2wQL7Id5m3RerdELv8HQvJfTqa1VbkNud316HCkD7rRlr+/fKYIje +2sGP1q7Vf9Q8g+7XFkyDRTNrJ9CG0Bwta/OrffGFqfUo0q3v84RLHIf8E6M6cqJaESvWJ3En7YEt +bWaBkoe0G1h6zD8K+kZPTXhc+CtI4wSEy132tGqzZfxCnlEmIyDLPRT5ge1lFgBPGmSXZgjPjHvj +K8Cd+RTyG/FWaha/LIWFzXg4mutCagI0GIMXTpRW+LaCtfOW3T3zvn8gdz57GSNrLNRyc0NXfeD4 +12lPFzYE+cCQYDdF3uYM2HSNrpyibXRdQr4G9dlkbgIQrImwTDsHTUB+JMWKmIJ5jqSngiCNI/on +ccnfxkF0oE32kRbcRoxfKWMxWXEM2G/CtjJ9++ZdU6Z+Ffy7dXxd7Pj2Fxzsx2sZy/N78CsHpdls +eVR2bJ0cpm4O6XkMqCNqo98bMDGfsVR7/mrLZqrcZdCinkqaByFrgY/bxFn63iLABJzjqls2k+g9 +vXqhnQt2sQvHnf3PmKgGwvgqo6GDoLclcqUC4wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA1yrc4GHqMywptWU4jaWSf8FmSwwDQYJKoZIhvcNAQEM +BQADggIBAHx47PYCLLtbfpIrXTncvtgdokIzTfnvpCo7RGkerNlFo048p9gkUbJUHJNOxO97k4Vg +JuoJSOD1u8fpaNK7ajFxzHmuEajwmf3lH7wvqMxX63bEIaZHU1VNaL8FpO7XJqti2kM3S+LGteWy +gxk6x9PbTZ4IevPuzz5i+6zoYMzRx6Fcg0XERczzF2sUyQQCPtIkpnnpHs6i58FZFZ8d4kuaPp92 +CC1r2LpXFNqD6v6MVenQTqnMdzGxRBF6XLE+0xRFFRhiJBPSy03OXIPBNvIQtQ6IbbjhVp+J3pZm +OUdkLG5NrmJ7v2B0GbhWrJKsFjLtrWhV/pi60zTe9Mlhww6G9kuEYO4Ne7UyWHmRVSyBQ7N0H3qq +JZ4d16GLuc1CLgSkZoNNiTW2bKg2SnkheCLQQrzRQDGQob4Ez8pn7fXwgNNgyYMqIgXQBztSvwye +qiv5u+YfjyW6hY0XHgL+XVAEV8/+LbzvXMAaq7afJMbfc2hIkCwU9D9SGuTSyxTDYWnP4vkYxboz +nxSjBF25cfe1lNj2M8FawTSLfJvdkzrnE6JwYZ+vj+vYxXX4M2bUdGc6N3ec592kD3ZDZopD8p/7 +DEJ4Y9HiD2971KE9dJeFt0g5QdYg/NA6s/rob8SKunE3vouXsXgxT7PntgMTzlSdriVZzH81Xwj3 +QEUxeCp6 +-----END CERTIFICATE----- + +GlobalSign Root E46 +=================== +-----BEGIN CERTIFICATE----- +MIICCzCCAZGgAwIBAgISEdK7ujNu1LzmJGjFDYQdmOhDMAoGCCqGSM49BAMDMEYxCzAJBgNVBAYT +AkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRwwGgYDVQQDExNHbG9iYWxTaWduIFJvb3Qg +RTQ2MB4XDTE5MDMyMDAwMDAwMFoXDTQ2MDMyMDAwMDAwMFowRjELMAkGA1UEBhMCQkUxGTAXBgNV +BAoTEEdsb2JhbFNpZ24gbnYtc2ExHDAaBgNVBAMTE0dsb2JhbFNpZ24gUm9vdCBFNDYwdjAQBgcq +hkjOPQIBBgUrgQQAIgNiAAScDrHPt+ieUnd1NPqlRqetMhkytAepJ8qUuwzSChDH2omwlwxwEwkB +jtjqR+q+soArzfwoDdusvKSGN+1wCAB16pMLey5SnCNoIwZD7JIvU4Tb+0cUB+hflGddyXqBPCCj +QjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQxCpCPtsad0kRL +gLWi5h+xEk8blTAKBggqhkjOPQQDAwNoADBlAjEA31SQ7Zvvi5QCkxeCmb6zniz2C5GMn0oUsfZk +vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+ +CAezNIm8BZ/3Hobui3A= +-----END CERTIFICATE----- + +GLOBALTRUST 2020 +================ +-----BEGIN CERTIFICATE----- +MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx +IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT +VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh +BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy +MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi +D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO +VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM +CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm +fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA +A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR +JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG +DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU +clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ +mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw +AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud +IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA +VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw +4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9 +iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS +8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2 +HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS +vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918 +oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF +YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl +gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg== +-----END CERTIFICATE----- + +ANF Secure Server Root CA +========================= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Certum EC-384 CA +================ +-----BEGIN CERTIFICATE----- +MIICZTCCAeugAwIBAgIQeI8nXIESUiClBNAt3bpz9DAKBggqhkjOPQQDAzB0MQswCQYDVQQGEwJQ +TDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxGTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwHhcNMTgwMzI2 +MDcyNDU0WhcNNDMwMzI2MDcyNDU0WjB0MQswCQYDVQQGEwJQTDEhMB8GA1UEChMYQXNzZWNvIERh +dGEgU3lzdGVtcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkx +GTAXBgNVBAMTEENlcnR1bSBFQy0zODQgQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAATEKI6rGFtq +vm5kN2PkzeyrOvfMobgOgknXhimfoZTy42B4mIF4Bk3y7JoOV2CDn7TmFy8as10CW4kjPMIRBSqn +iBMY81CE1700LCeJVf/OTOffph8oxPBUw7l8t1Ot68KjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD +VR0OBBYEFI0GZnQkdjrzife81r1HfS+8EF9LMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNo +ADBlAjADVS2m5hjEfO/JUG7BJw+ch69u1RsIGL2SKcHvlJF40jocVYli5RsJHrpka/F2tNQCMQC0 +QoSZ/6vnnvuRlydd3LBbMHHOXjgaatkl5+r3YZJW+OraNsKHZZYuciUvf9/DE8k= +-----END CERTIFICATE----- + +Certum Trusted Root CA +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +TunTrust Root CA +================ +-----BEGIN CERTIFICATE----- +MIIFszCCA5ugAwIBAgIUEwLV4kBMkkaGFmddtLu7sms+/BMwDQYJKoZIhvcNAQELBQAwYTELMAkG +A1UEBhMCVE4xNzA1BgNVBAoMLkFnZW5jZSBOYXRpb25hbGUgZGUgQ2VydGlmaWNhdGlvbiBFbGVj +dHJvbmlxdWUxGTAXBgNVBAMMEFR1blRydXN0IFJvb3QgQ0EwHhcNMTkwNDI2MDg1NzU2WhcNNDQw +NDI2MDg1NzU2WjBhMQswCQYDVQQGEwJUTjE3MDUGA1UECgwuQWdlbmNlIE5hdGlvbmFsZSBkZSBD +ZXJ0aWZpY2F0aW9uIEVsZWN0cm9uaXF1ZTEZMBcGA1UEAwwQVHVuVHJ1c3QgUm9vdCBDQTCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMPN0/y9BFPdDCA61YguBUtB9YOCfvdZn56eY+hz +2vYGqU8ftPkLHzmMmiDQfgbU7DTZhrx1W4eI8NLZ1KMKsmwb60ksPqxd2JQDoOw05TDENX37Jk0b +bjBU2PWARZw5rZzJJQRNmpA+TkBuimvNKWfGzC3gdOgFVwpIUPp6Q9p+7FuaDmJ2/uqdHYVy7BG7 +NegfJ7/Boce7SBbdVtfMTqDhuazb1YMZGoXRlJfXyqNlC/M4+QKu3fZnz8k/9YosRxqZbwUN/dAd +gjH8KcwAWJeRTIAAHDOFli/LQcKLEITDCSSJH7UP2dl3RxiSlGBcx5kDPP73lad9UKGAwqmDrViW +VSHbhlnUr8a83YFuB9tgYv7sEG7aaAH0gxupPqJbI9dkxt/con3YS7qC0lH4Zr8GRuR5KiY2eY8f +Tpkdso8MDhz/yV3A/ZAQprE38806JG60hZC/gLkMjNWb1sjxVj8agIl6qeIbMlEsPvLfe/ZdeikZ +juXIvTZxi11Mwh0/rViizz1wTaZQmCXcI/m4WEEIcb9PuISgjwBUFfyRbVinljvrS5YnzWuioYas +DXxU5mZMZl+QviGaAkYt5IPCgLnPSz7ofzwB7I9ezX/SKEIBlYrilz0QIX32nRzFNKHsLA4KUiwS +VXAkPcvCFDVDXSdOvsC9qnyW5/yeYa1E0wCXAgMBAAGjYzBhMB0GA1UdDgQWBBQGmpsfU33x9aTI +04Y+oXNZtPdEITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFAaamx9TffH1pMjThj6hc1m0 +90QhMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAqgVutt0Vyb+zxiD2BkewhpMl +0425yAA/l/VSJ4hxyXT968pk21vvHl26v9Hr7lxpuhbI87mP0zYuQEkHDVneixCwSQXi/5E/S7fd +Ao74gShczNxtr18UnH1YeA32gAm56Q6XKRm4t+v4FstVEuTGfbvE7Pi1HE4+Z7/FXxttbUcoqgRY +YdZ2vyJ/0Adqp2RT8JeNnYA/u8EH22Wv5psymsNUk8QcCMNE+3tjEUPRahphanltkE8pjkcFwRJp +adbGNjHh/PqAulxPxOu3Mqz4dWEX1xAZufHSCe96Qp1bWgvUxpVOKs7/B9dPfhgGiPEZtdmYu65x +xBzndFlY7wyJz4sfdZMaBBSSSFCp61cpABbjNhzI+L/wM9VBD8TMPN3pM0MBkRArHtG5Xc0yGYuP +jCB31yLEQtyEFpslbei0VXF/sHyz03FJuc9SpAQ/3D2gu68zngowYI7bnV2UqL1g52KAdoGDDIzM +MEZJ4gzSqK/rYXHv5yJiqfdcZGyfFoxnNidF9Ql7v/YQCvGwjVRDjAS6oz/v4jXH+XTgbzRB0L9z +ZVcg+ZtnemZoJE6AZb0QmQZZ8mWvuMZHu/2QeItBcy6vVR/cO5JyboTT0GFMDcx2V+IthSIVNg3r +AZ3r2OvEhJn7wAzMMujjd9qDRIueVSjAi1jTkD5OGwDxFa2DK5o= +-----END CERTIFICATE----- + +HARICA TLS RSA Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIQOcqTHO9D88aOk8f0ZIk4fjANBgkqhkiG9w0BAQsFADBsMQswCQYDVQQG +EwJHUjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u +cyBDQTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBSU0EgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTEwNTUz +OFoXDTQ1MDIxMzEwNTUzN1owbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRl +bWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgUlNB +IFJvb3QgQ0EgMjAyMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIvC569lmwVnlskN +JLnQDmT8zuIkGCyEf3dRywQRNrhe7Wlxp57kJQmXZ8FHws+RFjZiPTgE4VGC/6zStGndLuwRo0Xu +a2s7TL+MjaQenRG56Tj5eg4MmOIjHdFOY9TnuEFE+2uva9of08WRiFukiZLRgeaMOVig1mlDqa2Y +Ulhu2wr7a89o+uOkXjpFc5gH6l8Cct4MpbOfrqkdtx2z/IpZ525yZa31MJQjB/OCFks1mJxTuy/K +5FrZx40d/JiZ+yykgmvwKh+OC19xXFyuQnspiYHLA6OZyoieC0AJQTPb5lh6/a6ZcMBaD9YThnEv +dmn8kN3bLW7R8pv1GmuebxWMevBLKKAiOIAkbDakO/IwkfN4E8/BPzWr8R0RI7VDIp4BkrcYAuUR +0YLbFQDMYTfBKnya4dC6s1BG7oKsnTH4+yPiAwBIcKMJJnkVU2DzOFytOOqBAGMUuTNe3QvboEUH +GjMJ+E20pwKmafTCWQWIZYVWrkvL4N48fS0ayOn7H6NhStYqE613TBoYm5EPWNgGVMWX+Ko/IIqm +haZ39qb8HOLubpQzKoNQhArlT4b4UEV4AIHrW2jjJo3Me1xR9BQsQL4aYB16cmEdH2MtiKrOokWQ +CPxrvrNQKlr9qEgYRtaQQJKQCoReaDH46+0N0x3GfZkYVVYnZS6NRcUk7M7jAgMBAAGjQjBAMA8G +A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFApII6ZgpJIKM+qTW8VX6iVNvRLuMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAPpBIqm5iFSVmewzVjIuJndftTgfvnNAUX15QvWiWkKQU +EapobQk1OUAJ2vQJLDSle1mESSmXdMgHHkdt8s4cUCbjnj1AUz/3f5Z2EMVGpdAgS1D0NTsY9FVq +QRtHBmg8uwkIYtlfVUKqrFOFrJVWNlar5AWMxajaH6NpvVMPxP/cyuN+8kyIhkdGGvMA9YCRotxD +QpSbIPDRzbLrLFPCU3hKTwSUQZqPJzLB5UkZv/HywouoCjkxKLR9YjYsTewfM7Z+d21+UPCfDtcR +j88YxeMn/ibvBZ3PzzfF0HvaO7AWhAw6k9a+F9sPPg4ZeAnHqQJyIkv3N3a6dcSFA1pj1bF1BcK5 +vZStjBWZp5N99sXzqnTPBIWUmAD04vnKJGW/4GKvyMX6ssmeVkjaef2WdhW+o45WxLM0/L5H9MG0 +qPzVMIho7suuyWPEdr6sOBjhXlzPrjoiUevRi7PzKzMHVIf6tLITe7pTBGIBnfHAT+7hOtSLIBD6 +Alfm78ELt5BGnBkpjNxvoEppaZS3JGWg/6w/zgH7IS79aPib8qXPMThcFarmlwDB31qlpzmq6YR/ +PFGoOtmUW4y/Twhx5duoXNTSpv4Ao8YWxw/ogM4cKGR0GQjTQuPOAF1/sdwTsOEFy9EgqoZ0njnn +kf3/W9b3raYvAwtt41dU63ZTGI0RmLo= +-----END CERTIFICATE----- + +HARICA TLS ECC Root CA 2021 +=========================== +-----BEGIN CERTIFICATE----- +MIICVDCCAdugAwIBAgIQZ3SdjXfYO2rbIvT/WeK/zjAKBggqhkjOPQQDAzBsMQswCQYDVQQGEwJH +UjE3MDUGA1UECgwuSGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBD +QTEkMCIGA1UEAwwbSEFSSUNBIFRMUyBFQ0MgUm9vdCBDQSAyMDIxMB4XDTIxMDIxOTExMDExMFoX +DTQ1MDIxMzExMDEwOVowbDELMAkGA1UEBhMCR1IxNzA1BgNVBAoMLkhlbGxlbmljIEFjYWRlbWlj +IGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ0ExJDAiBgNVBAMMG0hBUklDQSBUTFMgRUNDIFJv +b3QgQ0EgMjAyMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABDgI/rGgltJ6rK9JOtDA4MM7KKrxcm1l +AEeIhPyaJmuqS7psBAqIXhfyVYf8MLA04jRYVxqEU+kw2anylnTDUR9YSTHMmE5gEYd103KUkE+b +ECUqqHgtvpBBWJAVcqeht6NCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUyRtTgRL+BNUW +0aq8mm+3oJUZbsowDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2cAMGQCMBHervjcToiwqfAi +rcJRQO9gcS3ujwLEXQNwSaSS6sUUiHCm0w2wqsosQJz76YJumgIwK0eaB8bRwoF8yguWGEEbo/Qw +CZ61IygNnxS2PFOiTAZpffpskcYqSUXm7LcT4Tps +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIG3Dp0v+ubHEwDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0xNDA5MjMxNTIyMDdaFw0zNjA1MDUxNTIyMDdaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMB0GA1Ud +DgQWBBRlzeurNR4APn7VdMActHNHDhpkLzASBgNVHRMBAf8ECDAGAQH/AgEBMIGmBgNVHSAEgZ4w +gZswgZgGBFUdIAAwgY8wLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuZmlybWFwcm9mZXNpb25hbC5j +b20vY3BzMFwGCCsGAQUFBwICMFAeTgBQAGEAcwBlAG8AIABkAGUAIABsAGEAIABCAG8AbgBhAG4A +bwB2AGEAIAA0ADcAIABCAGEAcgBjAGUAbABvAG4AYQAgADAAOAAwADEANzAOBgNVHQ8BAf8EBAMC +AQYwDQYJKoZIhvcNAQELBQADggIBAHSHKAIrdx9miWTtj3QuRhy7qPj4Cx2Dtjqn6EWKB7fgPiDL +4QjbEwj4KKE1soCzC1HA01aajTNFSa9J8OA9B3pFE1r/yJfY0xgsfZb43aJlQ3CTkBW6kN/oGbDb +LIpgD7dvlAceHabJhfa9NPhAeGIQcDq+fUs5gakQ1JZBu/hfHAsdCPKxsIl68veg4MSPi3i1O1il +I45PVf42O+AMt8oqMEEgtIDNrvx2ZnOorm7hfNoD6JQg5iKj0B+QXSBTFCZX2lSX3xZEEAEeiGaP +cjiT3SC3NL7X8e5jjkd5KAb881lFJWAiMxujX6i6KtoaPc1A6ozuBRWV1aUsIC+nmCjuRfzxuIgA +LI9C2lHVnOUTaHFFQ4ueCyE8S1wF3BqfmI7avSKecs2tCsvMo2ebKHTEm9caPARYpoKdrcd7b/+A +lun4jWq9GJAd/0kakFI3ky88Al2CdgtR5xbHV/g4+afNmyJU72OwFW1TZQNKXkqgsqeOSQBZONXH +9IBk9W6VULgRfhVwOEqwf9DEMnDAGf/JOC0ULGb0QkTmVXYbgBVX/8Cnp6o5qtjTcNAuuuuUavpf +NIbnYrX9ivAwhZTJryQCL2/W3Wf+47BVTwSYT6RBVuKT0Gro1vP7ZeDOdcQxWQzugsgMYDNKGbqE +ZycPvEJdvSRUDewdcAZfpLz6IHxV +-----END CERTIFICATE----- + +vTrus ECC Root CA +================= +-----BEGIN CERTIFICATE----- +MIICDzCCAZWgAwIBAgIUbmq8WapTvpg5Z6LSa6Q75m0c1towCgYIKoZIzj0EAwMwRzELMAkGA1UE +BhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBS +b290IENBMB4XDTE4MDczMTA3MjY0NFoXDTQzMDczMTA3MjY0NFowRzELMAkGA1UEBhMCQ04xHDAa +BgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xGjAYBgNVBAMTEXZUcnVzIEVDQyBSb290IENBMHYw +EAYHKoZIzj0CAQYFK4EEACIDYgAEZVBKrox5lkqqHAjDo6LN/llWQXf9JpRCux3NCNtzslt188+c +ToL0v/hhJoVs1oVbcnDS/dtitN9Ti72xRFhiQgnH+n9bEOf+QP3A2MMrMudwpremIFUde4BdS49n +TPEQo0IwQDAdBgNVHQ4EFgQUmDnNvtiyjPeyq+GtJK97fKHbH88wDwYDVR0TAQH/BAUwAwEB/zAO +BgNVHQ8BAf8EBAMCAQYwCgYIKoZIzj0EAwMDaAAwZQIwV53dVvHH4+m4SVBrm2nDb+zDfSXkV5UT +QJtS0zvzQBm8JsctBp61ezaf9SXUY2sAAjEA6dPGnlaaKsyh2j/IZivTWJwghfqrkYpwcBE4YGQL +YgmRWAD5Tfs0aNoJrSEGGJTO +-----END CERTIFICATE----- + +vTrus Root CA +============= +-----BEGIN CERTIFICATE----- +MIIFVjCCAz6gAwIBAgIUQ+NxE9izWRRdt86M/TX9b7wFjUUwDQYJKoZIhvcNAQELBQAwQzELMAkG +A1UEBhMCQ04xHDAaBgNVBAoTE2lUcnVzQ2hpbmEgQ28uLEx0ZC4xFjAUBgNVBAMTDXZUcnVzIFJv +b3QgQ0EwHhcNMTgwNzMxMDcyNDA1WhcNNDMwNzMxMDcyNDA1WjBDMQswCQYDVQQGEwJDTjEcMBoG +A1UEChMTaVRydXNDaGluYSBDby4sTHRkLjEWMBQGA1UEAxMNdlRydXMgUm9vdCBDQTCCAiIwDQYJ +KoZIhvcNAQEBBQADggIPADCCAgoCggIBAL1VfGHTuB0EYgWgrmy3cLRB6ksDXhA/kFocizuwZots +SKYcIrrVQJLuM7IjWcmOvFjai57QGfIvWcaMY1q6n6MLsLOaXLoRuBLpDLvPbmyAhykUAyyNJJrI +ZIO1aqwTLDPxn9wsYTwaP3BVm60AUn/PBLn+NvqcwBauYv6WTEN+VRS+GrPSbcKvdmaVayqwlHeF +XgQPYh1jdfdr58tbmnDsPmcF8P4HCIDPKNsFxhQnL4Z98Cfe/+Z+M0jnCx5Y0ScrUw5XSmXX+6KA +YPxMvDVTAWqXcoKv8R1w6Jz1717CbMdHflqUhSZNO7rrTOiwCcJlwp2dCZtOtZcFrPUGoPc2BX70 +kLJrxLT5ZOrpGgrIDajtJ8nU57O5q4IikCc9Kuh8kO+8T/3iCiSn3mUkpF3qwHYw03dQ+A0Em5Q2 +AXPKBlim0zvc+gRGE1WKyURHuFE5Gi7oNOJ5y1lKCn+8pu8fA2dqWSslYpPZUxlmPCdiKYZNpGvu +/9ROutW04o5IWgAZCfEF2c6Rsffr6TlP9m8EQ5pV9T4FFL2/s1m02I4zhKOQUqqzApVg+QxMaPnu +1RcN+HFXtSXkKe5lXa/R7jwXC1pDxaWG6iSe4gUH3DRCEpHWOXSuTEGC2/KmSNGzm/MzqvOmwMVO +9fSddmPmAsYiS8GVP1BkLFTltvA8Kc9XAgMBAAGjQjBAMB0GA1UdDgQWBBRUYnBj8XWEQ1iO0RYg +scasGrz2iTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOC +AgEAKbqSSaet8PFww+SX8J+pJdVrnjT+5hpk9jprUrIQeBqfTNqK2uwcN1LgQkv7bHbKJAs5EhWd +nxEt/Hlk3ODg9d3gV8mlsnZwUKT+twpw1aA08XXXTUm6EdGz2OyC/+sOxL9kLX1jbhd47F18iMjr +jld22VkE+rxSH0Ws8HqA7Oxvdq6R2xCOBNyS36D25q5J08FsEhvMKar5CKXiNxTKsbhm7xqC5PD4 +8acWabfbqWE8n/Uxy+QARsIvdLGx14HuqCaVvIivTDUHKgLKeBRtRytAVunLKmChZwOgzoy8sHJn +xDHO2zTlJQNgJXtxmOTAGytfdELSS8VZCAeHvsXDf+eW2eHcKJfWjwXj9ZtOyh1QRwVTsMo554Wg +icEFOwE30z9J4nfrI8iIZjs9OXYhRvHsXyO466JmdXTBQPfYaJqT4i2pLr0cox7IdMakLXogqzu4 +sEb9b91fUlV1YvCXoHzXOP0l382gmxDPi7g4Xl7FtKYCNqEeXxzP4padKar9mK5S4fNBUvupLnKW +nyfjqnN9+BojZns7q2WwMgFLFT49ok8MKzWixtlnEjUwzXYuFrOZnk1PTi07NEPhmg4NpGaXutIc +SkwsKouLgU9xGqndXHt7CMUADTdA43x7VF8vhV929vensBxXVsFy6K2ir40zSbofitzmdHxghm+H +l3s= +-----END CERTIFICATE----- + +ISRG Root X2 +============ +-----BEGIN CERTIFICATE----- +MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQswCQYDVQQGEwJV +UzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElT +UkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVT +MSkwJwYDVQQKEyBJbnRlcm5ldCBTZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNS +RyBSb290IFgyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0H +ttwW+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9ItgKbppb +d9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV +HQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZIzj0EAwMDaAAwZQIwe3lORlCEwkSHRhtF +cP9Ymd70/aTSVaYgLXTWNLxBo1BfASdWtL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5 +U6VR5CmD1/iQMVtCnwr1/q4AaOeMSQ+2b1tbFfLn +-----END CERTIFICATE----- + +HiPKI Root CA - G1 +================== +-----BEGIN CERTIFICATE----- +MIIFajCCA1KgAwIBAgIQLd2szmKXlKFD6LDNdmpeYDANBgkqhkiG9w0BAQsFADBPMQswCQYDVQQG +EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xGzAZBgNVBAMMEkhpUEtJ +IFJvb3QgQ0EgLSBHMTAeFw0xOTAyMjIwOTQ2MDRaFw0zNzEyMzExNTU5NTlaME8xCzAJBgNVBAYT +AlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEbMBkGA1UEAwwSSGlQS0kg +Um9vdCBDQSAtIEcxMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9B5/UnMyDHPkvRN0 +o9QwqNCuS9i233VHZvR85zkEHmpwINJaR3JnVfSl6J3VHiGh8Ge6zCFovkRTv4354twvVcg3Px+k +wJyz5HdcoEb+d/oaoDjq7Zpy3iu9lFc6uux55199QmQ5eiY29yTw1S+6lZgRZq2XNdZ1AYDgr/SE +YYwNHl98h5ZeQa/rh+r4XfEuiAU+TCK72h8q3VJGZDnzQs7ZngyzsHeXZJzA9KMuH5UHsBffMNsA +GJZMoYFL3QRtU6M9/Aes1MU3guvklQgZKILSQjqj2FPseYlgSGDIcpJQ3AOPgz+yQlda22rpEZfd +hSi8MEyr48KxRURHH+CKFgeW0iEPU8DtqX7UTuybCeyvQqww1r/REEXgphaypcXTT3OUM3ECoWqj +1jOXTyFjHluP2cFeRXF3D4FdXyGarYPM+l7WjSNfGz1BryB1ZlpK9p/7qxj3ccC2HTHsOyDry+K4 +9a6SsvfhhEvyovKTmiKe0xRvNlS9H15ZFblzqMF8b3ti6RZsR1pl8w4Rm0bZ/W3c1pzAtH2lsN0/ +Vm+h+fbkEkj9Bn8SV7apI09bA8PgcSojt/ewsTu8mL3WmKgMa/aOEmem8rJY5AIJEzypuxC00jBF +8ez3ABHfZfjcK0NVvxaXxA/VLGGEqnKG/uY6fsI/fe78LxQ+5oXdUG+3Se0CAwEAAaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ncX+l6o/vY9cdVouslGDDjYr7AwDgYDVR0PAQH/BAQD +AgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBQUfB13HAE4/+qddRxosuej6ip0691x1TPOhwEmSKsxBHi +7zNKpiMdDg1H2DfHb680f0+BazVP6XKlMeJ45/dOlBhbQH3PayFUhuaVevvGyuqcSE5XCV0vrPSl +tJczWNWseanMX/mF+lLFjfiRFOs6DRfQUsJ748JzjkZ4Bjgs6FzaZsT0pPBWGTMpWmWSBUdGSquE +wx4noR8RkpkndZMPvDY7l1ePJlsMu5wP1G4wB9TcXzZoZjmDlicmisjEOf6aIW/Vcobpf2Lll07Q +JNBAsNB1CI69aO4I1258EHBGG3zgiLKecoaZAeO/n0kZtCW+VmWuF2PlHt/o/0elv+EmBYTksMCv +5wiZqAxeJoBF1PhoL5aPruJKHJwWDBNvOIf2u8g0X5IDUXlwpt/L9ZlNec1OvFefQ05rLisY+Gpz +jLrFNe85akEez3GoorKGB1s6yeHvP2UEgEcyRHCVTjFnanRbEEV16rCf0OY1/k6fi8wrkkVbbiVg +hUbN0aqwdmaTd5a+g744tiROJgvM7XpWGuDpWsZkrUx6AEhEL7lAuxM+vhV4nYWBSipX3tUZQ9rb +yltHhoMLP7YNdnhzeSJesYAfz77RP1YQmCuVh6EfnWQUYDksswBVLuT1sw5XxJFBAJw/6KXf6vb/ +yPCtbVKoF6ubYfwSUTXkJf2vqmqGOQ== +-----END CERTIFICATE----- + +GlobalSign ECC Root CA - R4 +=========================== +-----BEGIN CERTIFICATE----- +MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgwMTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9i +YWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds +b2JhbFNpZ24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkW +ymOxuYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNVHQ8BAf8E +BAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/+wpu+74zyTyjhNUwCgYI +KoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147bmF0774BxL4YSFlhgjICICadVGNA3jdg +UM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm +-----END CERTIFICATE----- + +GTS Root R1 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM +f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7wCl7raKb0 +xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjwTcLCeoiKu7rPWRnWr4+w +B7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0PfyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXW +nOunVmSPlk9orj2XwoSPwLxAwAtcvfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk +9+aCEI3oncKKiPo4Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zq +kUspzBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92wO1A +K/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70paDPvOmbsB4om3xPX +V2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDW +cfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQAD +ggIBAJ+qQibbC5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe +QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuyh6f88/qBVRRi +ClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM47HLwEXWdyzRSjeZ2axfG34ar +J45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8JZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYci +NuaCp+0KueIHoI17eko8cdLiA6EfMgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5me +LMFrUKTX5hgUvYU/Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJF +fbdT6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ0E6yove+ +7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm2tIMPNuzjsmhDYAPexZ3 +FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bbbP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3 +gm3c +-----END CERTIFICATE----- + +GTS Root R2 +=========== +-----BEGIN CERTIFICATE----- +MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQswCQYDVQQGEwJV +UzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3Qg +UjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UE +ChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv +CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY6Dlo7JUl +e3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAuMC6C/Pq8tBcKSOWIm8Wb +a96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS ++LFjKBC4swm4VndAoiaYecb+3yXuPuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7M +kogwTZq9TwtImoS1mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJG +r61K8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RWIr9q +S34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKaG73VululycslaVNV +J1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCqgc7dGtxRcw1PcOnlthYhGXmy5okL +dWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQAD +ggIBAB/Kzt3HvqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8 +0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyCB19m3H0Q/gxh +swWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2uNmSRXbBoGOqKYcl3qJfEycel +/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMgyALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVn +jWQye+mew4K6Ki3pHrTgSAai/GevHyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y5 +9PYjJbigapordwj6xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M +7YNRTOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924SgJPFI/2R8 +0L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV7LXTWtiBmelDGDfrs7vR +WGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjW +HYbL +-----END CERTIFICATE----- + +GTS Root R3 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout +736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL24CejQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTB8Sa6oC2uhYHP0/Eq +Er24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azT +L818+FsuVbu/3ZL3pAzcMeGiAjEA/JdmZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV +11RZt+cRLInUue4X +-----END CERTIFICATE----- + +GTS Root R4 +=========== +-----BEGIN CERTIFICATE----- +MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYDVQQGEwJVUzEi +MCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQw +HhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZ +R29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu +hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvRHYqjQjBA +MA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSATNbrdP9JNqPV2Py1 +PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/C +r8deVl5c1RxYIigL9zC2L7F8AjEA8GE8p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh +4rsUecrNIdSUtUlD +-----END CERTIFICATE----- + +Telia Root CA v2 +================ +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIPAWdfJ9b+euPkrL4JWwWeMA0GCSqGSIb3DQEBCwUAMEQxCzAJBgNVBAYT +AkZJMRowGAYDVQQKDBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2 +MjAeFw0xODExMjkxMTU1NTRaFw00MzExMjkxMTU1NTRaMEQxCzAJBgNVBAYTAkZJMRowGAYDVQQK +DBFUZWxpYSBGaW5sYW5kIE95ajEZMBcGA1UEAwwQVGVsaWEgUm9vdCBDQSB2MjCCAiIwDQYJKoZI +hvcNAQEBBQADggIPADCCAgoCggIBALLQPwe84nvQa5n44ndp586dpAO8gm2h/oFlH0wnrI4AuhZ7 +6zBqAMCzdGh+sq/H1WKzej9Qyow2RCRj0jbpDIX2Q3bVTKFgcmfiKDOlyzG4OiIjNLh9vVYiQJ3q +9HsDrWj8soFPmNB06o3lfc1jw6P23pLCWBnglrvFxKk9pXSW/q/5iaq9lRdU2HhE8Qx3FZLgmEKn +pNaqIJLNwaCzlrI6hEKNfdWV5Nbb6WLEWLN5xYzTNTODn3WhUidhOPFZPY5Q4L15POdslv5e2QJl +tI5c0BE0312/UqeBAMN/mUWZFdUXyApT7GPzmX3MaRKGwhfwAZ6/hLzRUssbkmbOpFPlob/E2wnW +5olWK8jjfN7j/4nlNW4o6GwLI1GpJQXrSPjdscr6bAhR77cYbETKJuFzxokGgeWKrLDiKca5JLNr +RBH0pUPCTEPlcDaMtjNXepUugqD0XBCzYYP2AgWGLnwtbNwDRm41k9V6lS/eINhbfpSQBGq6WT0E +BXWdN6IOLj3rwaRSg/7Qa9RmjtzG6RJOHSpXqhC8fF6CfaamyfItufUXJ63RDolUK5X6wK0dmBR4 +M0KGCqlztft0DbcbMBnEWg4cJ7faGND/isgFuvGqHKI3t+ZIpEYslOqodmJHixBTB0hXbOKSTbau +BcvcwUpej6w9GU7C7WB1K9vBykLVAgMBAAGjYzBhMB8GA1UdIwQYMBaAFHKs5DN5qkWH9v2sHZ7W +xy+G2CQ5MB0GA1UdDgQWBBRyrOQzeapFh/b9rB2e1scvhtgkOTAOBgNVHQ8BAf8EBAMCAQYwDwYD +VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAoDtZpwmUPjaE0n4vOaWWl/oRrfxn83EJ +8rKJhGdEr7nv7ZbsnGTbMjBvZ5qsfl+yqwE2foH65IRe0qw24GtixX1LDoJt0nZi0f6X+J8wfBj5 +tFJ3gh1229MdqfDBmgC9bXXYfef6xzijnHDoRnkDry5023X4blMMA8iZGok1GTzTyVR8qPAs5m4H +eW9q4ebqkYJpCh3DflminmtGFZhb069GHWLIzoBSSRE/yQQSwxN8PzuKlts8oB4KtItUsiRnDe+C +y748fdHif64W1lZYudogsYMVoe+KTTJvQS8TUoKU1xrBeKJR3Stwbbca+few4GeXVtt8YVMJAygC +QMez2P2ccGrGKMOF6eLtGpOg3kuYooQ+BXcBlj37tCAPnHICehIv1aO6UXivKitEZU61/Qrowc15 +h2Er3oBXRb9n8ZuRXqWk7FlIEA04x7D6w0RtBPV4UBySllva9bguulvP5fBqnUsvWHMtTy3EHD70 +sz+rFQ47GUGKpMFXEmZxTPpT41frYpUJnlTd0cI8Vzy9OK2YZLe4A5pTVmBds9hCG1xLEooc6+t9 +xnppxyd/pPiL8uSUZodL6ZQHCRJ5irLrdATczvREWeAWysUsWNc8e89ihmpQfTU2Zqf7N+cox9jQ +raVplI/owd8k+BsHMYeB2F326CjYSlKArBPuUBQemMc= +-----END CERTIFICATE----- + +D-TRUST BR Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQfMmPK4TX3+oPyWWa00tNljAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEJSIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTA5NDUwMFoXDTM1MDIxMTA5NDQ1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBCUiBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABMbLxyjR+4T1mu9CFCDhQ2tuda38KwOE1HaTJddZO0Flax7mNCq7 +dPYSzuht56vkPE4/RAiLzRZxy7+SmfSk1zxQVFKQhYN4lGdnoxwJGT11NIXe7WB9xwy0QVK5buXu +QqOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFHOREKv/VbNafAkl1bK6CKBrqx9t +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2JyX3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwQlIlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAlJAtE/rhY/hhY+ithXhUkZy4kzg+GkHaQBZTQgjKL47xPoFWwKrY7RjEsK70Pvom +AjEA8yjixtsrmfu3Ubgko6SUeho/5jbiA1czijDLgsfWFBHVdWNbFJWcHwHP2NVypw87 +-----END CERTIFICATE----- + +D-TRUST EV Root CA 1 2020 +========================= +-----BEGIN CERTIFICATE----- +MIIC2zCCAmCgAwIBAgIQXwJB13qHfEwDo6yWjfv/0DAKBggqhkjOPQQDAzBIMQswCQYDVQQGEwJE +RTEVMBMGA1UEChMMRC1UcnVzdCBHbWJIMSIwIAYDVQQDExlELVRSVVNUIEVWIFJvb3QgQ0EgMSAy +MDIwMB4XDTIwMDIxMTEwMDAwMFoXDTM1MDIxMTA5NTk1OVowSDELMAkGA1UEBhMCREUxFTATBgNV +BAoTDEQtVHJ1c3QgR21iSDEiMCAGA1UEAxMZRC1UUlVTVCBFViBSb290IENBIDEgMjAyMDB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABPEL3YZDIBnfl4XoIkqbz52Yv7QFJsnL46bSj8WeeHsxiamJrSc8 +ZRCC/N/DnU7wMyPE0jL1HLDfMxddxfCxivnvubcUyilKwg+pf3VlSSowZ/Rk99Yad9rDwpdhQntJ +raOCAQ0wggEJMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH8QARY3OqQo5FD4pPfsazK2/umL +MA4GA1UdDwEB/wQEAwIBBjCBxgYDVR0fBIG+MIG7MD6gPKA6hjhodHRwOi8vY3JsLmQtdHJ1c3Qu +bmV0L2NybC9kLXRydXN0X2V2X3Jvb3RfY2FfMV8yMDIwLmNybDB5oHegdYZzbGRhcDovL2RpcmVj +dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwRVYlMjBSb290JTIwQ0ElMjAxJTIwMjAyMCxP +PUQtVHJ1c3QlMjBHbWJILEM9REU/Y2VydGlmaWNhdGVyZXZvY2F0aW9ubGlzdDAKBggqhkjOPQQD +AwNpADBmAjEAyjzGKnXCXnViOTYAYFqLwZOZzNnbQTs7h5kXO9XMT8oi96CAy/m0sRtW9XLS/BnR +AjEAkfcwkz8QRitxpNA7RJvAKQIFskF3UfN5Wp6OFKBOQtJbgfM0agPnIjhQW+0ZT0MW +-----END CERTIFICATE----- + +DigiCert TLS ECC P384 Root G5 +============================= +-----BEGIN CERTIFICATE----- +MIICGTCCAZ+gAwIBAgIQCeCTZaz32ci5PhwLBCou8zAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJjAkBgNVBAMTHURpZ2lDZXJ0IFRMUyBFQ0MgUDM4 +NCBSb290IEc1MB4XDTIxMDExNTAwMDAwMFoXDTQ2MDExNDIzNTk1OVowTjELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSYwJAYDVQQDEx1EaWdpQ2VydCBUTFMgRUNDIFAzODQg +Um9vdCBHNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMFEoc8Rl1Ca3iOCNQfN0MsYndLxf3c1Tzvd +lHJS7cI7+Oz6e2tYIOyZrsn8aLN1udsJ7MgT9U7GCh1mMEy7H0cKPGEQQil8pQgO4CLp0zVozptj +n4S1mU1YoI71VOeVyaNCMEAwHQYDVR0OBBYEFMFRRVBZqz7nLFr6ICISB4CIfBFqMA4GA1UdDwEB +/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQCJao1H5+z8blUD2Wds +Jk6Dxv3J+ysTvLd6jLRl0mlpYxNjOyZQLgGheQaRnUi/wr4CMEfDFXuxoJGZSZOoPHzoRgaLLPIx +AJSdYsiJvRmEFOml+wG4DXZDjC5Ty3zfDBeWUA== +-----END CERTIFICATE----- + +DigiCert TLS RSA4096 Root G5 +============================ +-----BEGIN CERTIFICATE----- +MIIFZjCCA06gAwIBAgIQCPm0eKj6ftpqMzeJ3nzPijANBgkqhkiG9w0BAQwFADBNMQswCQYDVQQG +EwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0 +MDk2IFJvb3QgRzUwHhcNMjEwMTE1MDAwMDAwWhcNNDYwMTE0MjM1OTU5WjBNMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xJTAjBgNVBAMTHERpZ2lDZXJ0IFRMUyBSU0E0MDk2 +IFJvb3QgRzUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCz0PTJeRGd/fxmgefM1eS8 +7IE+ajWOLrfn3q/5B03PMJ3qCQuZvWxX2hhKuHisOjmopkisLnLlvevxGs3npAOpPxG02C+JFvuU +AT27L/gTBaF4HI4o4EXgg/RZG5Wzrn4DReW+wkL+7vI8toUTmDKdFqgpwgscONyfMXdcvyej/Ces +tyu9dJsXLfKB2l2w4SMXPohKEiPQ6s+d3gMXsUJKoBZMpG2T6T867jp8nVid9E6P/DsjyG244gXa +zOvswzH016cpVIDPRFtMbzCe88zdH5RDnU1/cHAN1DrRN/BsnZvAFJNY781BOHW8EwOVfH/jXOnV +DdXifBBiqmvwPXbzP6PosMH976pXTayGpxi0KcEsDr9kvimM2AItzVwv8n/vFfQMFawKsPHTDU9q +TXeXAaDxZre3zu/O7Oyldcqs4+Fj97ihBMi8ez9dLRYiVu1ISf6nL3kwJZu6ay0/nTvEF+cdLvvy +z6b84xQslpghjLSR6Rlgg/IwKwZzUNWYOwbpx4oMYIwo+FKbbuH2TbsGJJvXKyY//SovcfXWJL5/ +MZ4PbeiPT02jP/816t9JXkGPhvnxd3lLG7SjXi/7RgLQZhNeXoVPzthwiHvOAbWWl9fNff2C+MIk +wcoBOU+NosEUQB+cZtUMCUbW8tDRSHZWOkPLtgoRObqME2wGtZ7P6wIDAQABo0IwQDAdBgNVHQ4E +FgQUUTMc7TZArxfTJc1paPKvTiM+s0EwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAGCmr1tfV9qJ20tQqcQjNSH/0GEwhJG3PxDPJY7Jv0Y02cEhJhxw +GXIeo8mH/qlDZJY6yFMECrZBu8RHANmfGBg7sg7zNOok992vIGCukihfNudd5N7HPNtQOa27PShN +lnx2xlv0wdsUpasZYgcYQF+Xkdycx6u1UQ3maVNVzDl92sURVXLFO4uJ+DQtpBflF+aZfTCIITfN +MBc9uPK8qHWgQ9w+iUuQrm0D4ByjoJYJu32jtyoQREtGBzRj7TG5BO6jm5qu5jF49OokYTurWGT/ +u4cnYiWB39yhL/btp/96j1EuMPikAdKFOV8BmZZvWltwGUb+hmA+rYAQCd05JS9Yf7vSdPD3Rh9G +OUrYU9DzLjtxpdRv/PNn5AeP3SYZ4Y1b+qOTEZvpyDrDVWiakuFSdjjo4bq9+0/V77PnSIMx8IIh +47a+p6tv75/fTM8BuGJqIz3nCU2AG3swpMPdB380vqQmsvZB6Akd4yCYqjdP//fx4ilwMUc/dNAU +FvohigLVigmUdy7yWSiLfFCSCmZ4OIN1xLVaqBHG5cGdZlXPU8Sv13WFqUITVuwhd4GTWgzqltlJ +yqEI8pc7bZsEGCREjnwB8twl2F6GmrE52/WRMmrRpnCKovfepEWFJqgejF0pW8hL2JpqA15w8oVP +bEtoL8pU9ozaMv7Da4M/OMZ+ +-----END CERTIFICATE----- + +Certainly Root R1 +================= +-----BEGIN CERTIFICATE----- +MIIFRzCCAy+gAwIBAgIRAI4P+UuQcWhlM1T01EQ5t+AwDQYJKoZIhvcNAQELBQAwPTELMAkGA1UE +BhMCVVMxEjAQBgNVBAoTCUNlcnRhaW5seTEaMBgGA1UEAxMRQ2VydGFpbmx5IFJvb3QgUjEwHhcN +MjEwNDAxMDAwMDAwWhcNNDYwNDAxMDAwMDAwWjA9MQswCQYDVQQGEwJVUzESMBAGA1UEChMJQ2Vy +dGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBSMTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBANA21B/q3avk0bbm+yLA3RMNansiExyXPGhjZjKcA7WNpIGD2ngwEc/csiu+kr+O +5MQTvqRoTNoCaBZ0vrLdBORrKt03H2As2/X3oXyVtwxwhi7xOu9S98zTm/mLvg7fMbedaFySpvXl +8wo0tf97ouSHocavFwDvA5HtqRxOcT3Si2yJ9HiG5mpJoM610rCrm/b01C7jcvk2xusVtyWMOvwl +DbMicyF0yEqWYZL1LwsYpfSt4u5BvQF5+paMjRcCMLT5r3gajLQ2EBAHBXDQ9DGQilHFhiZ5shGI +XsXwClTNSaa/ApzSRKft43jvRl5tcdF5cBxGX1HpyTfcX35pe0HfNEXgO4T0oYoKNp43zGJS4YkN +KPl6I7ENPT2a/Z2B7yyQwHtETrtJ4A5KVpK8y7XdeReJkd5hiXSSqOMyhb5OhaRLWcsrxXiOcVTQ +AjeZjOVJ6uBUcqQRBi8LjMFbvrWhsFNunLhgkR9Za/kt9JQKl7XsxXYDVBtlUrpMklZRNaBA2Cnb +rlJ2Oy0wQJuK0EJWtLeIAaSHO1OWzaMWj/Nmqhexx2DgwUMFDO6bW2BvBlyHWyf5QBGenDPBt+U1 +VwV/J84XIIwc/PH72jEpSe31C4SnT8H2TsIonPru4K8H+zMReiFPCyEQtkA6qyI6BJyLm4SGcprS +p6XEtHWRqSsjAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud +DgQWBBTgqj8ljZ9EXME66C6ud0yEPmcM9DANBgkqhkiG9w0BAQsFAAOCAgEAuVevuBLaV4OPaAsz +HQNTVfSVcOQrPbA56/qJYv331hgELyE03fFo8NWWWt7CgKPBjcZq91l3rhVkz1t5BXdm6ozTaw3d +8VkswTOlMIAVRQdFGjEitpIAq5lNOo93r6kiyi9jyhXWx8bwPWz8HA2YEGGeEaIi1wrykXprOQ4v +MMM2SZ/g6Q8CRFA3lFV96p/2O7qUpUzpvD5RtOjKkjZUbVwlKNrdrRT90+7iIgXr0PK3aBLXWopB +GsaSpVo7Y0VPv+E6dyIvXL9G+VoDhRNCX8reU9ditaY1BMJH/5n9hN9czulegChB8n3nHpDYT3Y+ +gjwN/KUD+nsa2UUeYNrEjvn8K8l7lcUq/6qJ34IxD3L/DCfXCh5WAFAeDJDBlrXYFIW7pw0WwfgH +JBu6haEaBQmAupVjyTrsJZ9/nbqkRxWbRHDxakvWOF5D8xh+UG7pWijmZeZ3Gzr9Hb4DJqPb1OG7 +fpYnKx3upPvaJVQTA945xsMfTZDsjxtK0hzthZU4UHlG1sGQUDGpXJpuHfUzVounmdLyyCwzk5Iw +x06MZTMQZBf9JBeW0Y3COmor6xOLRPIh80oat3df1+2IpHLlOR+Vnb5nwXARPbv0+Em34yaXOp/S +X3z7wJl8OSngex2/DaeP0ik0biQVy96QXr8axGbqwua6OV+KmalBWQewLK8= +-----END CERTIFICATE----- + +Certainly Root E1 +================= +-----BEGIN CERTIFICATE----- +MIIB9zCCAX2gAwIBAgIQBiUzsUcDMydc+Y2aub/M+DAKBggqhkjOPQQDAzA9MQswCQYDVQQGEwJV +UzESMBAGA1UEChMJQ2VydGFpbmx5MRowGAYDVQQDExFDZXJ0YWlubHkgUm9vdCBFMTAeFw0yMTA0 +MDEwMDAwMDBaFw00NjA0MDEwMDAwMDBaMD0xCzAJBgNVBAYTAlVTMRIwEAYDVQQKEwlDZXJ0YWlu +bHkxGjAYBgNVBAMTEUNlcnRhaW5seSBSb290IEUxMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE3m/4 +fxzf7flHh4axpMCK+IKXgOqPyEpeKn2IaKcBYhSRJHpcnqMXfYqGITQYUBsQ3tA3SybHGWCA6TS9 +YBk2QNYphwk8kXr2vBMj3VlOBF7PyAIcGFPBMdjaIOlEjeR2o0IwQDAOBgNVHQ8BAf8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU8ygYy2R17ikq6+2uI1g4hevIIgcwCgYIKoZIzj0E +AwMDaAAwZQIxALGOWiDDshliTd6wT99u0nCK8Z9+aozmut6Dacpps6kFtZaSF4fC0urQe87YQVt8 +rgIwRt7qy12a7DLCZRawTDBcMPPaTnOGBtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR +-----END CERTIFICATE----- + +E-Tugra Global Root CA RSA v3 +============================= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +E-Tugra Global Root CA ECC v3 +============================= +-----BEGIN CERTIFICATE----- +MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMwgYAxCzAJBgNV +BAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVncmEgRUJHIEEuUy4xHTAbBgNV +BAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYDVQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENB +IEVDQyB2MzAeFw0yMDAzMTgwOTQ2NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEP +MA0GA1UEBxMGQW5rYXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1 +Z3JhIFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBFQ0MgdjMw +djAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQKczLWYHMjLiSF4mDKpL2 +w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YKfWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31 +Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQ +zPUwHQYDVR0OBBYEFP+CMXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjO +PQQDAwNpADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/67W4W +Aie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFxvmjkI6TZraE3 +-----END CERTIFICATE----- + +Security Communication RootCA3 +============================== +-----BEGIN CERTIFICATE----- +MIIFfzCCA2egAwIBAgIJAOF8N0D9G/5nMA0GCSqGSIb3DQEBDAUAMF0xCzAJBgNVBAYTAkpQMSUw +IwYDVQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMScwJQYDVQQDEx5TZWN1cml0eSBD +b21tdW5pY2F0aW9uIFJvb3RDQTMwHhcNMTYwNjE2MDYxNzE2WhcNMzgwMTE4MDYxNzE2WjBdMQsw +CQYDVQQGEwJKUDElMCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UE +AxMeU2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A +MIICCgKCAgEA48lySfcw3gl8qUCBWNO0Ot26YQ+TUG5pPDXC7ltzkBtnTCHsXzW7OT4rCmDvu20r +hvtxosis5FaU+cmvsXLUIKx00rgVrVH+hXShuRD+BYD5UpOzQD11EKzAlrenfna84xtSGc4RHwsE +NPXY9Wk8d/Nk9A2qhd7gCVAEF5aEt8iKvE1y/By7z/MGTfmfZPd+pmaGNXHIEYBMwXFAWB6+oHP2 +/D5Q4eAvJj1+XCO1eXDe+uDRpdYMQXF79+qMHIjH7Iv10S9VlkZ8WjtYO/u62C21Jdp6Ts9EriGm +npjKIG58u4iFW/vAEGK78vknR+/RiTlDxN/e4UG/VHMgly1s2vPUB6PmudhvrvyMGS7TZ2crldtY +XLVqAvO4g160a75BflcJdURQVc1aEWEhCmHCqYj9E7wtiS/NYeCVvsq1e+F7NGcLH7YMx3weGVPK +p7FKFSBWFHA9K4IsD50VHUeAR/94mQ4xr28+j+2GaR57GIgUssL8gjMunEst+3A7caoreyYn8xrC +3PsXuKHqy6C0rtOUfnrQq8PsOC0RLoi/1D+tEjtCrI8Cbn3M0V9hvqG8OmpI6iZVIhZdXw3/JzOf +GAN0iltSIEdrRU0id4xVJ/CvHozJgyJUt5rQT9nO/NkuHJYosQLTA70lUhw0Zk8jq/R3gpYd0Vcw +CBEF/VfR2ccCAwEAAaNCMEAwHQYDVR0OBBYEFGQUfPxYchamCik0FW8qy7z8r6irMA4GA1UdDwEB +/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDAUAA4ICAQDcAiMI4u8hOscNtybS +YpOnpSNyByCCYN8Y11StaSWSntkUz5m5UoHPrmyKO1o5yGwBQ8IibQLwYs1OY0PAFNr0Y/Dq9HHu +Tofjcan0yVflLl8cebsjqodEV+m9NU1Bu0soo5iyG9kLFwfl9+qd9XbXv8S2gVj/yP9kaWJ5rW4O +H3/uHWnlt3Jxs/6lATWUVCvAUm2PVcTJ0rjLyjQIUYWg9by0F1jqClx6vWPGOi//lkkZhOpn2ASx +YfQAW0q3nHE3GYV5v4GwxxMOdnE+OoAGrgYWp421wsTL/0ClXI2lyTrtcoHKXJg80jQDdwj98ClZ +XSEIx2C/pHF7uNkegr4Jr2VvKKu/S7XuPghHJ6APbw+LP6yVGPO5DtxnVW5inkYO0QR4ynKudtml ++LLfiAlhi+8kTtFZP1rUPcmTPCtk9YENFpb3ksP+MW/oKjJ0DvRMmEoYDjBU1cXrvMUVnuiZIesn +KwkK2/HmcBhWuwzkvvnoEKQTkrgc4NtnHVMDpCKn3F2SEDzq//wbEBrD2NCcnWXL0CsnMQMeNuE9 +dnUM/0Umud1RvCPHX9jYhxBAEg09ODfnRDwYwFMJZI//1ZqmfHAuc1Uh6N//g7kdPjIe1qZ9LPFm +6Vwdp6POXiUyK+OVrCoHzrQoeIY8LaadTdJ0MN1kURXbg4NR16/9M51NZg== +-----END CERTIFICATE----- + +Security Communication ECC RootCA1 +================================== +-----BEGIN CERTIFICATE----- +MIICODCCAb6gAwIBAgIJANZdm7N4gS7rMAoGCCqGSM49BAMDMGExCzAJBgNVBAYTAkpQMSUwIwYD +VQQKExxTRUNPTSBUcnVzdCBTeXN0ZW1zIENPLixMVEQuMSswKQYDVQQDEyJTZWN1cml0eSBDb21t +dW5pY2F0aW9uIEVDQyBSb290Q0ExMB4XDTE2MDYxNjA1MTUyOFoXDTM4MDExODA1MTUyOFowYTEL +MAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKzApBgNV +BAMTIlNlY3VyaXR5IENvbW11bmljYXRpb24gRUNDIFJvb3RDQTEwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAASkpW9gAwPDvTH00xecK4R1rOX9PVdu12O/5gSJko6BnOPpR27KkBLIE+CnnfdldB9sELLo +5OnvbYUymUSxXv3MdhDYW72ixvnWQuRXdtyQwjWpS4g8EkdtXP9JTxpKULGjQjBAMB0GA1UdDgQW +BBSGHOf+LaVKiwj+KBH6vqNm+GBZLzAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAK +BggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3L +snNdo4gIxwwCMQDAqy0Obe0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70e +N9k= +-----END CERTIFICATE----- diff --git a/TwitchDownloaderWPF/Curl-Impersonate/libcurl.a b/TwitchDownloaderWPF/Curl-Impersonate/libcurl.a new file mode 100644 index 0000000000000000000000000000000000000000..dfcf4bd75e34703948c343a88e2ab089e37d80fd GIT binary patch literal 998618 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

f)o$1Xim`XwH5@9jat z$VkZ#5bkwz!^Nsu;^Sp}jFAe$M<#Z|*g$l1`HO10!qq2SH4d%1HZ?{h#^628*~CF_ zcfEjogPHe@ENm6o>?Kn5cJ?o@8NULm<1OG7=wmB|Wt8w`xYrOaI|w=jUxS~bo}}cq zC8t+qv2SzA8rOLa-ra+B3!=ft=>SW+Bup3e zNWnc#*wZ)SZc374mK2i2@kqi)aCbgGsOM(vWmxd|m6g7mWVce!N)q-!9*BzjDb$azRQe#GFuMimfkp2z9hWe{hQX$+jiV8`bhw?$x zNSO5jGx;{sMb)uRCdHutoQG15iH^sH2{Um&^T81(wNGB>^G6&~83! z1T4i+_cN3%O0_bd>;S;m1+vD>pdQ8g ztmA-haX1yhTroy{Ej&!7k@XqG=D^g$B@}$TQvsvNKk+=6`Pk`=^~b>?cfAF(QL!7z z|Hm^VXa}?X{c`gH_Lp-QnJy|3ri+x6s+o{4yi49VG`f}X!q~OK{Ta;1O#BLnf>3o} z1wiIX^sv~AQd!a%>fWbZ9u}8yNlOT~07{te;uqS32 zlg~6_tUkG3ufRSs0SVt|w?5A-Oo`VEnJ?=raFSc#7VbE_#D( zqep4Zr4lrVIxFJw$8dk5z)R;nnKO#v+gOiTK?|r<+Yj!+Cu_G>_!@J8yQ=IJwNgus zeh&XKoT}{A;-eY;buxMK1R#z9IvAhrLT%tm7x7eOh5ikaZGzb%KOu|r*rLREDH&I%+d3+(#)4)~KRv6#=bPazuE%((*<0U9tPRL0L)8763s zNZlKXa6gnd%7 z9JD!pjBg~mM&vAwD3}=$FUdwUlUymxMm}C5%aSk$>&(J z$U10l;Bc`E=pt%r6LpAe4=%y6eE;v+@f7B!G*+*^feQ8XXXJm4TW04M+3;aIwH^a| zP&jfT!d#&;l7#g}H`PA(cFU*-Dn>Pfqz|dY3#-@L2QdRuX}J1x?9oEVOHhp#EYEgL zu)F6W95nOKXR9)DX4cB#E?<7RY;&YkgDwo_r_`-d`i_=JS2j5_u^mBUk8!+&(b`?> zk)*lmTlk0{s8)6ap+~Fn`6Pcb!9uW(%V#L@J-HaH&N2eiEAI=g+Qbw^2?jr)C9oOP zW%I{*6G{t1Vx*hfS}Bdr%i%255}Z;v_QVf_B4>sk4I#pl{BauK>ZKpa2QlU&CATuu zU?HKi%0F@|NV=PH*~^+7?a!Li4%xD3rv4Eem0W@)g|v(4Mh-E9Zv9!%#4E9l4p)V! zmLLD{6W5;^|Imz{4bz)q??{>-{@r+)j-sE6r~C%^b+-`f!tEvjnbQm z&Bzh+H$l$dB%a1cW+jv112deTD0)grnhStdX5ufPbNs_2B0KE6IaP*X$)wnmR3Z&~ zWfvSWf-F-oS8?Wzyz&QparH$v-v^{49F1Pdexwe1PY1ppy>k#ZldmF(bF;9NYQLPb z_R?!LNJm*JTEd*V4)4ywM)v_HWsLN`G;ym zU{r!bfM8n6^P*OYrz{*|hcrm2grL$6(E>0mn>lnWG|-uBy`PdgagD=HLf&F{rQ{iu zjvu>)rR|%a7HVF44ls^Wc4ltz^#o>O3j%urI&yaE7Ru!;E?N!qWXM`+%`O%k+c-%$ zd2)SllNyKW+42`NUcDOUPHH4Vlo6BtFNUa7&sD;QC;fHHe<8|pcf;U{>Z zvZPWUf69v0MamJ1Z-oWJCMF2hN;5{@I7m&IuN3QD4(y~h^l3h;zaX5i zqC^f2#s8jn(!-07~)<|UibypbUXEpPW!FOe9&3dR#q15GQVch0xCVq@; z$#FZFJ=o8Zo}B$HP<9sK-P1dO8kJQ7Jr$=9TdSV2t=ha~n`?|f!;~pZYMHcWg*d-y zj~ucu7xiQk{LnLB!}@Z~28se`F(_$BFW~o95SRF{Qd9_((J4)#8$%)5=;Fy33L-CYe2bCS7!xFFi>?U(Xn08aeZe@wd7twXBApRI=UM zD`oU*Ke-RoOz!2FJg8>S$Q{2_cHO;oe?~J)y-q~xEc22*f;Vbd%y@R;3?^`pOyKw{ zJFyjcTQl~U>Bk79ix&EjF8>UynpUt0?mpPX;r zb`v7>7T{;_KV15vd@#x4>{A(tU{1s#bZ}a;8;XoM5sre9H5rTqE25*xJh^4Xr`V9{ zyn8X5Ysfjl?mShxXrGTXVoB*tMmkylfDiYKy1~vlL_$@f|}z8J4u? zLsQhk77oQ`;v6JzrS24K`jjJG<-mFU%*6>JVXYt7Nlpw|_SMDRLtMtdA*5jL_|T1J zVjBP?b&{FOCfVclu zvgT<((3@0-7fXoQFlSD$q-IB*ZpED_NcT`!G8;3VN=SM;>PaS#PLnMzve5+neMNyv zni$9lk;&_jx@A{s6GrlfGZ#+2{y++<#Lw{{P$n*xHwd^l$?XhSs;Ne**^-Iiat5YD zaH%Zvk)E9>S%)a>uy`6KnI3UjO1L6&4{`?nhVu%1r61`Y+Kz8C`2Z5Pu5B5gm$`pe4TjQ?e}0HlM*){JO2gmVf7=p*>Ra+AciwRTq5&%a0ZSp#Keu6SgqOWvFC-YT9Jy! zL)RZ`$B9R}c1R(_$jdNQ%B&&(SU8kHjZqyn562-X6k&~bzYlNcNTl68^a=}^7)SDW z3d6_J;Xy- z(ES2dWkOL_Kh258CmMlD-libKu54o}*f52_nA+ozLvasES;{<Hr2s+42ED!}%qg zx`*CpDOOu-&FLc^h6mzvP@|Ic;dOsb3J7mF9BFkA{RyC%_zFZ)_t38iC%*u$sI-4Z zGTvvgp8H;kAgy27@yB(MWv7U77{*KwY{^?U-1ZNIKPII+~J_~ zZ)X#gZJ|b%L*RlXm7KWZv<^;6wD8jwX@o=5QUaVC?*cK++fHUdm87xO0x{j3he;i0 zE|bT8pmj(|b*MosqN7(!EJF>&o={U`t4cvH4rf*eA!Nd^^G9$Cn>84%dPd)k<2hox zEe~SCi*gL3q>JY8rA2>O_Y82p&gWd2`YF2^%k@pg`|#=YIIplIP_f#X%riKz4Ou1c zM|>#c?O32m_CT3HlKxJHL@a+X)kB@d*WolHq{sx;?TWL|S2=SSnSw9fLrrOKjC~B6 z$sRNlwTkjX)U;ay)t#KA<0!d+fQECpI3;CQ9TxlNQuVC`QgQNm+RCT?B`d}igz7l3 zDIz%D&F)lI;07orE_sh|GuC{?DZ3I_6#x$MZ!AJUi;#Tmoh>mCB_A%0L zeNKWR{qAHeJKc{ek^=k<$?uI*XyZWP0lc!5Kl38k0=f zD6SyBDj!RkObr!=Qx9wh;!YD9di*iAhq0KV0OzCL*P=LBJHP2O5~@+vRRVKSGa>|4_N#vu3=~aia4Vh#q$wl16=D*K^`{;gk%_ zjAx#*6eqghySd}{Gf%-FgxRPXL49Eb9tI1lj0&?OC^q8T@;9O_qvY61^?`U;a>!%! zu)!%({}{UBklEkC2oRwMl~tfMfNaLHCCm+qVlozg`|stS|>xB|{h1f(Mr z-QY=f^CIV7C;f8eobv(PWX|tZ7hfqvVja)*1gjNDDJ6C1a+TvWUvK1-li6`jCDuK} zQ1Uw{Sj<+ocVY`jiQs%fl97Rz+X50LAm_n4kl*4Q&}`YI19=usqhOuocm zyZG+sz4*#u(8#ja1&gNFP*asZ!l8#%Hel&7ofMvpOLqB}D`l z!)YUx23eX!-MI(^4k+*+# zo)fs%)hMjqWs#=NBZLj^C|Qq?nl}?A54j1dI^7HuoE{{tMDevCfs6L0SqSPxn60|e z0&U?qGf}{Dq>H|zg#J@Q=XD9| z@CMd?Ez9{K7+v@3V2geUiT#QG#&>lNJ^=)AE~3-0rgWbc`NNf?eg6e-kI6||c>A5V zCFxHp(r%(zrlR?;;E_wWTr@W@VlLV4g_AN5Fq5A}YsjiEkr^LOx~ zY7<6x$z3Jih4O%oXYiO+dFF--WbbJ>eSvr_0KvkkEi+Gv{vL`^Fb|z*@@(|<)O`l~ z#fSt(C1$b<>X&AN#39gTST-)1J5y0W%nk-9mry2=PpB|Mhu53UL=K9zLd;FR)+J3Ka)YeC#prd zh%l6#iKj5Ha_@qv{@$`p%yrnAG($zkw?hl^<1&YP}8Ro4^QF+dt z=!&ot72Hk**f0~1KwM;NiBk%q9uv?#QM%~)0*{krKLXO`4gsf;jowbHnTZ`HdS85V zP%4;^2kt>0cA_MKm(_4lw6oq%6klg`IfYBM!a6p3W}}FgMWZDgD~PMEa;5U z@=G|!;ER6CpD(ftgSuW35+zEuqwW_!Tvy6zij#7 zi8*>aBASZ3_Yq4szlm?+5kk<*XjiH&{^PsH&m3)W$p*syHeSuCX$laO3n@S4UC(aS9RQuQ2h0RP<(S}X5Mjc$NyLme>xPb zcyK-9nhCkP#IxX2mWZl|Y&K^@PKWL5u&*2!Vj(>B!r&^2TAjY5gmW?weMjjk6;o_4;3?qDp*nDJ{dV?sAptHvEScO*ejS5=y+&mEQ+iQ zeBIbw&#AOmzXifD>*PJi7VGi9p*suYVeJ+}YBl8HtI;J5&P3Eo`+jD|o2J%gkS16! z3TM3zm9-U1Sdx!eYGVIV6+3iv7g>UC2c}rc-oqriCS+DDN2)}A?@F=hz$87sDzQ;h zs{0%Gh>7iI$V@acs;Vhvw24MGyuMb-Qc7EKCP}iRb1=58U_FOeZcFXw_lhn>hSY?= zcdDCHC96I$#56KviT#M}K>Gy`y&XuE%-apLUn3a%{=s$wk)p427=qKe-0eVe$`tiZ zhifcZdj)MDY9CPrz)2Se>h zP1v4*9fzJdsx+!p&qD~JMKRLX;{>U8X8T2C<8R!Unm>j8tcxI*`p`asr9ON^ z(5tegIfM3nob-Yb{x$?d72eU88dqiCSHhmGDz#ez!%pIM8Vp%j>X?7{a?za1AE?*4~tb9))QKZwn<@V^24_JHbi{$M5>k-FYGegnYRZEAvL zrAv|Wz0PSMZVz<1cJ|Ma63qg;6mhXpl-aGJr;p}X{(!S6#Wo=wIKB!n&MQ2wFW#4* z5)2&^sKI^#_6Mi|v8JoGrH*RbDU-a|&&?2E zp_dUvvEOXCRNIG_Xawq91Wsc}J6=IGAzjp{D%DC=6}b9QO8MD1>W^tw0k3Zo6qMqR zvD)&@#3>LF8KDr{i*pn{b$tt7b}iDwo}M+5k6nvI)<}98YL-YBtjo7b0w}5EDH`4t z1?DkUg@Gj;G<+2ZRME?L6_QyD-z*9159?V{!1NI}qd;NBKw&#jW9OF$-aN>&?>+O# zJyHoaGIWniuxko%4noMB7{w`2`KVZ&a#oZ;Dyj-FA{M@?8pc;^$X6JlRbrJ5(9jwN z6AlZdo|dQ~99f0CB|$krP_!JNTZK_gfhYwxpp>D#7|aAChgU=MFU5GGpA7_+Xg;nh zG4UJ3$!#e!K@aC1{J8QtF7%dmZWl<#(&~>!sAd6l6M{S95 zUHysGAYU#4xS`GYwqRcA`fZwrRO4Ef@WLqGxB9ELy-S)G4e1%$|&Svp@b2C;~((@*e`4&vU4+X z(DkZOR%7dGls1PCq%uxte%bs%B(L#^`(sF?BG>z)VsH zRC(P2Kepyu@pk@(0i>#L9X#@?%8=|i_zQmpNBh8-S0a*c^n`vP$3C?Ct+j|3w(HSV z{Dfk;I{mne2Waxv1uwLsXG5u9R^hfN3?5>1!6P=}agaTJ;0SZY@rakc;GOus^OhcM zZJf=e9>79Ty#G-DJDuhc0E6|7v4x03zpA;-ZF8lxR((bj_k`UT?QuX zvT)`?5wLWkqR+>&FDYQonF~=^D4wu;=-x_F=9uD%9@Cq57Q&nN_IK2j_qoMq0Wq^o zsxaBnD1nRY+@84ETbeeL?*ZAt%TbT8IEg-}sTR4)4U0QFQ9zumn2nM+9xlUV?x=k^ zX+gnBTJZSCBu{j)>`zc$u{DR&YRW~K%6Ca^;G|FT<|PtRx@ostwX4vXa(|asQ~e=S z3X94ZO-K=F>d=u-GE@uv!Z4JKAu}Ffp@eYtI3wWF=?#oQZGRTGZ0kLM$;B z6AD^sb#^X4tifX-#1bG334MKmL_7dIYwXi&a7N`Itob<|bsAW2F#|;>RAYO8=y70& zc|^`)a*o*73u!)V1U+a(uIA}rCk#BuDnYOXw;5RG#M!}t9lts*P{SpS$4JQeNhV5Cnxj;QY0E~5FBA+&qSp)2>u z@oX1-q;O7Ba;)TZ$rYF`0cqACLl9!X*O*-rJPCW*oL1v>X7wMO8?I<433Ch-V>UH7 z)1eeuT4_v!v#|W2UAqJm>v9+o$r2NeV}}8QIq}lq!2Lf55^>BegWXhoFboedInhjT zI4X^vx2sm!-_khjyi z){g1RJ8A;%gnYpmep_T-ex8wkEz&z;oN+|nF-A59+?e0BIzKlY@1(qCcq#~6kb9>j zMM>TvV~j)2$Scb!1Mi{i&^QWCQ%B>+-EKN?f^wxF#wRD4kS&*7U~7fu;4Gfoq$VwY4_-Qq-Q3-i6Gkelf4$ zSr%w$ThhL`Dblof84_RGy0{HD_2_)7TX6?cv?0>z<{oJabToBFmox>MJKB~6+El)h zt#Mh^oVfuPoO@YdQl}BBt*zpF&fH7oo5=EeR$Fv&W1zJS#lS^l0c64pSTC&Sr9%P9 zqrNd9*AEH0#=-E7wrgy0ZB%Dl!y?{kR604(ED4>%oYbQnRLY%gi?44AL|Qnf|qxUN$!y@!Ey0jb3_F0!y0$9rdk&wrB(;50Lyi0}03P^Cq=KCkNVE zQMT5pi`yFN7kjz*kQx@;=fgsvBIy$CXc9ywbq1DCYFs|4b2-vxj4xbXJs0HC1sqN<`sUDU zQiJ@9PHK=C)r%K5U5C1s7TFqIa&1#bU|}n&WzH37FYSw$8CNzf>}W&_<85d4kqGGJ z^HlADt$JZAiVGwoLZdUzID0BMw7sphv&ongos#<>InPc;Adt?g4&%y}E?AABw;i9a=oF1rL*jaz=Vpay@ z8nq$(T!3~sTK)% ziR~BEZUnytt`j7tpHUu|8gLVu)zZ|kh*d^L8QHd#sh}G=(ALlp?O@rKwy?ukS}#m7 zO1!x(O&us)XP_0$AOh-Ti-2a(P~U(CuhL+iY~V_oD0!2c`e>M4CLI+Dt3=aq7SEAA ztbKR@1 zR2|%_@}(_Jt${PnD3cBuw|1kRnxtoqw(9O1w8iy!kWgs$tjt*uX_wZ{T>vhCrNWFS`_JgX?F_a%BV%@qPlcYan*&J0nwT+8P%&E9!Pmkx;0jz@+Joqr`xnt)B-( z(nv?4I|yU8pe_0!H9pamAe1{JBJO#KC<&s@K!Rsv0x6)Nph--ENevK_3810|lL*rxHm%m$)>dq7 zFKw-*tx`m*K@hOg7Oh&}MX$9PLn|tO#YfHm`}R6#&6!Nl+xu&K5A4i$)?WMlIQy~o z+U)E3;bDI)A)3zDEmaQxq^W6*tnz$PFhXf+thlP$Q({#zK68g3Y27vk3esz%B14dw zLuz+48$8b$mR?vL<5x{mVrmn|+D@z)!y*n!OuxY)w27eGf`YY6&{Nk|aGZ=U489+3 zGj}SG^NnQxEyGgM(b~HUF~cvgtaq{O+cnX$_Q4c@cGqOgd+?jY@84nf0L-6YKAnJw zfX5G$1#{Qgm`8xV7k+r@!(g`nW)Vy|%&1A2U%*s>Hv~65;NJ`Sn=mhcKEJlEsglOTReUCtfKIoOOX>**19=}?_A7_P!|rue0nj`hxdCy-vGmBPBm^C z#o&pN!(ba1hjJK&Mk+B0Pn#`_y~k&?U{lcXFUl}xhLFyX0X=x#vSnAZ1H|yhLX(Nr zV!Wm`gw2R^psKOx;g*@qVKqRXff1Bd>`cZmUR~CJDv7BR$M(j~#M|lkt7>IZgO-dh zMR4}avF0O;#5<3SUy*T5ODpPXuUZOZT9ujd$pp=vU6__6b$JZ(rLr2ey9$G6j3M3F z)2UN=ok~AznY0PkUUYcIjdZ1$Vlh*DwYf$oUa0|`5ICQ(I7x8q@h!42isv{4C6@VY zI9zD^F+b< zG_N#`y%g&VeEzTE$82HTXcqU8mJ6p(pAyWSQ@uPtZ)|W{Q*B+0O{)YS(+QlN@(VpC zm_K3s1YF+yfAL@g-Z~$~Z=I$HOB@dEDWF-#b~MVDIq$cw0b(WaTdhEBwSJ3B>8w6} z>z6>{BGeBmmkrGZVtw;ldJSato>h~S`Bpi2$y8$jaAU5YjVNvu9rT0g9M35^<^#Kl5I zl|T|24{k|1eyX;=0+RSWr8FM)6IvB^cP}$>`3lel2K@?Xp+PSJEi&jspvw*NV{=w) zPX@Ze&~kyw3_4G3FIC%ewS5%mLc{j~P`N=Tpt)5TbOF$n2F(VNTG9wqX=vXBsxs&? zAlsmqfFcHU0bOL!F%Yk=Ht1v^$*ZwIl0y+7iNQ@k<%aJU%J&eE0!Uos0Evq^KoZ86f!JaBt*-!GWzbfjs6iJEbzOWFsK(HEGFp7TA4q(D z5J+<4w?G#ezI{Lvm-m6h#b-d`;*?=-7_~rBT3-Q@65I$>YkYYc=*tET!kYcn2IT{Z z&(yjiKFMsPPb+#ENPON0BtE~dwx0os&xfPu7oQ_Q zOO1bb0!c~#L~VZoB(Z-8NZkH6P>FGIK>2vwUibzBN$t!5T4wmB0ZG46rRa7biNTQJ zZabd{B)${?IdvT9OU9RKpn8L@0lLN@>dcWo;z6JWL)!`@HEi4wmc?(m-|7I8{$L-F z)SMHJbZb*9kc9gUpv#Pl4M5_{^FT2}`v6FMnK{Dsr3NTuZ0`mVUw#H8dG!F0_;T1$ zuI*7k^Nfp$N;?-wTwDtzG2pQaar;Z4Cgb8owfzK0;xZni0txp#pyh^d7SIZVzN57J zl=j>)mUXSMeM8YZiU#9Le4Vk)2D;v$%YY<|3PrU*7fTpGvkZCyNa8%?SlP4iTZKSE zn+qg$@-iUtuNr8+ak~nr)S$kHUmjN{vgl|hVMln>CyKBNnDON!F914NW!Q;(M8t*N&Hp= zg^VwMRNK8k5|{obxh{qR3GH~LnqF<}+@0Iozki_)JQ(a$10*Nn^m3D#BE>l{CqW@C#bLAV8pW|+KozkS7{$9&3BsXb}*2*z4&yOb~%vHnt_^4{%uyIu)TXa1?H=Vj2-Ilu?})K(PdyGuYVnndY89O|4oZNG zi;ID7HmDJ(#h^a|wHnj~)Mn6-@$UFwIFR@}3P@r#U1>9cB;~g$?K{fX|18V8#rQW0 zXpKPyK;mBrNZj58Br*84+CHYX!}DYZ*l+P}J#jl0NZd|T+POdyzqv|VsI*3&W;1CY?p zp6t@5DVhZ&w%<|Oy-IslX)h~!OKqnWxc<#nv=B)A+oH6`fh49A3SAc$0L?csO(^Z_ zioOdZzHC$49w71MOk}O(?z#98z8@&jy#jQ%a4Mew(}KL0!e63Ds7LVzo_j|7q~v30wi%M29j_$0D%=b`GE300wlTd z9MD2zdl2Yag9e0LbOKPjp%ns2>}LQiF|kfzG^Y1lhk%9khrjwRth98ex$Vffh4pSfxcvXIc%C6#z-Ksoujl%6;-J1 zx0LoHAPM(FAW3ERboCENY^NygLZ!`B+Cm_S>2jsrsC-{l+8v7S0g{*wE^rTt#f^FZSBvBho-P6iTMrPAtw#Fra@noW-X zPHmr4+c%Zgt!Tsy*S{|TNjb}J_eHZ(JvwrQGV-eAc?^o zAn|!VkoepR^feQghk;Pt&;nisLRA3z5J+4EE^>W71xV^-2uN&gAjyq+N?QcvgaITm z_@3I{ueMv1_MxKB6b+u~rt)YY@ns^Agj)b4VZ_vS3((h1>|X%7&7fnWkk2ycS3u(S zVIaxB{Xnyf?O7$3^$mj-0$pOz{Xk;74@i6-2ErZ2wh~DEyBbLRy9WsWk$J8cs z)ND}k95<$Ofy8YCki@kATz9qNI7N9t-!g8ifMN!<0fh{@7YJQBQoa@F+Xm&rGx7Nx zAT)5;&I7`KpkLwVI|h9OBz(h=#G4FlG?0|}1wdk31SD=30xd9nHz_&@B>pWy@kt4; z!H>B8Dv-F{0wn1eh0I%QeEAYkgFy>`B-|%~LWVXJK?$w$Qg?p7PSI^ZV*3)1__yRT zm+uci64SR79kJQR0r~P%peY9Z3P|Go&C6Zd_koa5@ckO-7K3`!_OL75 z8nFyWe7QksKLfhUxENaI+8&|k1R(MGETB5WSE#mOAY=%_y$lEy4``*@HmmJVmG zy#ypNU0CjhTL~oo-JrBKAW84nfh3Ik)%I6F;$pYjzM!^msqNqjw-gRqmW8H-m@YiV zMc)TnX=wOk<-zoay^FGd&M~xMO3PL>LTyJXZIq&*+U6)NSJ7CtWtbA~Bt->ki{YPR z8&brUBe6m!@7SW_a!{$-GVjFa1&S7_ZMo8_6xFCL%Uj&mD~hQtb4+YkDQZ^RR;8^~ zv`%e1lybpy~sclec zIf`=CcC6C!6j4rD>Q#Z#sGvlA4ykRC(riUhwJlZJJVguCc9GJ`6;-J%b=EU9zr{-v z1ih)KOA&WR#CE@;1BwnR`cx5x(Zz*dQI?`%in0}rP&87}C`Caja8JVXp*7= zMN<`p6cs756-5=5Dw?Ngfuco<$`!q-s7uj4Mf(*UP;^kyr;2!&ljL9L;nHXOtX)8) z`K&#PUQo1GQJ13qiViBW0U!?EZ$|jm8H47@7}E`_m|g(HV>h%kUhFH=epkQP>;s>_v)lE+{;Kk)lwAJ0BE( zpYfqA>-c>5g9r~KkJZ>%S+R66av3?8^5@I&hb5Sz+z1L!a-=BS_2+qx6vdo=NTdAR zi4Q7fpYZ|NdI~(0-$?nh7Zgg0q$pJC&a)sXiVxXK>5&wLI@WkDBtbdHD2L+Z?1pOy;h1miOV=1?{BSgDTI;LqWi2p&rL zNPH*{R<+DBazLpVUf}q{`rlVr;%aF%rG~`S_*nJI7`XYMXyJ+{X0CPOY{=GlislM5 z`PWw)9DikFqr+m_R-Zg8Qy%$ESi2cy+B3dB#e)Wg_|$;svUHw?6pv{;zWrz+)6#hO zQsLyrAmIK!RDeF7I)?{E=G2Xw912^mWW((ag>6SDKXxdr2|{_)p|F&N^0Y%?nF{4i zhr-ekN)IUfE-)2B8IFu$drwhLVOBYh@Jz~}gfb{IGbj}ql%*Mz>oO>7loE7e_^k}e zk25G+GAK`FP+rWSyp=(DH-plXK{=Au#5`^cPt2f9Ort?EBl2*N6-er%|RiHPn?YUA7|KpRcF!&~AMO<^BxHBN-Il=Om9C!9JW>CJBLE-%q=`p1K)pW}18I+z3 z%JKYkn8!`&8A`F7-uS!>3NPGoANgL)&7hQLP?ls+u1lk|;cdM6?&e%~-E}S;-%!1{ zKGrba)EpzC4!QU0Iv%2MnA12`TwPUhZJ#zvAWdG=r%mM&BMRQP9h!4hQ+?ldI2j5N z^1kgjtN0unresM|U97gOF^1y^OK`f%2;e(sU=4PJ*9|sYWjIqPa{BVxR9A+>Ylt0v zb4ZQVW#)uaUztSJ>5X1YkoTal$W7lxS3bI(++s4U|csH_U&@+JUCtiy9Q zU~}ZB&j6g9&<=o zC^a!0u61mAEZc$e=Y~;+Jl187C^}ST1%_tga%pT?jq6g5F-fTPPJ1%#(!>K4x7M0> z)>0TAP!T7MjdgBqPx)b5r|Z5JO-!t6mo8qm*u%B7%6T)*IaN1}OCFp{S(nu=Eo0$a zSy6elRf!y0S=P7=W5nxRpQ~eK^~ev$4qXgRN_*^(;(B>SGr|d8FD`3>;sAJSf|XP3 z4#wGjo=TNB9_+ZGpB4=8eDDt@^i}2(Ce#(vv%=> z+Ikb?vg(S)YtffE;W2?_OB$D&5Ei4*mY_daQMTM!$&mEpl;oAEc-LRm&^Wg`CZ}}f zvTu;&EUmh-i3%3vHLdPRM`v1r;YFZT)jaC!q@!X*8FCSarJM|yJA3-fx#`uRwy~=A zDip88s1do|SSzkkaXg)x@!#p;cxYO9NMM~nCM{uiMPJI6R5+vH zBA(-LEKX=@K#S{|8f&QBKqx5F%8Ev0E6+Mg5>a(Izkvb@Hy`S1aS*X=MMJF{I$Kp^ zO;e1Ayu=^0LPidafT!0S+7iY~u#>rE%a&ecJ{~6bY8&0Q={hmz)?K2wG$fpMn^io0 zo>1^D#Mwn}{!6vO$w;2@PqT4LCe5yny^Sf=<&HmnR6H3)m{8JfkyKB!GaU?@o&=l5 zDkSM+jYrZ08|V&i=IVy&Nj$zc~^f(;>yDTA5KsnX&9_Y_z7C2<=zz_vB~@!vPwI>t3a6? zLTM(SX9b7U^$2qw)+-NS^^uPa1OGzfJu60}PlY*f1X1bwl}(mf>Kec-F=%{O@h zo#{iqN5HqVH(z0a@(_@3H~3ce=F6YJ4JUob_X_xK?#1Wm?a#FnKc*s2XzI6d&$=D| zJ?=!Wu@jG)D>4!n1$f9&*~SOMvb)Zx@;@S)_!X}ej@P~qV0)hxOXg}Y1mQ8YpyEKrAkO# z9uR`RGZ#>;;e*h=#o&Y=x(n}hG`Pm!b*>a~l^Aya!lS#h!&P*QB)qlA45DLg_s#_n5%55j+qIyhUY3`DX&sh1PvxMF4c%7#-eQKG`;CUHlPB&|W>g-q7RIYZ3!-F*%T`o<+R*3Ovb`Wpndjn;#3lZgj|Z<*-iZF@X(4M35_|gqwSUu~AIN&KX9>lnu4ec6>$5;OcJ#@n%~8CWwOF+knCEHPtb;*u;D-i(p-?r3<2 zOLGEkC17Bpa4js-8V)>)8|4o>8J@fKI?zUi;;Hi9Ib+y-SSQ;MDBA;k7H?Y)W(C&# z9-%s(uyv$7`3u;)(SWR$8?y!k);y0_WHQ=NIoR}Kbl8K+k{^w_&LU{L&u}_nNKCn` zftyDDV0;I2+gk7>D-q3<`?(+)_jMWW+b#vk?vD)aKO?v!)Pt;N`I)>#Q5K*i>RGp( zTn5RXJPl5yeLL}cANmcA|HCr<|A@K|59xm%{O1Nln*TfCB+dWP$Vf>)Y&4H0{r55b zE$`&vZE)b01Q?QwHGUwD3$*TKVYa+egtxN-Yj_g|ighKjx;U_@=b}pgL#D>}DnEF3 zD|QcB4h{*loef`2Xl+C37=8PW&=B;dGlHA>sbam1`fyeEkmipXVng#gn?D*C_(tc} zy(0sgF7h>hv?9>@6k{3R8eaV*f(2<@I8eM5w*8tvS{Z2lA#9sJY7DeKXu#Y+>obSo z?~f1ytxFDJ>o;LtcnI48CajZ95D4o60}$2~hu|M*!b)O+u&sRa^xF@MZ_2(&$n*Z4H3Y92sQjFyYav!d}C zs0?oX^CusoYEt)m;MBLXvF>K-!(FgMeZc+Y@k>UcgboX|zJay^gi^Z+mMogESzShv z^NX>=k2_Ek*VjbjA9vvu{aB#w97H10vU6a!AAfylOaaHL>78U3qLpgz2%q7$jy4hK zhbz3GFj7K$SEAxpbvynN?qEtaD9X-YU@#-MYZvZlW24>+r|}uXk`es6=|g`oD6nP+ zC>p7H;1qr9X1H_n$LUQu&^ATH4@TQJ!H{e~ z(D>e%&ifV+QeDC#TF*5xV@zU!w!7J`5ku!QmAnKT86_WXzQ78!9S?Vih$+0C)7fWO z${bm)=mV5 zbihk1`7A9>qx}h}2-OWGy%`~#(yq0*P>aRhiB{_rP4f0sP~&1hfltWma;DDsxdgV! zFX6Q#6`kdXrSKIf-z@Tt!KyFT;$Vu;aIM@9^CVvbcoMfCIXd4d4$!(}c`OonC6`z}h zEI~EUiiqzvBam!>GqY>l{qh!8o$hD1Fn-;?Gk2tR@7RJ)-0FU83*B~acFW&eU~Ol? zi{#1plj;v8e?I`tv~0BMWWMR(-BG%ufEVMW13+g-$hBs40z;t;~kBnYsR?zN0vqn4nS~`GI z<6v`v)s$mzMh5b^iMq6NIk###_>UFC*dLmHFkT8T2CPILx=q_V5*kI%5Nd9;eP*tN z9EFy4M8JGlUNvFO$ad~ENq!%_i8r#26KP7Gc$&C0PqCVgZSP>*T0Z{A3S8@RN%rcC z%A4VLd>Y41<%fvW8o7HeH6mP2g6Rh81WgIFUI~;u5Al=!dRM>XG*tYSUH&9*Om5kg zmHZerxn);&@^SMUOx|UFL&@d%9oC$@06&MZ!%99)#G6}^3xQCStV&5A0%+OgO9tRw z^KO6gr?6|@ot2!7UqrqckvHFr7jet>VU%%7{>5R{pD=OK+2>3yC>#g%tR<<}Dc01Y$ei;LdJIw6fNK5^6JOfC#>Cdh-K#7F_m zRG1J<5sVEJg(-!Z2eSZX5e&nxf~kS2gQ^I=|KA4R#wRqo*-$!6p0rx{kwHax;6J`z45`j4mhH|HMFzj^sfZaUE9`mqE z;KLH+gNc!OkX7bkSHg!4m`|S?s0a4am`x4PS7vIjrh7{E@(JO0J`C4cSgmh|83DW= zzxToffj8p!QY+NcjGOnlG^$g|>0J zar;xCvkamp7;$k7B*la_7lC|A)~MR|(YYl_q`z-!nmu2-m9`c6^G!!#bAv-0$$Pl%-U+ITV(lP@Z=vEDNFRb12Mtp>W*Fhxsh;e$x#6bB zxJwr~ND0=s`7?wiwsbkf3xe`|k(5FHq;nh=N*S>Cv8>O~PGmDWQ_5gH>{p?$y4Pu0 z>~(|x4k?3P(gPd|jPkT*yjqkB@b=uKvA4_v-)@JOUk>v1B|R|J;h{S|Mrr{fJe4uX zlsFGZ9(5Ufd7XVp8MK1$ZHE_GEin$#;2YT^&ZiU985N9&hqx2*Hx+`8HX-b$H;KJl!ujizOYtVS}t;)3Wjgl@F{R zQ0njOw})Pdb_M?av$N*lI0!XC4fK>#Dk)VZ)%Fzn^!X3J$*c>0>jeCjnbK82+ywO- zol%1DYR=)vXw!Vt&1ln%T4-tEARI$Z=U+BP^0XuwBQgKdA8#v?F;Xg@yqt08MaD>Dy;cT~_p}}vBe8@spW7W$ zYP9nchmsl*{l?==8q3QWl(*6-2k@5m0qNso?0ho%uyOlYPknTK`zO9}UjH-Yf!#3D zJv44aZ1%$HSn<;3wGGRb@@j%haCZTvKg04>@qDIroPvhK&yRNaU)0}E#;rN>Wk~h+ z2haexLc|*At(l~RP(d6D-xnA$X??PYwJx~AbWd!iBvoKO+6AR6|`-j2tr1;yt z_+06uv&pzP@J?s*JrAJG{iFGwb!eWSK_)3Me04MC5cuhkpY`(7Nnxs;t7|yFzynAf zwS0E2-sm6@Hv@9>0dSAnzu?*@;(KY&%cQ#iaBno<`ScvUqvaqmJ^>)pmd}osJj4sv zrswjV$Q_1kZq$5IWn4n#JuD8fq+FJtfmm}fOLkbkA&=k`lIwr*oLwtxE{J%8wF z`Q*eEjo6=OT#cJ_WZZ*y6!~OZ~-~OoQZn&SYVj|pkWV+AB z9!jReree9rm=(#DirTigLl_gdBGW{3^~Yloe$$H(>WV$9Vr+x*JG-Bf?{NFKdwSkM z=;y6~{M%uRkW^3Xi|}T=N+lcqtZTpdFFlW8^ZtkxtKnuII!)~Fi^vtE;TW`+KhU}W z)ua8}pY{A1;S>he@Rn}K1*{i$-^PAb&tALzmJVc{ome_DJ};-njt?@WY45z{PN#I^ zhJiu{7tnp%-vX`Y0DRE47XJ9K@l_LOy8x|nGm>C^&_>@OnT6Dr3wte*mjL@ z2=CnwrrU=ohv_7!fcD?eSN2!E{D05v+}^={!j40FG5NX>$SQ;~zAFS~rx4Z&f%zwd>xIA!6T+8C*!ehWUyqy2!|cQzOrTTGOzfujW(&pM0-H(a zs{rg=#lvGIgq0dXmJnE%gyTaaDs+dfgtvsi+9Mp#QM_k0C5cR3-eF$ZmA4!m5oqO% zBJfqt87ME-`dtHt2HO4%uyYXpupWQixM7cMyl646?5fRc%)C;~gn6wtuXnkxmzdW( z-Pa58y80o0Q@ARO8`2R(VAE=TmRk1uj0ZVjaXPIn%t~{cbJ63*F3b4F4~=>K2;0($ z)zp%2Uf(va{2-avm(A<5?(1&zN+E1x`y2DhYk$q_{dl#JPq4PnL#Q_eZv8G|xN{IO z^59m(z8~XP!+w*n^K)t5ml8Hi|T_f0Y#|DgwDQ4PsI~p81Thl4tawMukR-mmJw8X7J zd3_X`iKkNAfVA~P9dSk7lGyEt5gi+gb2R_Vp_ ztP6|h!46ZR<6)@H;lE-20P`@+f5F@aLxC5{lnjHRZj`@*m--NX4im)tH}RW`U$zpi zJ4}M%8Z6fqLNG-zHcS+z6oy~r1u)b!&>scJv-(LGN)sGFTo1y03iC4FcfkAr#tnM} z+>M0cItatgf%)Hry$J5gVX9ziVCrD%VPY`+7_Wk9hG~Ua3$qU9IKe#9-anz9ez*3?+BQ|FrT5!n?d7!Io>?{Bi?tx zlp{aZ!~R~FFUrFkz$?%G$N1aaIzH?W{^>O&*WIChQKZhg&^{op_xP=P)J^ngK-?V@ z6hOQ=J;Ur5NN86o`nDnpuyI|~Z}A=_S$ir5f^sC#SQ99S=C>#zA-?!gLj>h0DpFLX zs8tdB6LIltMQapg$(I872XNl}3!?$n8GNKug@ zTTxU|sUmdlj@t!_7AY!MRHdj!QJtcCMKMJy6|GX#tf*DdT1D#=btt-B(VdF!QnX&t zy^1y{x=+zYMGq+2tmqL%or<qCJY9RrG?QR}}44^roUNMf()(S9CzpK}DY` z;&)m~nvxHKDET00n4)Y&BNS2cLHI@~3M!)HgV<8?LC{!5d5R_}qU3|{O;r?9M9BxS zrR0O4sG?Fu^As&m#Cg29C|6Xas76tpqIyL!MJpApQq-)dRnb~S>lAe;x?RzoitbXh zUeUdZHYmDJ(MClNDB7&(5k;Mfwkz7DXt$z0ik?;Uf}&Rx?N#)qqAo@I6zx}ZK+!=( zpDMD@w@bdPUJ*MQUQtZZN=2&_H7jaWgpZ3g3I>fF&k2gc=AHCI@AA!d zcsPdaOUjAXwfqCmjX%WZUIYGS!Sv7Hh)uFKT4<#G*Er*A>imH!?BN;x-F`@j%yz>uA$6$^`azrU9A_V0q??}<$ri`j?REE;9;^)H7UM z4n<3i9;$3Y4!LSseN8phSjc8#@Qd~xCr+4rPVaq3&Qfwsfn@GGvj19z@_4|hjGS!+ z{{wO+IS7X*A-qqh4>=R^b%L*h)g2FOwBhTu@7RnqaQ^nT!^h-=tnxnh9jnqC9{Bp+ zccj+C)7W6}!23hWncNG$yk30yonEB{IMp~me2F7_0(A)Gb|Q=evl}>SvUe8c*bD-a zCw3y9jb+JbV$DeW>@=bgCEW9Qf{gLsIxC)C!oCCQ6auY}87oHz1W(GZ;dswcTL4`W zOe{8Wiu19RgOC{90=lP4f|Z0Fa=sCnh@bz7>BPVzPFuo3&%p7xhDQHl3ulL@s4EtaC%n;9l_%W?r;+YD8>jd8Ci{j_y z{a0WoeoS?rDgS5X(Y`27mx2LZAIkX({FN2I1|V7SYXOq=z^?!aA2&T%t^L-Y@t0#f zzx5gZa;wB|@h*5dfi)8-XlSI`@I9$C%8`qI9|N6YY>!8N$XaIw z(5Z%210?a|tR~0M{sA=FApDULE8^v%EFg-($SNS;`kT5gXoT9bt_zK66%0&^!P^RY8LN6WPw8_@8CJ&zz zGAOwjlqne$JA-mr2BkWKa%~1>Z3g9A8I+$W#ZCKzX_UwD_60MJ&pB9tlM>XRD?@SB zxaYj$f`LO%K>D=l(>rR3O^cyt+TljcOL9Ch69`wssKlt3+EF3)Qpi{dS>TmrP1ixm zqoa1yqp`3uLx*9y2E|N`i|GnJp)^-@)0+4pFt0XB&WN08k|S@~TN9~Q0Mkim&4ikX zsaa6)3+F*+=ND$ogBGK!Vn5CAg11K@#g)H&VHn@!rnG;{JgAR(3*|41xI2%By))+{ z-qTd1=fdztAMbOh`BD}54m$q1^QFGzFV|-H*Y`YVGx+APo5#auC0hOR&Aa=D*1N#B zs2AUSBY+vC?zi~!(fCdydU!XOyXX=EE&kYu&1V|8JqXQa?s&5K+$Bwa-Lixht`;;1 z8$P$Cq8DY`7L5MVcz&^^z8B?gjQp{64lbD`!K1u%ugAOqi8~`Y>BIr!ZH^19pk-n?pn zHKb`jetHgTN|J1J&53ox>#nvCyQK%doDUydQNj2}_SV-2*ezRgd$J?(CpcegJrVXL z@%>vQOOjHSoY27TCB`M*xh05SJD!Y;=`z+4mOZQ=Cb{s5KC<_*!%M8zCF4~n75;2o`Ob1qv*np*JMY1pV;xzk=;i~IX0ggwA-im z#Af4AN2Ku2P477Jv`((zY)4PFJ8fH;u945kr55M^t^1EA|EW$7kxSO0NEdfR3!jQT z9Bn@@h!~nVGX-)NxJg6&qVYvJrCm=zLS5=0YD8GqrZch6Oh5 zGER`PzeeNNXGi0&m&8B9Jl!;z_M^^12;ygArlTT~`ViyOM{?Do2DYfrJ^cf>tVaEd z#vjPp1IlL11o2Xr6N<$D5slxQ(~0*;98#4hq5atHH};DrS`DXDUEil3MbzpsU6C=J z5}Z?YsZ`1?+!<)S10b+zdcUc`K|EnpSr!y_ zVvdb?McS|MnOH^Q7a;d$_#%nZI2#vH0e;a6d3&T!3{&dvW#hxeXOTHgi7V5$u8~QK1 zf`Q?o+`w?Vz%Ja{^cNfYF5PBeYW~P*yc7!PY*a3I2XXB$vu+pU|1JN6X#3gULwZd< zMibMspyLVLuiGrb#8BjFFw#B(Rs1=qG}@0g8)To68;!pwm89^qrYG&y|0sVO`wvHj zH}e;%-UuJziLjuenXWi~18BLBu6qqqn&Hh90+GU4=gIGH81-wo&A8C%DyZ2=;Yd<7Krr>5p5m!p=6`!H4J zIO)9@$dm(nqz$Zq?F0CQitM~F3qve?5w1Xu9%LF7vVvAzG^|1V(7*z1JK$ss8IyMa zx&6lp%rcV&$-mIgmTvS&=q-~Js%6U#*@@;LV(~#UOV<}W3c+3kgnlb~Gke?QIj997 zmbyenIe9XP@!uw=;1lM_KSw~nCn)P>ODdq~e9DsQSk1C3YYJ~#SO(qV*IH8=D{HEk zR9jQbRTda;WAO_&0OCk(u)eXnscKoU25Qo)8-k-7gRy1!Yt_VfB?13hMsGV5ls7?D zI+!eX(*jEOudc4HA6HRVi<6l~oA@}7oja-@SB;AUxX5O4R32P7di)uUQ-b_^x$z(B z!p)-Fl;He|2B?L>{n%$qP>F#BLA(!3lz)Q{snzCnI#(1iYZ zT#@uq3(^~zT9D9fnuod|_=NC#8b&o34qJKnodS~s{I6asI}U#G%jvgf;P0^pEl~7j zMXMCCd2_YNZ?VDCz2CYAf5k0_W@7u4qCWx&-Q7%y2Ua07gK(fv@5}!)3yo) zza$Jweu~fMD{Z>cE>{|*ONEd1THLNy8u!M8wnu4o=(B}(4Uo8PR@!$IZBz82qG717 z;&vjCtx^y;W>sX`Kv%pzxfcsMx$atCnKvP*OjO0hvo&*+kXG zbDjAsYk7T1Gtl}DhsVU}5bLTN!NdMWeDG{E?r3*_x?mRRfI*VXZ`v zT+2v3-W3fr8Svz$EFI)sS4DFHPY(Vf+P$8w&O53*c*gd!mDk-4m98b9Uw0_X!@gEO z@m1+VAIky9m1VKKc*kJoEr?l2tvqg-9+yEmJ%hqtG2PYl3<}$X`$#G((Y3qi4 zoVfO$l}?wYaP)O>P%xoP#tmgMZh&Hrs_K>FYa1IX#^=d0U7CHP8)}~(_POq9qG1*U z9iP1M$`rroOP7deVUUI8xsAp6iy=|v)e?XA#-KF)AE`@=;2QS`;pQv%4ipkH{YypJ zRR~g3(OC1(tV2#LD3EJLf;x*L@9@kHF;7L$Q6W{weT%|ke2XE>L%_?LoSK@P7Rhq>1xDmp~$#F!`+5#mopE5nG+pGvSq z$0NEA!V5e89%fEGbIod$?Rz4cXtGM$K4?0ud-CFrlEm_Cyu`*v5{E;)B7&uf#Fv6* zwQVkLf#{6A#+y9ogR{!ka&<0Fr_IU>L*a-l$Hivi3X0qawUmfH^hmrZh&xQOO5(|q zc=gB<2vw-->AAirE^{!~Y@`c4v@*Fk5!Q`k+gR7A#1#GY0Sv{C_qWZuU+j%&<@8`N zW>>dTz@V5j>hrF5=4J7Bu};L*5VKn7lh~5qPMld>xc{ctk_W)q5uWFqNDoF6C*wRi z@+umCqNMH3*b>P)ikI|UV)82D+a5`b%E4V2O~boqIrFi^LUTFB1$JU+1gndl{JO-= zFJuH%kvmiJmZiBqUD<_{ha=yynIf|32eva_T=6+b(1EG2Td#=4!?aa_*$MdNQE zFMH-oStdsHXXHk7hY>k(Z#(fj%T7!ziN8*P7OEL|qyC>jJ;ZYK)4h_WCNX0Tt%|C_rG3OOJyW%>SOCr)DajCSMm60^Y6 zMn}MhCBSTYlZxY8p70fR-H1D2&hLK2v_GdNy7{0|QclDEeZ(mMXe{9P1`W+Ltb2h? zoC3Fg3lMct!e>)4@xmg`<-DvV7GmWpO_dKS^PjPNYYHk+Iud$)(8`XK=96kCPMr53 z&aBi$h5K)uWGBXV->vCSrPFPhZaTYvn<~FlNmIONTgT=B(3=D02v`hjJQ3>|5O6|c z_eIP?*RE*b(MV4;e;1a)n*NgiOyolp?w+*%2i;vRXwmrNkj;q}?rIv2<#1ExcyH?r z2X60-VtpLBiX1Is=QCvIH1wN5JEyS|wY=V8JvuQsl0flv#!f@WgBtowEC&}AVf8GG zeyKBdOeA5!C#<`e_on?2Y-72hF=Q1dB4`kgN4Ns*>kJn@ebW)$=v12-3N{#mpu~1Y z6IRRPK6~J*_5Dlxb^3b0 zd$kqwjOw)18CBomS=QkbhU5({&#E6(IduC2$bGym`ABIE3E^VOoLz)oTT(z)zVSw*bl9bRUq+db5$TAm04e89*l+^lc!z z@|!c1!bho#Qw{B8Ao1^eKw>)w=@N8{qJcR#HJD zfW(&Ha-nfHCMc-3^j~PXiZ~|_w|PoqSqWc(+Oo`r7E)BCwzkruideGZ^E{<3P_#&G z%avB8s77t;lvb~Zbwhk+&5&5FQq-)rtx8*~Xr0;u7;g1>B0DOV4J!giIS{1z0p zt`y}J@}S10DEmNROG{CP!dJGp6y;b@*y>W0@u0Bnr6@B%VG9&W=Iog*lcVv}^Dmn{ zd&c63ByyhRn*Mla#)t@bI`B6qoe6K3BNcpP_B>Wzdi~}42_Ke=l*aWAh2wPGLLK(Ug5B3nrT}8o8I$%TfU?r*x`!p_-7ELaU~m6>f4e z=ikok+$(hCWU>h%^J36LXzp~$?$yEaUIn3CO}{(2HXh3y-aX%^hTd-Ag&X0ErSmmEa&aL*-wfvy6rT-6P?hoRr(aC601U=8n(z|%rF(SQjF>JzkGR z#V$I9VotO3Z#+E}mWgj{NB3;D1JAwPxC*S}m%#NRn)nSJQ<5N;9t4Vo3pYFFe-Ia3 z!aE|9u+;fnNn$eQSCPc5ktS3OV@GrUaBSPb*eLAwt_N?pa7J!Zz;1!RzLNNXX#6vb zmrD{iVf@_F^q9E^#zgXK;5F0ENa1shFJ(U|-m>?y*Hr?^Tr&`QlVk;J9A zvh(HG7c~_rc+O{Mq~?Q| zsn5b$oQpMEM->&`klS>0U{mqfqLcSRsw&d*8n&LD@+kZyHrGbs!k4DUA(Mc~JaeWb z{vfj?5^rM$g`KQnR3q{4GGij`-(`lH{0U12B`?A%iaTFQT%V0%GiP+nRi$lL!m|5& zcH&#C8Oe{$GD`@0YLg>iq2<-9z2)L&&NHOV700)SoBx4}t=MvapwsFcAV&!1MW+#o zP}ceQ=-XrdY`3q#m2dxm9KdLC1Id8nf!tNJ_WAkd3!f4MI}Z+{?e*i#^cjmTB48KZ zQFJ!$^=bYzyXnku^9|#sMB0nT$AW3HQ}elvH9aEP5S}% z>;Soa0mvaAWQvA&ACGqB%D?myC+dp&KC}xzX*jC;B-g)pd^;}mLDu2VlsnSf0RLLN zwt8%$jg`zq(D@k82U zjUmv=MX?gdw_sB29LI|9jIA$q3Rt4tI8YXxz;9=p-lqBakHv+P;q> z5MGh$9O=I*Cx~^ZlK9>o{>dmvlTg>^Xxv0Td19&_1~$#~Y1Ed0Znym12prihpFyAC zLUL{z>TonY?Ns5AW#lGQRMV05I|h~3TdmrD3|WWdlb~w-H8OO`yM=^$;L3|iwdVpH z`T!J=(cg*k$Fde1Jg?Jzx#>N-{i`f7M@O2jp>0boFqk!kK5j1hTzX$?5FR-IWV}UP zHhi-2dlhCMoT1j^cM8T8{C0=%dkc&W{Ljwid+BVhu4ufrjAJ$#6P?nRwPS_AzTl~b zz3kJ!3?#er)o9{^c#dDtPmmVb8-D?avr@n1^SgWPCjl|V(DMT%>j2+Uv>QlP7zSgi zA}a!C00|#8as`dsD}YWmh^zFY4EiyUxP1ahT>Mp$4>>Bax)exauoCDL;}(D9ObO!U zqAVbaLdyyR2UBvsM$ibgrC&m0JOl;RHb-f>ia56tp8?FO2(l3mc?A`lcV|W^B!`mv zxdf1PC^Zkg8Wh%~6y*ko-Nfn;d%s)+<-_zIYUchc*s)$7YKF`D%5iY&`S;CmISx*L zGH1AKM;!O2Kf9b)L>4K{oZ)&$zOw!>CEWw(jgl>Vn5!rNJYD9mcV7I7L$NG(hD$jY zc}T$=rq^z8-!tW4nk%{=mqvjP$bo6{&?#oHInroB6} z=@Z>bxoM%2%H&PQBt4IuFX`1&IkQzGht^nD-_%&+2HdBgUo;&uFO9nQMS~%T7rexdnY;V-UxRFYc368M=S{wazpi!We}D#Q`g3d#nrCranB?< zwTR%^zpiwmIizMuMWs%2gI|2IWx|AW^1+5DrCIzAr`KeU>|MEH?P*5k=1g}xJ4HNf z6aR^sZUMsi6#ba@In+#d65=)lY2f3|bftWS#=o3#Ryk>KsUhwtPjcVnm%Rq>V)Q2>SW6U;9J*=&vTPR0Z;SCpNH^pA{@jfFoxcCd$b>hEyfKG zd&@X`JHo(bEtv7&&Vu|g#I^1Ch1o@gm7@YTKLqQZBa7mHu@keidyXvTpz=A;qU~eH z^O*iw+<6IX8fdor60@;c{YKc#C|mZQv$iPbEbK93#sQ(!+1S5Pt3{4gwD9juk0+*& z!s&~~^P}w?;v+K7z$%21)$AEy=SUrc7zaLY%F8@ z4gQd|5f=cjK+4~>A-~=;H@hfNi5bA`tmJWKv}xu4Ex8OxM}pkhiY6im6FbyT_LOGH zm>Yh#BBGv=VWAu*;#SqUkkrmX5ZGHSN?ZuvwJ*lPn(Eshujo$W%^AaK6h8kGg|F^ zzbDg*iII6q@ypdCf?torAl9nGr4Lx9sjml5e!prc^? z)-FXn*(oE^w}E8rHv};g6a^AnIIxDo$nKJ$EWFDu3i}kHvDFJ=n#Go5KcO-0f`V$B zqcrA**mBe%ZUIb=A#!*)UKLbq-kq_QkQ_?t#~lNG-ng#b@zIQSjMM8J4^kAi50<3Q za>ohZ0EOk5qWsWt#XLFG`0z2-_d5b2T(L&*>ydi?ed9xZJ<^~5$@tLw&5-dS zqTI*xltYv8VdfZ;*3UaUsqtaALt!3@zn?i2OLLwpj_xBoN2gJ^Qkgb#In;iI!<0UX z@h-sICE@9i(!;X)=dp5hQC3@DQDqsljK~a4jPs^?1n&%93;|c7ReYi5CHj;KHgo4d z_hP)GGBW_Yu)EH+FIdc{XTOQs^1`J|i zhZ%m?2H#Vxf{ti-fAB?d zzbb;*`c02*;vh8oC5UxSYynJY{53sluaY92&uK7B)uDP_rj|7{_5AyKU8W=b$?SDm zJEe_zIVU?WwCQVBPU~q7PpY?^lR>#MgA&W2+>%CFk2g<`YC1RU(>72ATNx)=)V?O2 z4fM0QHW^MDYbqL`m2H{JTUh~V;xe*3b30?-v^2%R9!AC2%%IHq9q;tlYmAAHl0 zcYN6VWPX?Kp{eu8yJ&B|0)~`&$d?ViOM3I==cNr+$QJ}(c?RFaw2?IV^1%1yUVP|O z6LYdSyEzhv{j=;bd+f^LcHy4DcX?iPTLv4#4zeHW8VK;=a$IAohJx#}P6L9r* zMl*FNAIU9(pU|F`+hg)AQrT+wIX5%se398ZIG4+{$2^T=#j74d2D5yy?UMg;S_}|0 zB4J3~w;6xKAGGGoK^x49wLEkN+(;1K)F5#TJRkG$Jmd0;;OCu2vY=FN#nF10zdJ=t`C^V%K#unOTXiEo82z}S$MgU7^9aLPLzjKudC z)p*!#^J4?ue0WjG44q96bWCA|?#{bee?lz}nfzrHYQzwt6TG<9>(GM;|Rv&E@Dw(SN=}hOTvF^ zQG3{z|4jJ9{Ur(i?<4L0=j{X*%;0Xs?`>TEgO>DCD!fQy#EwWJD&g7ji*gZWcO+4C z{y}Kd$Yr!k665Uzr~XL5yFEuD`+JT|et;_HwA&Aov$$sD9!2?x3sK2?K$3n*=yXMT z9CT0bi~OX-H(LBLxRYrQ!bmi)L-wPdIuhOwvEgF7*eI!VN;tliOI;uJ#9k1>W>a8K znea?|rY=z|apBW3)^rFaryx;7zP4v>I*vAZkT)@&JJ}exn;#&jDSEySUJW&?_ua{C zNZglW!K-NE8XTl428CJUw9{hj=|Tp_CNbRnqXQT>e|G4O#57U2-jqv$I- zDddDWPsNWFE8N0d(mBvG=-Qewx530|7x;Q^BR92zz8H=_VWL%xlR$07%ny7cL+F)E zmg88Cld(6hLIn>)^GAGtsxX|hJr&wj9qE~{xq*u#eihNl&80#CovR@yVn_6u`atWu zh(Gcy`2p%$2P0L_NUcg*at1gphtvm3m)k<=a*zMiOk2^a}?T2*)!`L6R9m>E**|6MI}Ox1YkA~3;v zp3~%0;xZ?LZD%N(Lkoy*?fWq)LbJAn{g0ho6k$5pQlN5*W z>uxDT;w7PnE&@u+Hei1}dlx!=xixK^Lq{m4?x!ANHwT4c?(13(8 zENf?L&RYKB(L`}3LA67Xe_tT2_wHBk&m>8^8&-?<*bavF_35vN5ebA*`vS^ zagNX-c0MpK%Bcssl!>m&Sp{b3v5G_&hvQ$G2YSWSl6XmO@^JK;eOHg z!nO&<5jHCQ2hHq1d`&02k#2jHpL+HKsNl#D9EjPTJREvE3`6&;>`zxg05Gx>QO6OC z;T$>VhRt_6nU5CKu^E-7XIrX&OP#=i7F_hhv$eB2+tVVA_bp4aeX;p&8;l+AHa~XO z3$HMvt;HQJUk1|zA#uFM_on@JVuPh*=9{l!1g}Qn0wAcY4YWogTMkYl=qqks?e3BwkL})AX{YtyyC5bXxj* zji<{NzraW*W_dL}45oI2*S zKDSlKPV*^3N8!nVcIzn9J#J*L*^ z6-u;sf=`rgi6{6njiLYZO7LZBKPnF~)Z>5|+%6-xO7UHJ;eB*E?0tWY{7IBzGZNL# zPPFeu7%gx6iupOKgH^l~o%EBsit0qFeZV^KF)xs>C~rm}o-{!qA`4AK+*aHy4dRTZ zT%dd4%xXH(jSQHZJ+W?XH`7v_FwSDbX?u#=i*~lLiSfY*arJh#zO>N~`jf(gf!1Ha zpXQZ4mj~K@3>0k-L4OexsYxwr+rmCJz9V@JemmTnWBU#!TR=d=O0pAn$LnaPsL0G| zELwP?=eCH=`G`!i9(Bl>PqfeU@e|;b1EboN^$u^q>=&C@k{AeY)`RAjjV5m&I`8Bt zc;l=yAkgkO`d8$rQz4x>Cd-LO?4#}XntJF=LeT1|4Jr>+)NlG1G-OP>s3o!I`7q}0 zJ(0p!noO}2;LBsyDV(bKPuD_I`6wBVx$tzKICrXUpp`=%r=OJyqDdUgBo>;1PY9hR z+eG_OoF}=NfxI?XG@JIcGn56ZL)N(j?2>CtK{b=lZ9Bbcrxp`;T$9wz=&s|mOEY%b z@YZA*>sLB)Tk>~^t!Fx8#&hA3?q_?bd=t&M&cJm0Sbv;06_(WZcs?gE=n+<%4F#i} z{wcJ*SO9VqHMoVHWIpZ~8S}qk{PZoPZc(lS#a~2A6D9TR05MKC(;ia_uCN2ihJZ{S ztFD{rFM|)F;5j@)_M7V$Apa3f#JO)0*wnlq{ak$8*8e_f>nA6*Y#X=%pMwDpu)YO~ zJB^=4PCdBLky3>XBr9pe;9#>q=FZs+&y)^&enzdT>P6Gxov1=+}e@;3+*f#El_6s8S^ zi+&w2L3BkUoL`ES^UD^(?^+mo(t+ROkhPP@gWp?VI3eS=i8s93z}fg+2vZJRj^7`` z)Btb9?-fI_Cr&zkZ-H40%xkg7BLeJy^YD8G3@3!;_YRXW+&lde(I6Ra<&GbjDRQ zG*$-bvRohru(NKjf3RmGT^xA=Ois-o04CRFo z^0*06|5nu2Rndd7NK?g?CWl>85JgdWb)%@g6BT(T`oX2kV#o=zv%~PHOV9hDT3T$A zsAA^fEYyAfXLl$aFaBjeEUz6dJ^Ij5p|4_{+hu-}(doPBiEf{1vxc z?mO4exSl9{rvtI|`K>Y_wn@LW7D!xt9q2qm`ytTz22lsQ_)IAy;rla?`21HO@%b|# z@p&tk{~IN#AJqxHzv*uFun#+sMXe1 zytLBRTh$_p(trwhEo$q%J!oy4F6SLx(jEuWblG2!H_*BcwzOj`3Ru?yOB-g<28L1_}5c< zf^P|;o++)^BDQ4e8nQIzD}aAJrM{>uHC<_xyP_FD>N?BPsx6vpUFTa`gGFKMy4cdL zwJ2&`9p2?!Wl=JvJn){ zJJJ*`Idk@rro0CV=OAgyUqRtaBu&XdE;%1bQw|4(vywDrI4Njz(v;Ic;S42BnF0#u zDQU`VP&ivjQx-B5K6&_eAo;BJ{h&kd)=yWvVa|qDGFtoj-?L!bY11&Es|DLX;KY_a z{Zacd{f#0+zI???dlAItJ$^96f}atBJOA0@`#}Nuk?@`_ z5Hyz`%2_F+eF~{cDegi!uM6d}E|djbD16dDKLJ1HWEQ3S^JzcK^26{vHL4#I&y!s! z9GPeP`CS*vM_nk~=E)8rKiMeG5q>*r?k zyf(`Z-DEpKJQ<1ori-7Cx==pvLdof+DWQ&|1iPL~1SO2gzVC^Cx<9GdKPw)3|7I5o z&+_WW@Lb%5QqhHSWf#f~T`0F&isS1cZ`?K?)%gdqC{N&5hV^H6rtos-4f1dNWtr52 zo^^XpcM()o>7mDN-K??ufeiU+|Eb2Ld`1iFJPR6dLB1RsY{Ftj-JDUlV!tVj+x8o9 z(=LrltLyNHC01OzWmpa7=isH`xf#}}b&&<~OV^1+`5IsW8^#)k8nMDb?O4<7G&Dx) zeB1xd(J8-NcIlpne?cI^Lv6#tv5V>(v8p0JnfA=uCY(nAze>`Dl}tR7Vych$hb+~7 zW~SXO&pgb8jD*Q_#L9EVElTt2E327eLuD;qMi2)4*kq+AivojPK5M45`nswb6p^g> z_@^cOUyUCYxvBWwa`Fw`LX^I znU5Xg=r4WX&Hqs~zaC4EkWEe4r_2pQUx623eR9#vg{s6Vxh#|DDxMKu&{QXiI7dAQ zi|MPdXrrC!l6h+u-op;h#3juQ8nUx}w!|c*-R&J&>OE6!Bmh)eqie+55{e|92IR?4 z2dUQ9but{UZ5S<;L6isr?Rs9g0qdl-evFyc-x+ELyKv}!wqBu!=t}HdViJcf-1M*X zx#F}i{7i%!GZ@Zzp3mxWmcrxJ5Iow)mp(LjHO$x1yktE6A&K(0)-r9sGDBcp7Or@Q zLt`*XtKocQ)gPkaa>l2&VT?74|F6#YoIHM9KtHsK*Y58lbPOCX@q9$)s8dMY{0aOo z-0#)h>0{0lGe5;RrTp)%1ZU<4Qv!}iyL|qqM$wEI3rO;zWV;*L9tC>WewOVQo7mch zvHx;Oo;uo;b^5dxP0EymuIC#9NEusEPPH!qe*JHhWaj$>NCK;1xXZ&&lfU^X?&gJh zj`N4XU!Cul16BI#PBX@IiLatK`jlAMg%6fp$Y)ojm{8_vDE`JrEZ6b&h1zlcB)`K zALApP+l{dFOz>^{gQHrm&1dMlG+h|YNF(13-5=$!E@T{B{4ZZA{eP{R6}kogQ~JXQ zjXwW3S~V1;ZPL*3m^O=jkYfEicFY)(0;i51tB1Da)E4LU*kK;1dsS>pGTU>yagFC? zRGhW>{H5y=|9`YU&dv-JIH*1%I<3JAT-<9OylW2Kf7KXMbb48<74m$teDWJNp~YU90qm{#N17 z^_~1>z6T%^Pk9pn=S`l+6Ax4s7f1flE$M9;YqL~Y-3U| zRr)jxp!it|1DRGd@ie<{xfZX2^0WyaGoZEi7&3K@T3bb7@$@xK*TpaGu|r8*8K;*e zBEqdD1!MT9!r8wAmNYPGn^q8rPJjvG50IhgwQ!A`i%SP#i-c?DV22cp?aXQ03acOZ zJ`zUbWTO2JBu0&bH5{zC&K1)$vTIDwc(g~|&Cw{0Qc^>txFuiWt&@1e>)L;9{BPh^ z4h-3{VuKZtzA4<5F1ADe#_2hpHfsJP3SL!$Eihvi6?jcv>ky+haL{%iWX`;~;Dx@C zGd*>+0dtVr1-OJaG#)m5VI0FT_NSX6y@pZYQ*d^JPdLB;^JZ9At;&kPDSc9k69qbl zcFWa~U$<|kb(e3b1VhuS+MmlXuoCMeUkAHU&pteu;47msL&^v}r}O(9uki7NGvpNx zkK1vy0u3J}R$3?P3kv5A-hTv-y&S;{`BFG2QxMpH1dPT&*fyCVU|41~8S!VI770OA za+HuY3Z{{6dg~#eiKSp4*D0l^qC;8TC zdK@wNIV@m}N}UzG_Kf|bO1&`! ztrEep;<7<9#}HX3VOJ`AC!b}MpFmqH+5V$MvC>kwfrR`fDV{&r+0c`~^4h z6A<F{F{cXaP*;o}iU{1{L~Uy&j%Qhh#$#DhVEkI2XI z7b4$G?L|Dc{*yE7??2!ooTDxIv+&GNy|esmO#8u=!QkGyrpDnHjFuC8XN%Ol@|H** zk{sMVDl@(Fklt4C71k>=k=Dm}$oKe2Z<4u-0|D{vXxO9{s!=zJUD%4@@z(f@@W8yk zjBmb9Iu13&#jU5#@os|qgv_+?E>Tggd~n&cUo@(|l}XSTRIUkTyBe~!o(93gN|W31 zR572o9gkyeABNm1n?pGN#}XHPLXo%KOY2MU5&yA?Ex8yCeg$5kZ6BYup2U3(-y%2t zX}3t;`llArMAPt7hSt9@H3l4-SJ^{Z)hi=iaMCuCscO&nedB}!q~OZ0DYSM$=FT0= zBYHTe2X21BGbK3rsTsgIAV#!i4{p1?rAzz3Sg6u-B^o}*^9G&^5;^gVqIcG?*v=lf z*aGj(;%89@3h$Jn4hY`~k7R+(<++_%xRuFRDJQqm^LluuVfkEpLMIgaHI47luifM) z*&s>stciCt>(F90eT|`KAR2y_(tJ1yKc&x@7GA7wJ=-p_Qa%C?A_;f>MJSDU0X4#1 zA1`RdckIKQ*v_we?^vNfaS!pZ(D+n%1myu|hrEUt!ZyG8IsVQn2UA`fs^LpX7aEMy8-Pp^V1lt8la zf++liT5ghoEa`^4?*{O|PdJaoG#Z*&)RCHnFOy&D&aB{udW4eh4G&z8 z1C}VuydiQ7fwSyVTTZDv;coTY$V37ljl_F!4SG|^Vk;o>NR=)3rVMVW$N`aZWy=p! z-*te!n1RF#P+k@-^9Ji)4kdAnh${U!V3}Leil4>!$>Iha2l%wYLeqE%t4R>cy@_~o zCtNVA+^a6YYwc6ex1`*}1&~S5yEs5r*w3`|%7E@eg9AH$9%#LsOwcP za75)P(rp-2jni=K2O}rk4UKD`{r=Hie-=)6Z^_~P(0F@#7v6UMWa5x;E9-w@2ilnR zzMi2m;?ri@kYfZE;}NZymp_Xu>H>7xc6I+01IPKH|GgI9ub}Qw&vxK@Fa8zK4Xwsc@NWd*Bl!L!{!Iklg>UXRmjGAb zJDIE2Z>#WKhiWn(^agw%jp=Y4IDl{WP`n=qoR9CJ`1b%Xtfa>_1&$v&cFbj09Dn)o zj%iP;oduPPM^;{0bGlPoS2aI^HzOjmtLqn3)?)u*6z<#&Tv8ut41}gm^DU`I1>}+I z2`8OYg}sMSO*JP~*H<;2G?#Pvx#0!#`wYQD)UYa^gU7PPe)`IqI(Zy}4^9W>*Uo0J z;{ubbYr_G&I=zIk*DtCIG}boF8`Z}d+5|)6Wkk(6NGc0dew` z>kNS&DD6TZ^~Zxnn#P+zY~*vDL!l!YAK!2Ome6R$uj%rIx)DNq-}=jkCaEiL2xSYC z>s$(i!UtLebdsQrKpNk6phBVT1X8a4Vo~2-Cd9Wa;x2TNg!rjNf3@hygB)kHxK4m3 zYq~+80-?PObh4liEv+Qa@Vpp^63%tp-iDV8f!KEEI`>-IIv}+Leg{ZH{LQ)^+Q)<) zYSBeN>~wOSn=I{ii|(>$okhO{(hx5KvCGVL{s^SDlb>5!9_r`>aXk@8b9pAv5TVij zR%J>%rqhI04>VNJ8X&d{xz2|`nno__xFR^n`3_xu9*AH1{ugH;YX7J-wmypZS6v5N z+A$UdtShl3#T#wy4CqhAgejq6+Ie&C;e@G{d^ivb1W8 z=33YJmeycV*t#yZv}-MjT2}zEjYS2-=M4N)M4Ki>#TH>CET0@F(Cr=)9h2(CL7~A9 zl-7@hWK>@H{KWr;q8!lAX5SA~_keyl+**r&!VkV3=TG>@-X=}iLoyOhQ}W=>o`)3W z=m=2Q|D-9yL18bHrko54`=T^u5-9AE(v%B8VZW57)PTYdO4?{_4;*i$o z`lHidp5)*MLW7?Xf;<2Dk?)84qownxPocIbg|?6UP&btFu1}$ymGYTSp}+3l=O+Ct z>nGrc;x!TaF_d9lDC4py-CI6|vivZ{8C@uKT_~|Gl-s&c?(IT(tP5pR7s`uSlsSv| z2AH2w$K;d;$Mr+X9I@5Nq;MovH!qVy%){sUG4cGZ3#AtoP(H@b084Rv$p^YnPV7P% zmqnS3Um3e+KFl_Ev6d|dGN|e{6l^A{BMm0<>=>)me2c?CJf&8{8&A89!}r&%+dqq6 zEE**ChRFQ+PB&Iv;s^_ptoPJ~m|?>q?9H#KtV2FzzmXo&Xr`Re%lO??Y3`kum}u_A zfo=DB%QV5T-m7LC&s`0XtS~Z6iK?s=GKt-oEcvNr8y88Q4se$~%u#p~EzEA@{A0Jq zMJ6b&o|UM;Ocy(xZtmpo?qTaHYW3F64`!s#; zAZ^^lP%{_I$uxCp#0f*+<6@X7)tx+gW@a=nGeX_;?eDsI08g@L1g<~)BI(0P&cCxa zIp&m8ibe)86Dx>|X|IVHtnB`omB7o7JslhCIfr z-sEpF_b|KJn=FJ(=0kS;fDM0dk|X-`Cm*mF{uXxjcPi%@=@0!?z+bepzi##>XTjf% zo&6P!&Ptf^HNfARF8)r*N|^ql@b}{`{!SgA=1$iER>9x8&i+Oha?)czjBhRcJ=)1% z$h(1)#L}d*fx>#$+}vlDg>WI*TXONvQ*9`DyItCV7ZL(k*J)z{(T!2;Ghnmlu}2V9 z_!z9y&c%?XEG71h964rJLmexOGHtf`^>&xNXY`df{LDyRtUx-*I9>V&hEK zu*}W+5()RVbbruzlV=9oe}J2Fuz6UFD~Pz}&YR7!EC@dJ+B__#=3@=1_==31gLHv1 zxf{!G6D2cP%b%#8Bwb$~Mf*#=JD9t&+^FGO1wN>0L42CG?)*v#F@uOy#VShfMh z0!o`umbKznEGA5bwn+>~-)X;1*L0KHQW30XhPF-0BRO>~en8GfAFvqd-9iCyvli10@jsDSv%cI)2a6OR)lY5pJS(6E7n6 zv_5n!+YK+p;orpe^jvg2H)|4m;Q_nd>%eYNYbo9wj6Bia*Q_na_T+{?H1Te01(W-| z*bKB9xC|(Kw70rUU;t07$M)s9Yc}U?kMxS|3q(ej4&PJSyyrIQv8Xx<3s}MkPq1xjBN@b zCA?VK8-cKck2Hp8uodD_B29gw+dC!9_*r?(Gcu5R2Gq1|L-g)x$lF(CUghBE-PMGU zxnCl@TvP9{LvaV7hNakLXh6dF$yFZyT+E-i_N^w=a&sPNlCs`PN6v8rWk5)w7Vm9L zjnsJ;wnoP$K8+Lxag_~A%2_>(1+g|h+xh3>V`3JX@A|6FZcfc`IWgDTj8?DeFNJQ?EU&pN~AAVe$#tt{(5y; zatrV3@`@X>FV0=%>vvgl8)|mP4b+A}xOYc0Pd4X8&JTHaaCF>0!t&=GA~!MZ6Zt^> z`-Qv#?)u!(v9<{la~AU9J5NU+kT|9v$6J^(D=Xc-9`ISV7u8282-0V%ehe1YjW7&Z`QU;?gEq~ zww4UWqm7^^x7!RF`S@=PW~LiiVJlI~F$bj4;SfKuNiYJE>QPc!l`o#|@O5*p%#@b|dw>vC~%EPZ*sR)GL%u>CcX zuGfOxfJ9L&WF_3+2=-jf_|i$9H%lU%&VZY9-NaMy-LV<_pB#1|;sh)e0QjnrMo zO)&b@5<~Z8=*BOHy%DaQeOerf5drPL+G?;B&ukAx{HdSAi>ZI``g3?i;}A!zc+B`{ z{7J2V4{a~jRuRvr*Jv_co@Hmg@&#lclfryCHj$ZvwQ553U|HqP`FGR{TZLXdOr4HFTC0v-Pa2p zQS3=orTG0w(p$|cijmr3&|hXA7u-b-O3DBU^-|sPJ*_}5(1p2PmlL@>>Tz_DQ|46- z*5;vyoA?p<(r8YPlEpaRWxyZu35k_HxVwIB<*q77L!SeW++nkWOqLqP<$25bbb)=)E!m5(5R1 zQ*@&gh`Zt3go0xPoE7pC30*K1_S9bLA+o$-5+VAfdL_Jx%FFf+*0SRk1-#y zojoU_^znSK#f6_w zvdcsL=aq8Nq;wxhFq)J?XkYK^vs_jzc?c$-L(P`~YiuJ679x2QlE%fNZ;OyANwiHd zDg)~5EBFOtgl2d_)kRMga!a;=K28X*RFGKx3??~w`QmjHkj!8t)2V-eGt-`+_Yrkq{^m?v%jDn(!ohVn<6{^ ze&=`t7&YdswDu~drBetdm@q-h)Q@jdCA^`Gjko`XaCdBOfg7L5;C>P9;B|@!iYKM} z9%jo3*~KlxQc%JD197+bMwS^S>M1w=8R|BP*{T9regq$G;w>7^7>!9hh*C*C2a@Jr zt%p#qen+Qw4f?h37Dx z^1#|-^dYee z(Pc+WW=C#3jvr;-y`0d94RTq_$lVA;|E1oc1;GuF0L@ROoY5N&kTP9gJU}K(?y{Ls zHX2l6Ipw3sD^R(Rs+>x$*MFsQw55W|p*`D?rE+|?_g_)DUF5E-%5nVxDz}rZf~p)^ zOTHP`o!ZftuXcp0cIyCC?L_##zNOkwM%^jXZ}xU8f41hS$NhS1%Jy)SBL*sPVp99_ zQ?n5mWx!dgScx*-;L|edJDX0h_J5ik%>EszQ}H`1>_s5_7ydihGUNQiZ-O*u-o_Ut z_}E~m<(E4|(eL1xA{afBI!V@{3~XW0bVy~3&xQnHJGvnkL>POT_wAt;LtyMWC6`9W zd^0sS-p^$IBeheys$!eXXHu_% zlFpwgr1%pc$NKfKF(Hv2*6{~$O!2jxi~>p=g5O%K$Raz`OcBjR2#SbBn~Opj9_v?( zD2pMUVmEOP<9i=}pnbnp?c-=SbscMq)q%)MspH@$W5KAC?Q-lBoFTY$a0pKgwK9G0 z=hTog@9}4MiNs$m!@Aica1jgs-$-__mJu>*ZFn&lb51C2a={?ts2UH*(H2 z(2akI5->t29l!1RUJwG-)sp*=5w6brjKk`6T%tAktee<}ScBf31^HO2<@+}dMns|U zZ-m^lasK9G9K#YOOZj{WTvCrCeypoNcX(0o@Xev&FSg&8)=w7K@NJNr9}3eBOjJWX zDVvtQ$F}X?|F@ufJ<1={(&YDcg6UH4!n~k+_~d*%d63}RIbK8P2e&y}_WTUKVzXkt5vT{R{lqNQZs49L8iEfH-gsd% z&iO@hYx{$CUVjZXb>?$Z2T#h#HcwL5Vp(g#%l!UzZ}Jb4!BnH)K6XU8dYzAn(ECUL zR@rZ9I%T-<*^3PuNDjS1e1V1Ca6*+T^kTC>0D@t8Y!90m;DE+k>BkEm%35OE#qnM6 zjS+DG96N2RF{mQ{@1memr@^<53)8mPVcPp+3Xg?neZHE$uS3vK&X-t}MbG25ACCQm zZq|4G#a$hdqCSN$2@QWcG=5iO5U(`#Y{v>b#?a4VMR|`;A1-Uwb`FFP|H10%ukOL3 z+O8L+`wuNQe?8YG75Sc7{|V*1-M&I!su&l&o4v(S$zIb8-u2v1DZPhX==YF2xR<{A&Lp(h2HnX3L-ggfW#2D&MS2iP01vNDzJu*WZjj zMW*|N4|mt!LZ%n>itft^V;VfwD}$#`LY7)Cs2F!q*Syx9%IpkngZ5#?w(fWc}T zOQQ-@x_^?lcr$Trp zsLVS!G*fOazWOg{9(34cS!Wl*JhaZ&w7E)yK+dkHT3%c|DXaK_f88~-B!pAnS(O?@c> zu?;h^aWxRJt?m@tGaz&8j8Yk}5UFyG0DpIN^7lRZW+m*DQg78-#FKu35^5FTlzLdui^_^vf~%BnoKsaZ z-WBOhLFMu%4(J8Ac&>$)m;?ti-$m`jQMJ6%@y|nupyNPg5hChH$Ye3xKjbAiQ51zq zy@{Sm(aSQyah^I&So2F?_N(0ZTQZyr;i(C}C%GBLKdAi_O%Doa&jcQA3Y}*HG5T36 zQL;x8)hcf}Z-3GLVD$R^r{O#*Udv$GW(tLeg`ji$^W_aCXdNFqiH9gxY;K)+(AM08 zCqO&PhwnY7CD%=H-Pq4Bx3anLo*IomrCyZ7Kz|V@p^G@1Aq1?a-&C*`eCXR6FQ5R0 zS!Qs5_|QzD@|5A9F>{v@RrY~CX}|pbG1f^37LkXGGRooD)ZrkR^7Ge-S_Vb3!zG3w zh|%+&ZsIrzQw$}93Q*TN`HwqH=dbvK7D6VQyV1e%fzY))u|+tG-f-Hp!7p~~ zw4=PRrVY9*84ttH*gn+Rw-8#6NCr7(L!i@N1z%WAj@+lON=OVSbu2^cVYyJ%O$AYS z#e<8cC%RM0uVobvmHFkxVJil#*M_`9w1T`;p0>>PyP?9~Q*6~4&`4TM>oS#|?FET!qH5y1}Ct^$enR=AbxT1gZZlz|I zc(<@gMA@%{7&>lXVI0iO<68!xEP0KZ<>rhpzEl za?>&>$S-&DmUce+DEa9{Qb#l6%ZohW`wYhR<%WO0Xn3&YEbc$?7I`$waGWCHzq5tA zg-(fk_UnGi2+#{2#kobIWGcQR>rv*}cD~x^{c;B~#`Ep$jlK!h33)%Gg7bvqQ1fUD zrhJrad>-6Oy~hg}MglAc0o_*1$f*c|_{+Sp(v_JLgg6aP!8DZ*|AG;o5#k%W%&&I{ z_lt&NzKrRglncCJ$85k^uqK$`FOYGe05KY)f)~X%I&@VE7BveZbmUJ@-iK-mRI z$}T_%n^@@8an8|SGiw=im9YN~n3PcrV)dmeI(Ch}TNk;E;=A|v5UCv6bmKWl&0X(c zjVo~|AQ}}pSGf;G!{LuaLS;IMj_Jrn0vMZT&JXh)lqS8K+}N{}p&g!PMgy2K2o3HnuY_&ONHvFk*fI zKBAyWI_)D_ztj_200vR(vAl4tnEAEzy%{vKuYf%PN{Q7rF&cUyx`ctSX2|p>6E6!_ zcNuK=+=_6XH(13FyGEkaOK2SN5~r|?(LuY%_A}ISG1{BH3k{Q*sdCT0eTCn?nTEXO zBJ>V;NV`}M^*(hu1z;S}Ovc+285)!TRW(hBZRdCmFI&@%7t!T5qQqq~$D1(tSZ zLdvpPDW)#5oxLaKu*InVzF!H*nkZY01qWy>HwWCfLhY>IWtZl(y*PI+&m@00>4 zO+F`$U_L_nC0#at**at(JQ(xfr&uRL{>>#!YA1f{9Q`S-K&K}zZsK`*^;Yjh)R5lY zMtZ1{qx}%j%d8Nq(~-e&W4sfqa5KJ91frp44w zo2RMAp^F@`|1k8ABf!WhX?bMyXXpr0cS_&MmN(6Zwp1@;yk|1?(~L~@j&7vQoU=F= zcPrcvk@FH})5@|%Ji%RGaZvpA@XqMsgPq8`?xq)o>6Xy1qkHof9lD`6vJrZt4cqgZ zO59B`POuTnFC~_}!OeTViK}<^1Y@nW5{wx?gDqlf>QsDDPlcZ1=D4qqTyRT$ft+M$ z8~ewLGG?@eW!}%YB3im_avn1a6E$2K~J z9d!+QUHJ4zGGH!#2D78HAXKQ27+PmWFe>9TpYxrz*Z!(g`eo0-x1G|5vQd?Lql3r}d;M`ElH#Sj%?qsaE*mbZ3$7LPTVe||KTF(9& z#I+k$&l@FuW{W+07Fm$CE?f!5<^rw{K(BIc}2M@n}SkMjWNd+yXHg>PX1s zHu7$ClP=than~pOg`45gO}cOsm^fh3lhKuoCffeUs?ykXdCubJO|mQ7Z$r82!ocp0 zMmkC4H8g}yL>I$05>rKe>-l_X?Of9{3wNn z`zXYmn8bsF+wYBg)XUl~zm;bt_mxHJL2%@BVO7n`zNAEdmyS!Y7?X4j$G z3P14`l(X-&g7O#oLoWA9b9pz~#ppAX#&#Yux$=8b4kZQo zD3j!C?74RbvC7V6cl;0D)RsHBz7@qOA`QwE3p~nNli!#z+h2%eUN8%hWi88ebrN=C zd)vPHv#d%cK4p5?EXdE1-L3SHACiX+9{Rtu%-;d$-O2p8E;5f?k2lu~Xp{~U3-Ema z9wQfv9E`xx;EPooA9M~NVKgYha$AMZ>>i)lJlKPxi4JHDD^=@nE@5lSBEuEC72&Uc z9f*bBBGoL>n8e%O{S!rmbjG>yFtUzZ9)}V%sUU;n+HXVUjFVL>r34R)YVMQGtaEss z7Ef&Z`spTV$H3ih%oMl?5b~y1&`fwxiuO|+->TiP+O3v(J+W?=*5&XADZWZA;|3%VQF5{7B5nO)@JE#SgoVG#PReU6BIWjVXFLizl@M$neh@U3Pr8B3CxPBGlUh z#Md8A8sFcMsEIGQfpcKUY&jB7=fF+yf|vu!e9lK!=7|CbgoS|&?@uuiX*X~@LIyIs z+ipzh!unlEHPy$uH($#}As_Gd{tWVs{**OrX(}vPE%|3vo%>DTx66`pR#l&jjUp~D zFY8*>51?UcWZ1o;`!fTpe^R-r9jNE5;F(q5>g8E~)O>%AEKxhb^N&Qvs{Pc<)R%D6 zej_MPw!%+qb~(iJuqKmw!}=>t%k4o3-pK9SqHd5I`W`kgekQre_O7TDt9T1yu^kGn zbw&S!PolQyu$ybUcA@nPWu%j#lKf<3#fU6RT4KkPItA?NI)%SDnyu77Lnu)~oKMLFeXl9Xyy!uJ{T4XrJo1@!QaNE6dsxA@WRf z6u&!#BG4a(rr0UOpVUnJwCzV)uOHRcF1{H?8L832mdJn5d=XqHzWc*NI_yF}Yy;~= z2jVwr>uqadgMhsGMPLdr{yQeM4c;-BVRxmH^!t)>jEM76Gf=@oxR0{YfHhIX6Yqfx;UwB%j=SCX15m||$*9+@j|8<@*d{&4htkGQHC*F`f)g7O?@vW%o_USra_m)#%j3UUMgBw2_2^nojdw0P4^n8W|$lLgZw9wgBVbhnP~|k%qGv^7?U6PPgr#@q{ohIr}b`ATFSGo^$35H^KDKFu`a9k9%A`Dd?c53 z2hzV;WlN7A`oc5h@rKAl_vJ8tiQxPpC~)#T2Qgzg4VJ)I}F8(l8Dg7F~k^lgYd60K-0wsUZE0+3D+DZ(VrMbP)e$ zc$cE^<4z3`MLtITq6CQ-WIJM*p zO0KMxdLa4b8uFjq73;yXS^awx9TboLIpLBlW5bZQQjP$6t0^eVo%Y{GZ(;(H+$s#> zhSjC9uVL>0I%S{|E!y9Hnv74qJ(wp$%p9QbrZ-d}Xa8zWutPc9LfrHizsrsBE*w8( z2uE8BLsgF*%KA5aZ)p7PrBC`I+S>lG(d%t7In9J%sUsmWw7xQWh8nKqk;%}B;tr`A z^39(^>rg;zAy#9HAd3g7_u#-j5sgfy+fj^L+KZM!(=!~}|Ac&*^R4Jsm?68K79OvM z0gJ=mh}}B_PG4{1ji^RnbxR865KVFdij9pyn@uqz3(OL#rFg#`Va$&P5-R%Bhb z63&Q@qd&iC#_V|kqAPPJx1!=j0eyvo&7MSq_+lF+J~zS539b2;N~WVoBHd4JX@5q> zotfj0=1&+M5@A;w@-7*?jn5#$;O{2x zNESX?jbM63M#El(YbCN$>&64{v^6FR1+r>ndiWr$ZCfKpOZyC3skffXCT&HSsESkg zs1j&>w-=B?Hn2+C-8T6zzTe1it>C#CVv?Y;n$3_>Z>4UAlx|yQHbeYDQP6vcI$Y{) zl5Id)d^$Kh0Gsi$?6fZ5O`HhzWP8C~C_emE?mfhX>Qe7Ej*Vb}7(SLGL7XJWv!#Rm zIo)2T=;48>0#rI&8HVndLKH7G@NK@yb{7JKBEEvJoc``TR|G}E?t;~bckX9Po zREWf|YO#zYe!_FC6~)m=I3wSYGVn(4;Ax2AsWd4e+3}1F{+hc`a@vFaq0WCq@NRqo z5>8!@Kc;?KJGMizQ*qGdG1 zV{GF%6di=Fo7-+Y3g*jNo-Sww6T|E-#rn)~F>mrr^*KJ>2-jjo|2vv2V2?3@L7B1wef~m4VYuf(0+p4RWang!-ciV>FTPh8o;j!p-(gW{U`a_^|q;pX|r+FMV z#=gRMR1Y1+3!>zZN0LMn@WU=Njb1L)`c&Aj5!G%qh77%H9YqVVoP_Tp52SxPj|B zZ4bUKi=qjxI&{d^U_Q+E@WXEW?2;flkED2inCWvFlZkEe*NCP=HMLd78WC%uCIV^k zepfRTMkMi97!Cs)_5y5B?q*?`n~hjev2HX8G`YZE$Hr!u4a4k1M59e*YFN`lI4%b-1Zq-kAgZ#LzxCk7BfJNeZTLqVMa zsr%Byyn`hO2_pE%ZC~!tW$dBKm)V7H8MHwP%AfKaDcJ*D$?d17v3cb53ml~L=*Kz0kCRr@M!})jGmx=~Xr^96G^wM&oZo)i zO_r~+^ff#M2G0F(6H7lBzYc6ac2#um3E{y!gBFrAXyHSpc--|aMk{|b#hR!`qM>ce z?9BQ%NXXBRukE}ZLsvr+G#B;jP6Yblud@%%Qu*+i-ZGtdMtVm#(W2K`G6G7~Pm=U0 z*uCKV(@oAojNG!MyrxMWp$sCZmOaPZALlC*y;6XTAu)D~&LqR50Zas;A` z?ZLG&x?a4A7tK06kHTdGaB^`LC*iYgHJ7nV_*7KmHe?NY!jNSxla4Z_5WfV;AcjVX z!B_0bl5{ca+AyZ%%DG6}A+=m^vN zVkHIxwuJwXrNM6eDvliN@T7{rTBi2L442KG--e~Y7^aPo3)+h5{DF4zP*#4yu=ta` z&MTPd7yM_3hHnccH|?U1?LwS>J^I`|3=z2fmoZ@KEjXBZ?B6@L40H@%o*^4zUz^1O z*8jjg%e_3SB;5E1)alr!Rp0;(60$O=e0bLuOi!&uleG%mACbY545U(xhyde*mX#G? z-Ctkub4xDHhco&&I)=teqvR$|2TjxOkt(8l%b?%q!QJm*Hk=6=q>iFP*M;<-V$ur# zofpz?RXV7Sqjpcr9a{N}OEAlI&Q_19GXL<9|`gBd)omNlJW0q45=+dBsDvzjl6VA-# z@K(Vncz_&a0W|hv-U6&^6hUD)dOZ>Az>CZC0U-YxtYitXDUhB0(A2Rta~aIet#ElZCVyM56c z?xPgKT|6h7cOgvsMj2m-o{Aq)()Rl^Rzy3UFK+&11;UkjgUh@pd8P#SvXv#j3bjbA zWjIR8Xi9OlV#||UJmE+W18L0Op--H^&%!x-F14co;HXx=H2sb2ybda7x>BJG(Y@F(~*N6sKsfUk_)?1f0B z6gYq4vvEu{Bow*LgvBW)Tbf0T#jh{Ka%wrQK?vX~(dgdZyu|Xwa4*cSBZvD(3oe!y@pgTzxwHb-u zIp9e8W?|5j37llkW$0+8W*E0nPOKFzT*l8lBx8Sizn~`atuI`(gu*HHPEDPFzSFiB zkbfcMZ`v1~m^VMS0vSjfcgmr1ZC^ASEfsgh_F>G%@qpjLBwvet@HLuLa=w3sG#tt8 z*l0&%hRZnP^WhV6y-k+eKP=X0!a*5#;@lN{>EQCDU~E$y`rqRzzDy7qLjFXGIuh|O zp7Vu?@d`M}5;U&(Bxkq5R_Jv!%Ds2^H474f`Lu`?Z*a;bZs|JVCb-pATJ@ZfW>39X zGbvyGLWH?VFkZ{7=xu=RN>0{oM{udj0^(_?^x+sge-36WgAn{RuBU<()_z$E}-%>ll%M zHo?-*81bjB6+c>@yau5u)ba}|C#ona5O)v(G3ljSqhEP3EoP++gWJA-QyIXMr%g`V zi@(6wGx?m%Vjn_V0aJi*j(hXr;MrYYhRBoJ+(_=Y7|NE5wQgD-(!snI(b>#{3tW8* z1vULy5Y?pUb!@>_hule6MUp#CsjZV9)T%ZGo|`w4{S)!;`jNpe^h#N$rxQ6$`*rM% z(l&Zo1-Qe48ckWT$9foK*&*FE#P$-}l`>puKqgTp9a44k!snO9o?_Pni!eP{ANfX? zHt)Mg);I@a_sCu)RE$?fFgGS^um!&liDU(rrZRj?Y~w7nbUh*i{OaQ@=Ai{GAHzU+ zO%O+2&{5vk{sUcafP4`-tsK}tm5tw8hIU?rOyQ2eP!$;|Pkt#g3#>4ep&WK1Ovsbv zX)T8`j4Wqml}s6W2YL&3+;9Xc9+q z80aQeK#Nm<5miRIwu)Vbq2f@uvpwiHJ$@TGc4B$Pe;h>VME!jwWptsb4VcULwS#JpJG7HWmnWZMN1VDFZl$!~otlx_^bvMAg#Fp95hTXHMVDqkDhbBKF0muq5sdb=yf zLzux8GDcF-Vde8T)KO375lEv|(s*Z^gW98Wved(PbB#c_0$EfxBbPpZ=O)1utxbd<4F^H(B!?YY9qWzPW1G^FISjxsfk9II^ z=9qx*;&_K)5+>!8u-}>)CC(_VGCv;C4-?9^g^95U4Vi9dTV*@;nkVJ|Zg2w!BB^Uo-bjQC`lb|&U?dVgyNhX&4!{`W z`^c5DksIAu!G_*V-Ur3j+J*9TQs2W*>$YEoHa8=Iv?13pG%rz)OQAWiDf5#;KYu$| zljKvShztDPu6isqzr7mZE*r>N_#c0>^;ZW}<1)q+sr!+?$%&8LL<#snw~V;{;@7)= z_uA^#hdH|q5p}ELzn~67!{r7iKDlaYO*2$5QWdD@wja+?_(d zYV<<1df6Y4k8LtV*be#m3e+dniwv2i87%=_nwgF#H8V9z#{g;FH>!(V#rq;|DAQ2B z!ij3M36gbE8_^R!3B7Xe_ySe=onZ2{ASOpGgXTgsD))M52~IPnE{6Q=>zxdnb8xP6 z@MwLJQ{Llj%$b!%%XIJjPG@e8lRI0-4F?Q!P*3Nevw9Tf%!0p6+%M1RcWa-*-m~%= z4z4(;HFrmkojH8p^Q>;(_ayzEZs_Fa(Sr(m&B|@)S<$04r}KNCOmDWIHuDPWxkJy& ze3=w9#@*eUqJ8*Q>9LM|tCZmn#9uG}9aE-1JGZdstR4+H74T2~8Z-D~o-gQ>XYzE< zzsQqGC$mfrg#X!_s9Q34%q$a@=UL!e!uId-o+?BDYZd+Q`&Ilym*wohzoVf{qy_N( z4K!kdiSfM_O-KPSzgNI>A@C}EKZ<|Fz^(Y^peh9HVA!(+|H=TP_+E(VKi99L_&yd5 zPBkz$27ZWt4Zv&h9l#11XF2@-BUTVr0q?^1Yd9~r4tOWNzYCkAR^SGFpLvY(Ta53% z-+(*l`S?B!|2_dO#`hQaw+on0KQ2BVc|@L~_&%%v@AUu&@ck+Nal2y|zF+?q@&&vT z-^YI&c>ylO_nP5&?*@1+zI%*toLRv6_?|ZkyZ|@gd+k`f6-z((4o+|!HkB3lzUef) zM+CeI-(OAiuL3$9BM>})_#EiP_&x>;yE}jb_#OuVzE3*7Pdy(pCC2v)7l411!w!5; znu_#+EAV~)Y?KjjXxg-jlTHpa)?5{-X$sd=2jaoC|93np1TE zPej#JE(lc43D-0RnriB*DIw>)X=UZ|YeYa^V+-J|+Hg%}b)bHZkZbF%3=AzDJBBaL zhHILf$qO37OORZ{{3U@ojr9xQsc~UVqw}5m#wz+1eu_pF2_KAHQgNJVb89k~1Y7tO zjx^SRDx|L9NE7Rqp+e;PSyO=e@$Juwn{h(G&I)Fo?o+IRG{?AI`9d>gz=Cs^u_+h z>u>YvyCzUAxm0%MLi9C_qnv4zD#r597^mWbDbp_rTzKBO=S{izJZ3?DgMI)1+Q86S zkS8y0sHqA&MTLbUtLni=U8KgRO)%eqOh*L4|9zbD%K6Zk1(jjyPPnnM7LR;g8BjJx z1e)g6HZ%zLbb<6k^-bXk&LpIO%#NJ4q@gDLtE{H(%J5wIT?bxJFcX|{1o)z7O%EK)wDb4HfK+nm~(>XB3NhH{Mq%7t|cvT0?NO=0WLDXm*r zIls0#Fs-zF@9NHIauOUOqn{(skm^O zbN1wE&V^9vkwHAQ9L|7@&AHsUOeCOU5ROG4aN~cBjq>q-P8eDZ3Lign=HTCHVMyzA z|7&QKb0#8O5SbsY#XEW7lUN8N<=L<wS%R~dNDT}WjVkO$_5nX8u$5Va_J@{Wr=Q3U>p#MLhdO|U1Z@X(0`f9dx=WD4 zzJ0n004duLe!Gy#$Akc0)00X8-8pIT$VH15jTE`yvAP=SPYt;kx)^^ne#Fs6{h-<5WLqetlKt{JAJRr)c!4qYCj~k#pIE2}PIt9wr2QelI|S)L2_Z zS=UFxSJqPyRT4*2pgK|$2-o|SC(u-TbksKAChAc{tN!Bmr3=J`PDw-HS_$=L*ggBz7EYl zx)ao?bl;%;0h&SdAq|nRGX5PtU0yk#ewRQ{3mWFvgliC36&Olw8$h5K>0uqnxR=sFQ4!E43n>TsX#Z<%|e8(->gu&K8v!pGw;(pUqXNOq zBw6umudD;d9P>h=etnft5wt6d=2E@tYObsg*CP99&?%L`Fq4HdG5mMVMjJ7v=v3eH zqRLwFh~5be1;$mHUm3{;X4insR?7~eN2s>=9jDbV9r31C@&^mzc^}R6S~FQT5QOp(o>yC0;iAS9@h^fw{cA!u9T+w=GHPh`a0WB+FhJQ73Q{KrEE%@KjSEQ=%^xk1;!k;Hgyg^7P9I_}}!;PgMTOpW-x3qq8SXnh+Rv zLCwMDT+mTKR|uL5q-pSotnzmqkf!l7pqb+Dk3eS& znt-*RS%O{xsuc7A5ap2T^g77Ucn%rM9iSBgX^t)dQh&8Twc&2bxrk zdALP|7F`IWsnr72N*dP#eOJ&bAmxu|N;H;dfHcGxmNufl;qN>k^*7t1T8pl>C=R6M zyV26NShN>NC3*B=CcX-b<^atS{_eE2do9`yr2M@Pq&eCRq&ez2z~qR>>6FuxEE)r( zVXw5bB|xehKeV(bfK)Djv*@CMCceups8Z^`Ag0p|fzk zk%m|Rq_O-2Nc}wsr2g^`#~b95#&Dnof`UMGg029n7t{o#@vQ*TSXKdP%x_xPkw@tI zajr8C=qd@j3aC-gi$G0++`%yX6jTVLZCwl~BDBYWE*A7LP=lZ~=*89FV?Y|qKA?-l zH5ZNhLP4W|771Div{=wBK+5wSKud(S73e}i?*VBnpId)>EgE>V341co)e>Sk&@4d@ z0;ya!0nHZLZtFT6E8$8T3#58=2axjeV<4@0>n-gWi*{SI7f5-Yg4J^kdyz$#TeKW# zx^S=-NYh;pbdAuSw`eui-qrOrAmu*in`A*723BfssYmYz6+$S-qk?O;;#irOXdea8ukGojrmFI`d1*0r2}Y= zgzfQd6ZSNVt^iU!co0ZKv;t`eXPBY&0=hwBITNT#P}I6Ew`iqB_gHj4(3KM6F-v>O zqE{_?)B5W>+(`0dAm!?8i^_mBzWG4467#h{F+oY7*@99)sxP@Gm{^7Z#l>|RP(o0> zMG5QgMj*}Q-PZMKi+%^ROv3&NXt|)Tfc(@>G;%HhQrAm?G#@j8H0DK?wiIZE#PS26 zq@ZW4>uW$-FH=AoUk&!*G`Q7(!Kzi zCS3JD#iVv5kfwGqkj8wkb$u8}Lwss!{|Tfa4j*gKsX$s<6M?jcI2%ao;0&NzN%txs z4SS7vE+CEXVW6wTbrX=L_KHRAKpJA7 zMLotD35@{Ku%`iO*mEp8A4tPqWzj;Q>5>`_m&r^z*V$sx?|?MK;PD0pfRxjdEbTOl zCIM+_U14ceK-xAnTH4h>H%PikOIvMeTY%Px>zfvRX8jGHV0ak?q}-1K(hzr8*SmqV z6dnXRN8)Ry+86a6W?(_8lnhDLxikrIgo~^vb4FDcD1F&EbY%g-;;EEPc*0j z=r*A}1*Fp50;JmcrltMC(mu1aFD&hx(@oeZKq`Y4OS{$5?gF|O0 zzqGWT#U@=BNYl6)NI6{!r13pwUH@iXzXVdA`vpyi0YDmJ4A318$E=rF*GeD_vDwmI zu(bCrtv`}i4odK~SYoLFxZi{jznfMO3=nRV@7Tsr2{}K~o zB#@@Dda|MYz@o=2+5n{b(qU;|0;x2P{*DP-XwhVgrdae{i>|WhMxY-^F7E-lOwdEt zb*DvNTXfLbM$QF55CckKIFRx(1xRDL%(~78nj`-1u(Ss)deWk;KwG1X?TpuClI6tn2qJ?Ji6E zBam`>90nlD)o>t+dSq%r$G>U*U z#8gYW%+l@#S}S4K162q*a*7Fi9FT^+7)ZIV1Jd${Sbx_6DW`W>*R|GloppT^=srnf zkM(yP5>?$e8OSd!AZ@8DmjkCd&QB$llYx}KaX`x7gFyF->wf?(5wsuZDnWhVsX@?1K(&JA0jW%H zvaUTZG%;Taq#KAdTfQOKS(x8r9?q&X@9 z(paWj+8sd3-+Jr12}n8Uu(TetOe{lzG?tM-%FCrdw>y-^jn?&6>v|WErttvK&m8(| z2hv#n2Bfj<142^{*JCSKRw6xoRR2p{!sWg5Mr1j%-AeF|q zW}BEt0ck8DOPdCy{%*0f+pIrcMg-LYr+@o~ne7~Yf*Da9Ji(OA3bcCKA{~Mj=_e8b zf1Gjn*At-)$^$w>Xop%_zC{DA>tIVe#-f0AEwHp<7LBm3g_btPBJ!c>PPDXQi%P6( z$kNcw_}o`mSISOvG~FVoy&v-|ORKhMu63PnX)Gy?C2U<6TiUf2MXhVx(pFe>lXYEX zX=^OH-MZdsX=^RI&$_O&vlXq+cmX9i^f>jah5jGqGIb>VrjI7*I3G|YlWpvvuL_?ondLSEULDyb1iMYMGe+9 zY-x)vy4JczEiG=*3hR24rLD4Pjdi`<((bfqt#!T6($-n@fOUPu(jK>HgLQq{(poKg z&bn^5w3jW~VO?kS)s`^FnF~ZY=Qs@(Ew*TdMXM}YYtcH3oPH+0JRprP-=e`54YMd@ z5fXQPE*ud3!Xnl~FpSTG7CmIq!xpiYs=r@a^cNt0a-4wEQyrC%@%IbheB(#xa=kQ= zi+??H^2ALX@TZ3lh9EZ9V~JU4V?YVuUz!pm1p(5OX`rk{4?;>0r>Uu`vJR6po@hz? zse+%@EXq}&@B>jDke?*|^fEEi_gYY*S(GRIcu-sijOPu8Iw&)qKl`B$`6r=z_+mNq zpZMYZf;@ktd51@53@AK>lct4$oS#XV0SeC{ zr9;gFg=TU}85OQs9A>8Qq008mxqr6fJnNU2keyL-#z8S1x@!|g&2HkvK|T~yw|*9< zBLWlfQ<#+w1CMG*`$08?pWlM52%YR_RAbr?DjodnKqY5A&;BfDBKRDPe?4{^DU?E)7ARDd>i{XVKp`mzeIXf|;t5P3LXo0ClIGD?+B7CJwB?~wW~S{p3`9Z1 z>*H1dMMQ5EENQ`#K4{8AtUQY-R<3$GH-JU3@{)W%pSAYc=bW4r^mq0C^*in4th4so zd#}Cr`?c1G4TdF3F;jqH|H5=BW;SWSjEA|z_yXS0v|3EeV3vh2#SrH95Qa8Y^l`(X z9tRJzxOH)J$8tZ0@UH_j#Qb*%^Vbk&G!rC`8`p7<{Kf*x)A2)AAW zLzwFW7?z*K9exf`FBUJst%4xW{~qu~x9^28_k}Q<0vN=F|0ZDc%i1P98K9x-e}yn_ zgfRQD;gQD;ClQRGneIbOoIfS`AgjpNHYz|>w3}L9_&5NDwbGT(2&2CB_ zR~jD;VX7=9V#-)`2yBqzS;#( z?rd%ANOqnqAuL|FxV3>7)P{6jdSwf4R+u1y{%{L+!H_P^sAjm|JG5I{XKU-wE{l27 zrFlpw z*|>3|9-3NO8k$qMBed8^&4*8-G$ZO3Tu{O_mZ1c*c%S7~%et3@#jUtyk2_PWXTr|n z*3S9hRW8i<*+dFDo8-o{M>|NA$tHMB`ofY+U>-R?MS?@JY^$i}!Q8s_g(z1#{oit@ z(}!qVhz@WmuCcW$5>l1h>3X@?BlIAXRv)4(*_2Fm;g-A!L*&A1XFeKMAc@9`$|Opg zAYa?#*55$GqLtlGWm^V6(w1*O(zGrwH=}*1NJGQI z#T^X|ENrKrrYV;Y7Pc=;@;I*gRINg`~+-SRdiK=R$zr~#TR=AnJN zlFgFP(FcCX&LyTvS=ipT#CW9G{Y_M=T{E_!c~NUqJKAFjp=Eh{gGfmeiiUFvT1+=P zB^5&NC4)Y2w+*GYpJDRYt1PV!9QsnH6zy6Yc`HCrz4-FV!KT0nGz1r=Qkf3bptli_j3# zWM#%y&5K%EzlB|bX|VSKH8j^vV;JnJO`$(_3JYDUdgccwC?Y3c#cOGumogdJF~745 z7gsM9g$B5F4$TtAGn$JAy*AvSEvyD37i--Dq9_&$^j!^0+T}vN7dMNe_l0KDutL7@ zWn^f+lyLrH7V3zKx~ttUYt;I#WP?@Qp)`tw;sV|-RbdMmi&z6X7Y)@AB}kVoUZfzq1!tBN95$jIP~C!#$Tm!#i@)ZG zXRlEU3m7`9tbS`N&Cvm+;-^XB;{G5i%FIWG{9oAKz!A>8CQve2 z%Nn|tAl+AMK#N;3;*mxOCBXD}k{~w9Xn3I01@*_*ftkigeJhdC1%Z+_zY}@{)QJhc zn5#$T8yz+@5crx2lPr`Wm#t)HatUs;nkP^8itsHiNbL0f>wraXk z3z06jA77O0x~kbY3;8_Ud~9hj4H}xD26RKN@H&%S9ZGA47vjU@S&dPU;N@ELqJ_Be z-Qcf{X#HgLVq00se;E=>SiW(A_9lXLN4fgpHL1=1ahlt~iLg&za!SlRl`ep{!ut30 z(@qnYDW^`YJYAs1Q7tQVNdK&(C$qWt>tAc+_`h;;B*Oib8mx};8Ne?Vsc-bJH;Tg$ zf2t$(z5X@FAxH$3CY^8Hk;t8h^WBq!KB^;?)&8|dx^i#o>B>lCdX3UH<0W*y^+&o? zWBsCW3UoUmt$esIQXOfmKIJs|w0{s(WX&}DDFD(@eKLB$=A>Odh%mYxA-c-mQ>s1| z@XUA)gY0@tykIv{J*FP*GuP<}j<0oJKO3CDrn@|m^y9aJ5fpdldGxq)`$nV(FKqdAP^cnA7;M>(0T z)t}j-wljK1Li=C;D^R1ya9o{^&a2>OQ0ehQfs- zB{-w!KOpZxHpJ)F6go#z*>W$^=H#EN$^W@F|9B$*a9#cvDvSI!NH&_SkhI;#w24XV z6R{$l{=z}98+Rm7h0ICd5_Gw(2&XnPuzzawit8fN(MrJ}6#cB&!u9z&T05l4DwEu3 z?s3qoQ7B~8mxKw=kz0$j$+w;Fpub!E{`lbqn!1KI5qAe0LZAU@REW&1>C_^Mn6wfY$Q3S!{%YRvVN3=FaR$Mon^BS0T z#y5-#WgZl%50B=!vj_#nv!UL7NBZppqN`p5|3F+^mf2ldJa-4x@~`?0aK-X;an9L0 zNIR_PDE?vM5BqXWF;TyxCSO=aK8lMfDmTQyCJfbb{ol3bp!VUUe0Ww{?g2Zd@K~dz zIq~Eb6KbE{M=_yI(s&Oyk&tc0LH_C)cCe^Kv#&rw=iuT}+6knoUoL%dGAOnnP@j}FXQXuK+p}!)4($~@6 z!o!h3z&w!nDLn(6#23FfKF8S2gXNfC}UX@bVF3=&sK0zLj+6)BkJH{hr^6wB3epfYMoz z7i^$>%9p~*=-4Fe`4;Y|=!OTH^rXj{{N@^1ZO;E(yt~HTzQrI5Yc+j)quJl%8-@#e z!4xc7ZpRBXrEc2Ry68DuYlq+114LVGw0%ci{$bdCQWKJ|$D>Pbqz?k(wJrM26K&C_ zx3xvLZ66kojulrYlQ9BXB?5A0{D(A~Gdv+`WviR^ht3m?YYGyKjzMzJdRBU^CpzCW zIE{d`>qY8*Pn5k^>xRfH|d*N6J3`-9K&3v5FhUpzRzs0DXic+e!RC- z9?$#^#%*BIW;HX$$v+0uJ$J#aX2yyg;39Q+blnQ7ZSLJ&4g)7OQ(^4mb|e)w2!?kL zaSC77e*4Mfeue8w2Az3nj968w zdUCaVL$AGXP>_0p)@D0s-D>n9wh@`FQz_6A7=h^vV?)8ky5+=~_9c3Z=IT*h`nPx6 z)*vP$r!TK&j^%&B>@VD&mXGu1I)(EZYbQPJ48LeuU4EA-3^Gnx{a+xdowhZ3fiwJG z^{cPKMU6~p5qXi{#a#jQ%!zL=D*8Q$5jnv z{tMdfpMrnZ=SCS1EpuzMoBqAm??EqGo#JSA50VADoV9(uOo`LCnJ-t4Yws#g{phZ; z}mBX?N_@)Gg0GFY0SszK0=@M-$qgh;84+2=16!UiT8FYT-T>2^A zy0e^($8ONVlw%`se0I~6Bl2?f4A53luejJZn~X0ne~OpUe6zM+ucH;LL`Y6?4$V0~ zkMCqfb#$z2RMbIrXwL0GJ%9zQ=#8(Su)vlfhv#VQOh2680+TSBrk>OCVtT5Fi>8Br?I4T7@<%Y4+vk)WQljqihZG zur`Y!`{VH$X;$y#a#nd%D`(P|I!MyDieG#n{x4`R$*;msSvWKA?H|p49C4%d%#Fmm zkTb*i?5{xN6u&u_ZH5sdaxisiU#=S{kg|<26LXKt&a7`3oiU}2nnUC2( z58%YKKS#4m2$)0~nneCyIu|l5M~O)fJNX~<0-CmpMJ<};kv#+hJBDZt3K@>Jm?4KC zX0fw_-ty0oIEsYhwjl8<;ti$QGLozTe}$XV@I(vY*hwP006q}WE*V$9hV+w!4?vRf*}WbXM9AU_iUV!NAYRa-2_HB4rrpup zw@}BNLJ;>w;M90-bu@bsf@f|rimKlJ@0iII|wRT!xG!sX3F2Xr6W89r-yJ3FA$Yi*|!hG9ipP)#Jl$OS# zOq+O|%tLHC5rgEX$wr82J81btbKCJZQCL+EG8$xSsff7^@@oTMm9|gafUjZjDemo9cEI$l2bhxMti;e=s%4usxm<`QF0KQl?kvI1+HKzN0z z|6$WlW@c7=GMc*{ks?)^g-G-9ATCW6v1Z`}j!Zbo2ZMaODY}s!&hYZVHx$EzYe5+R5LzgP!ugOXP24>mm%B zUW#50gcmf@Fr~4(8n#D#F0ax1i5uz3$^1;4u)dWHjSu>5y6}l+&k-6OkE@*(Cphe2 zqk)QAjR7fEj2@-oGso>3U>k#sR3Z#Yl*4!@QNWw!J#t?0pog4IzZ;H;D9lzmwPyV) z4r=z{bvcw;_)5k#-?6ST0_!Vjr|i+%V)?e$qn|%}4E~%uGJ5#gvFPFFj*r9A;It1+|Qk(l;&=ffr|Wf+X5B{Z&wVeyi}*RTBw-IPB@_63fnQLH$^=0fHi zu3=7f2lf(uM8pCRgBvLf4${#ZV;r@M5-*PUA&erj z94??exklR8#H|-O#c`}h$cx(i^Rx4B z3iCDjjZ)IYyvpuLu#>_J`W+cC1tE2WQz-fy-0aukivHb{Q4?$FFQ^mJZfFlKR*6e! z!R>fddXvAx8j9P_1%u6f7Xb{4D)(jJba82Rel~=o1Arp1Z5VG*1dvw@{6tD`NKKRe z!Ow28w{#Kev?Mm(^I=f--)Gv59vP5-H=f@CnV{m*D4C&?LBtKg`CdBzHJr{I)3;(g zODpoqzZ?#Er1R(F1RC6Tj~vpS7HeUOm8GmN&G7)AzVtFcU=V}xv@~--0%V2e)0bwA z=L2Mq2d*_>bZoj8ASxUNZp*+J*B-T>v^IUK9>JVJ5{6~FJ3%cy{qu=}GZOiOsk6-U zy0M~}Jk=?bu{umxG4+Qpyx0rFk%iS#Eqa|9Us?mNT?Zlww=s-D`3{W-`vQ{hzVR(e z=2Nmjs*5F6GPz%gM6CF@1bZzfw@cI0BgxM6^y#Vn(pQ&7lJlM7d1Yc6RCom&sX0zz z9iw;Kk3`|SWCAv`V8k_fdZO?nvQo9Tws7rV(B5E@@jR>?i+A|mFFo^=>B)&sW?NZe z+8VwK*Hw`J)rIvaGy1+lI+S1l-7=_VVO8hx*MJ$PR*jWe7gt^c4$jq5osQ)$s z%J!!2jTgQm!}}*wcd_3$D~)kemu-Wd{Gu+!XHlenL6iFVf?Qv}(rwz+N*w*PQL#(wkgrf5g zwS^*`i0Ts}c#8lO{{Y#?Wo3#51}nW4#pGP4cq7Y_DL*TPE9As+oSznM)%X&d-$ckr zfViSJMyE?K^&2c9n0T4;N(_Yf$p@`5ONM|L7F0?E@yx(5?i7}2m9aZ+=i<4)!sZ`7 zm%+0P%r8f-!6GYcpI>!2maEA*0|Q7BRH}j6;?Kyp-CxsvGIu^4&3zalxbx%M!dH4h zTYF-z9xu+}rlCiB3UiO0ZBDfPF)S+UXtZ{?P(Yg7NuS?YJG|Ht8tpo zZlU9FO669yx27;_qG{1aLJ-1@ZO)>($p{hV2QlkFD5a0$i}{BtSg9E>t|Y0@RQ9jc zco=@QgygW{kk-OMLCGBl+4Vo#Erk;C(zY-Aj>3&>-JHS(W-Q7!f{c#6o&iW8=unyp z7fm!H6k5Gj=2?fIpvU4(%rRecRlI3#08!e5=`EL6bw@>6vqC8C#Q;WK4?*QNj0cPJ zrTZw($IE*4KdC&In!yM&1bkM46SoyFT@1W$NaS1ZHLD+mh2ydEfz4Jay7{L~3T5xr zq{rPmO=9^(cQOmO@Pa{!}GhMyAA*?+GnYhmQimry-1PoRkQwO^%A*o3il1y;&Qid@kjIU?QYgP`~ zJzZzRKuf`bPnHjHCQ0E(%Rm&L+>@Vo3kjAUCD|xCpLY6ktQ~y%Wa>=_qXM26;9_-K zcVCXI@u8W;Y%^Mc(jxrv`d4pUTj~^tG^xF*JQu;;-0Ht^(0FC4!)woY${?CgBcn2D zM3*Su&c!CIZSc#<-%ybT3C4?Rw>TEf{srH0TJ(*?ABy4c&&J~qU#k6w5xkDQy&&Jc$3_x2)W zEiPEph3Iem4*Y=MiNJF@DJHaI?sP|1b-NOnRmGfwvX5bIkp&lvgLs*e2lxCIJ1gp2 znS?Yb5ZOPH?GBCwW%jD&Fusx8#vfvOsi8XZ&`A6-D>XF;-oz&1_xE%oy19%s|JnnT zi-}e_Qkq+QwWqCH&!3>Tx}Ig14K~iZKpbe+PJ(}6ouI&FJ$6ecSf z*|kGjR?6U{@W50E#>w>TVzjAxw_8A|I}H8qNuCc=zhD9uD~D(Pfpfj&NJhtrkmoJ= zNJb2@59{xhcBL;ZA%mtM(_)trp>R}jlB27_yWc^Gt{Xzm^nWFgUU$FD(bht10g5q( znX<5ky&{x5th9Sgs6c2>*p3=`uA-rHbloDezKqKm3giwZ9}h~3bZX734#H>%4m&-E zUVzx$VMFf?V==j=fU$9q?1ZqH2hOxdlWlvizX5b*PINXlqBl~=2zwnH(b9HVX%W5S2^MHsoa^^Ar>mREp`j+HGEZx!C`lbbRsJ1iI)=Vfn& z^&s0z4p;$17VLPo6N949wtCU8%rw_UoQK)Gk(yGR@Vh~XX}bm?mc1|tv1%}4@AH;o z4x^Pl7OdEN5#_fidoM(@&$3G^j@wVlw~>@tH09xgn_cV#t4WF8rH_(kUzT|b>B9fZbRw# zo6b|oilgVz68QpK(0E_Ag6y+~NruR7UNrX=@~MBM@&j&AGjZMaah=9Dou*qg2>u(1QI^Gph5uqtECW{ zWmz7bimwL-nZx!yF1^@>kpN4V!cE6ha)?ltG4-fT>0ktjMl=gDO69G14~2xlV?No? zu0f=jiE&96-(;`7^E0Hik~5AjKXJ@A+;m}Ou~+$UPT=P#w%$JrsQ zg5X3Q$7SvU0p;jlAmBc?Q}}8RmtymCN6JPN>3MQw72Wc`WWFT|@sUp9fZF_RJmr8; zQ?HP8aIxZ zxhdnYb4zVL&2amlHGI40b)3RvP5u-8rz-!KLY|xylYHP}7*-DjSlFnt9!Pbepb5L+ z6bC<663^Ys3u_A!9r#Th+CN3+-{{;naU~G!?r>&w2>)0MLME}}b@F5B?yh5}ziVQZ zAcaG-Q0I>7q_OoEn9o6!Si?~1p}-Wi?4SyKNaC*@nf|uP7o4;iMd2b}(C$k%n`D+w zL@2fSZiZ62QZgsY*ijT^EjQD%7L{kTHg{XBh41ceHe<%Fccr|ilvM_7b(b5P&-=2m zjp0kkW;X3ZFBlfKWjzx1ug~_`mge_hd)QNa_OQnu5E;8*zsNx^4YGgDIOh$*?aNL# z@h=Tw8=UF(|Mv6QAt!#Qbd5VOGH$_$$e7JTgg4msIpdu-1l|6yr+%SY4HtXl{`Aw& zP+`-LYlGbnyY{{Z%N6|dVXw`HO;jE~w8o-|y$^4UPer@Yry+#H05{^@ge%D6wAn3 zynl-ykCg1f`@`rY4+9*-`!D#72ORkjlqSX07WWvu*B*^J0X*Ncj)m4i!1Z{aS^<6m zSL6M;X}rHRN$*xr1J5T;fW|-4<9+3cYJa-}@8|KOj;>vJk3_Sy6)-jbPr&bK zz(bgbogy~&U`7(R(P%pG{EHI_*9hu#UWtQI=Ohhp!Z2oJ&XOgu#ZB$YVG;KtrvV0< z>uN8WZLG`D)+>!uPdNF6E?Bz6U)bQ}xp*A5cHh${q(+Ouxl^XZA~CwhXq;ItR-ZCu zdW?4?Vd4)4|C(`;u@g3{aWj)Qy~M~i?)K5H_k>hr!4zEYTGHIwg_}icqZjw5aMN#k ztbM+@5d}9~3vR&Oe%xqmzG~tm80|A=xF=lQLPqge>eRf&3zH2r01ZOrg2q56!roti z&V7Y<}h0%RWK;apkotZLlJ3_@Q3sl^m7ty2f`wpT3p0E zE3wK5vz&{pF+$fyC2UGBYJov$N{iNe!Gf4;baNl#fB{M*RSXoG{AVgr9$^a*Sz`sg z5B^;?jNwPxvxQy5*3Lz03Q@8t;sv4!VfYt|4f2aLA8TtMhZN+{)U`aeKgdzVQguxIlaOJy(^MhD3R^|5J{Y8$nKkmB9&^KGKo_~8d+!paH2<4t zhw<#b-LTy6ZWm$R?05Z7Jw7n{WA_;;13)(Y?%n9u|2L1zhx>NJa=*J>gn19epYTR^ zGCJt_M{RV*CZj!oQQ_&wH1l3^N2+Uq-dt^%x4gY+aqBVfOORT8%%J%Hp3fwRPQ$NU zMnPu^v<82n77w`Z;qP>T4nRWB66iyKss-ZF*tkFo0G%xmb%QE2au`||!5sxiC!A zc&_@juG}S8p66TWTI-s%xE}+m5x^$|eI{S$yRKc2C!Z(G-4DEsOf2XwZCmj$F;-3F*maL)qL@LmLTzTl49-}SK& z&;^294@muf0wZJ%Zyg|Y{mKCtJqq1#0ew=SIT(qt(I}668PFVoo&j{RKraE(@^U0< zwQAa)VxbEFT_SXs0#g230BMST1!%6gz6$74ftF+7|7n4~2Iw;a{R|M#5|u}O1L#75 zUInBfb17Rx9zNO)`A|UWdK4gaooHP*0=is6slbSz7Y55CGXXUSG!IatKq){?0(}*b zhVmbPl>4=S=85Ze>-ux+`g=esjjv!f(JXWm#<+5({Z5tN9e`ARhhXbVxjNQD(*P-d zwBMoRV`_q@{QZAdT&pfX)}!GR&4P7U)Po8t+_-TLehcyVgP*0cmW%1Ek^o z5s-%W&=Icw^lgCD^-9d1G`GG0=(7^r-GHtX=pxLiv}Au1P(pBb0Me8{3}}(yc3S8! zfHdU40n&I+Khm|;c^;sd;^R6%?E)R~Vb^NsDS*`P1%Nul^$Lsoyu}qQj`l2-t`E@X z#K&`hIt6+WkV^Me3my3p*OoxSLbPI;6d(U~6n3lxx(<-?k^`hI+*bfyF0LB^X=!>9 zkd~%t|K^sQ1R&+$Q-CzQMSxU(U4T@6-vFd>+yO{swGNQ_cn8o`65F94b=#(s0IAf@ zv`_+&hVn^3XNr%{0MbxCYh9NB(l~Aar0IRby1r{&PmQ^*XIbb{Kq|?<0@8GxezeQg zYCzhSdHvqa?pgRFwBhWfP*9z1J=sJOR0{Xl_B|u*g=xso0fet**wNv>~K-UZIL_isV zrUO#0&IY71I2TY-T$`=ymDaWOcsCaw1e6uJ7Xjr2;sTI{HxiJhXeFSP;(8aLI)NUt zbbXfYJwRFmK7zTnhEf4Yxtak;`;XbywcffmTi3KTBlSF76F0%zX!%Jl?wf#=?)3xQ^85nY$y${V{vsf(w3S&9%^F*0s^%S}e4{x-PP~4hto%E9&b^V6L zt+CJ@*7YunyT?Lnt?PXj*JGgvt!uBvZMD#L>-xCG?Xb|()^(@F{n|pitn2SBZnuSA zwyt|D?hOmQXpI4|a(z@?xjL%QN33hi;wmgO(Yl^w zag`Q2&ALvtxS1BJwyrf6$JJMjH(_1tEpCp5xH79Ly3FDlE!1LNIcL)F7FmcZx#~A* zamy@pt#wUXT-HLXtt-!1oCcYe$tw6NfyM*J5?U6i2E=%AQprMdE!1eC4hyXTq~Wav zq~URYT*KRC>2_P_O$$Z#cVnYwWsMh+%ep=o#`8t|6e?J#i4J(mA~9$cS9tK>4j{(3 zG~&qqr#pbTN$}Vez|~UI$FHSp1YCxf-2j^AAdOE$m&mZJ5;dGPGWc*kh7TMO&Pf9M z|M)d?p(21L?svBEA`=elGSiPyroo_U7|bmOgX&{2-#3^@#4X|Xg)rMgnEwi4Mp0Dq zxZz9Zn_=`VRi*DNCnlA z`g{S??iEcp9QIxMxR}FOt>tks69X7o$;N7SkmmFN4c%siF!do!QwVca2$KzAZVF+( z8^UZ4Vg4Axyc@zC$>vHPH|^(yFxP}IKMi4C4q+M>@;JLXOTV_j!*7WXb&m2k(cC#qi zlx=HIEh=~2y)WJ8Z&}!7HpN_4g7Hf@N{UT$DvgieRKUE}`OvrO>Wl@#=o1~16{F-6 zRH#BYfB+@SOS)Pa4Aa}tydc$nrJON{$amM0RA;lQ+4nI^eXQi~o7j7|}q zzu2V)v&y>ejtApc7oKe}L_w|WQ*a^zM;c_?+^+>zusm0RJyAa%pC7EdTI0M5s(6Rk z&q^&G3X5GXimI&>fJ$jdA)9g{&AP_oX{vTp`ngmqv=W=WPCxG?g?ynH7dz4#ginPx zMDJ?lS2?P(?pYz31$gewW*PkX;p{o zS5UjPsrRxStD%8czuIz}YCUcMRr)41p@i~afl25f)>T`(8xoXj%Q>osu8!7bshM6- z=IoK7@bLcj!VSl5MBHOdA!=zgkVRToD3PU53q9Do|A0r zl(XSPQngKz8b&`jU~-kI2~;KCvaropz`P?>UXF1{BEFfip6+x{M|wbIv&)Lse~MWc za?!3Vps+rLwuOzaO(;~nx8d99B=6{IO|`(}1rls6OBkH=4>m-T-zq&D7}`6YC9~gd z#J$fhoA-ab{15mv)mb|Ef52N{NbwK&(?a?8dKfe! z3W-5Ap1*$<1e$y;@wWI54v<+8Iye=|UiY|{mNiya5Av&$_jgC`=ue85c4*T3$#AMm z^ru(GyhmaE>uOFvwX$-GQc!cc4(6Z6$onHQ(hX})@4(EME646k=}6GU{tq;##}Lmq z?Ce#Ti&PJxIlTf-4}$LZW?sT!ywLg9W$2r0o4Y{waWl)nk|5})!JMw%QwfmkyZ(oC z8@Q(96l%wBi_gT(rA@p%)3+jxYvQCV@sIB=88o|I64336yH-uO5BrPSKFAUQ<)2OD zw?L`u-W7*oB`1~~y?4b{xQv8mPOR!Aij%n@0mY=rDRJD-nwoiY|E2Hbduy9(a<~V( zdtg_0`s1TgEpcjyV8WeDKkmqHgI<*vQcpnt*ah9ub^Fy7@2eo2Ge_&qv6-Wy**g(Q zyoWqML5q7!9#Z`VxU|s!G;Tc9 z;!atmGwm@adj4a(;S*Pwwnf*iVk+;7rOw#9N|Kp68FzMZk?O8$sFX$!xN^e5fo)~LSND>9Fzj)2Zjs3+fW41HU% zrY> zx#00GUu&(eMHDe@~#AtYHh5s*_nPcJUk;(BCd4+`->X$h&5=lP9rD)=UgW&65?0yjR# z>Pz;@UPYB)Hc<~N+ibSyye05B0=f&o)9{PoSB~FyxZQ(aHS*(v^W=iUA{fWPS@>lb z>@_dMv?$h|T09R^R(Wa{Eoz+)+>*}NVpuNX!CgOT7l(fB&8?BTrbQe*;i$O`cu3a< zlRYgsZ`6cy{1_}_1T}e(+XXnGzoadO!TFL-93NQ(-pAv25`NYA&B1R0emsBpkDerD z1{{oEd4#*U*zy7NF{J-6fjR-PGL?&raG(kh&(~tR22c_ZwrK!;5s-%RWk4FrcdRS- zPq29dx<>%9cPx)Q0|Z<7{9ZQqa#jGp8^~dlO zI>TN{@vev{0{wwpxhgSbaQhApqR&lSg)ykjq0o#{yZ2 zpU?=w8TiZEqnPks6l)dp&3pcJdr>hj5(9Vv-@uiV)^2AspmpZ%nTUCY$klOYe9 zf(lOR{RYtj(|X~Zv}$QiM*V76?e7}(Px;tXHJ23Qs9#IX6cmx8MTX%~{~EMl9HqR= z>V=1G!oOtHKWLO*jd(s{;shuUN8kS4S|U%v@3IhG*sc=m$ZF8JyJt)}X9q)#`tJ#a zhuOgpc94Dzx_@K!!UGZQ(+<+hpqn^|&b^ObTrm<2HKq~UM`NQCYWDh^Xw9a$44KRj z4`Veazil^T!T9`~=(-E`b3dl>!zniGmwhC4v?^LO_uxw;$0$6y?mP@Ex0GccN&eRO zO7-_Y-QC0EbKaf#!TK)dCi2;ewIG3_!TdAO7)!myJS_x$Dm*gb6n^aBl_>t0>?exf z--S*lQCvTli7DjyW$#jBAR{xA+zYjRv&mKjNrbJ1y?E`Z&3rtfdaL7mKLIs{Id0J# zuShsmlE8Wc6t2aHhvEk(0X5rD`S>fU_`z6hDv{L*sK-%u_Yhf0{aZ0fF9Pvt;=!!w zk{oP3jTlKbisQ(b=)Hj6l^syW!s4yoFng)4%|i{SdnLR!a~&iqLtzOOhT*#%Rc<(o44P58 z4E_Hb&eY}%?HHrkl220AlSV$dU2uMYV+}Dw(p~jr=`$F^+VIqV6;!|%^W;F&SS(24 z;{|;wFTVTaH4EosyC4z~BfOL4S}Ja+#`Q+))lD=SJ3XdEa-$9r2cE#)bBsGLP57(hMH+Nc98eLKWgXQi#J^(%M=2_f-wLsat1DBjIL4$<%(?=IaP$Z^ z@x<^`NUN|J9VvO z21Ds7<~4(fAP*JeiPgo7wt{vsQ$mDdC z6u-9yf_IAl$ve1luI+mZ!lm8hjhc@{Ta?uVE_&}UYOO1;EnZ%Z8N(SEpB83ANiejB zZ-tl4o6u&;&Vh@`oK$1DPQLr^Z^J6Toku+GhTor_5lL3G~!9T|CCy5JuoJ2NeU=Ry7*maa>u*qFzg#++}^rq%^OgMMN66; zq5%+ytzt(DQznr^VLzGui2gsx{scmY;n~z#j@sHvRMaC|5_vTgs79-J%LAcE0GRcx z*vixfCO%j-XQ3KFLgXZZSj0IQ!y%s&iJVI)rh(8_)(_nv@pg<_M^5vw=dysss}cIS zEOj);eI}>CVKa7`>LLS&=9q15_+*M2Yoj$!W1_Se-{OgCDjPYU8#vTV};m6d)B%5Ix@6#8r{(`E$x_eq2HOGDBa;g`l%BMn#t8d4z1aeYvoMUg01 zA6EW#N_j9oe4Cmm@4oq@uYwh%KxT%RPo6&~Q5WH#7{?*h@R4llgnk{x@u)}Ff~G55 z;qY15r3T(S;>C03F{~7{hfG|EEd? zo%R6I8Q~*Rgd8kNg!-g+Rkl zE++_d1fb&tng~c|&u0MAI6h&a1fb)E?rMwsB_Q?j1|SW21aeKGF@Q9V34k3_gGFy!zGwGJOkLw~6;lYapoDbFv|*Lydk-~qjd^2{P|WDj32+a+Lo9@!r_!lG>X=R2pjCF!C;4^ zsS47VsO=F~^KDPLn#7y)lakip@`mQrD9I&gH(a({C%hjt->s^gGEFDE-h6jEx}sT9 z@Wb<6Zu_%dyvs%!&n@`mk?C*_&maZ0wndmF=|>3HDBMdy@xbHZqpsFbggUfn9$3RtlO- z6>r>w;FROyjblKqaADX_0%a66J{nPp zpm(ZC$KOy&4{g&bgGXpqkeyoun`V6(BKgQ3--Wc>c*6 zSmoHsFDkljBg4&`F>Rg8uoA}fO8!ryAX38E+i)(rv64}WHiDnaCXr6<-QJAxq-a84FVe&vw=fB&g@`W1_(aF4bDfthCp!$at%73PHI7SMuV?-{Ib1mpuIGGSO z%!Qa-?c3DmjtE~vVT0_s_XOsZ<-C;e4UuX(`Rb+Wq=$-gt~F@A%!@r#@s|GX90dP2 zr*O@9r#UP6t_2Z6(_)IL3}0t?>swh3S{1;|zFHWO>09Xl!^c4dLB^YU!WxzP1x;yr zH6-^UzGay%V7YP&>_y$oO>|ixD`g(y0Im!r;! zhAC#Tl`-yqa$qx=0=ys0#Mg5YjLgz1&wTcBw_OO>MuXr5@gF3hjA6dYoT*fw4Eb_; zbkC)J6wJEI7j&$KBZ}a5geRruS8#*^`t4}nEPIgJR3kNd84WMCuna0VniZ5dOvB3w zPJbG1JPsuXM^71>yMK=U$2C{zeC!KW>afZ(I*Jvyr7_ zSTuJ7WmAw6B87Gl(2iPxW2ph|3wbS4;Gbb@YQeWwLJG%0EQQQH5Z`2`5{BKPtFrW5 zkk(}HN|xSX(d=A_i!B&Tk~xen7o~85UROR%UbSViUKfufFVKzO0w8@8+e8>G7{><9 zO|Mg!1&b(aq=3Ud=I7#>2P^8~K0Mh*+ZqCbyV~Ln6}CU*2g48{)}l-d?h$L@^Y7>q z#lKf2)%f<9Xzo-N8(%$#wJH$;?C1D6FYN@GY465BJoECR|Cho5(}t|>ctm|uVeS1dxCLV%Wi0hrgYXjCTmo}3IH_gw_wa_3b}uV$9kz!#3% z)Ocjfg0YCw+J$dGL!Z7;YG&yoz@~hF{o6(|ohVM%!`>hy_c8+WHJ{llfu_AL_Ojpt z4C@^P=|KM-+00Y*D;{7$XFk9T23wNk$2?9Edh${?0gP$mJ90D#{PwU%Db0tWWaWQv zrXE=xOKn!)ki77gtAbdybtsGGQuy#f_vFz3b$i|@+v|=?_BALewLv_VzN)wMF3g16 zZ?-N@p%;DKCnHh7jbiyc5 zr9F_X8GmFV7=TL&E8NVTK*&pa-$3!ooe3sc#}>fsxm!SU(rYj~`lN?pA(cCAIv9=$@pi9iZl$OE2+di>g`3EF*a4TJmKUy9N zg^?%&Fkwx>3ETD@n?#bI^?HU5Uln0_^omC*gG$t$D6mnO>hdSuc4>sv z$uyAYChDSz;*HFvIE|k`P?C_+VY)v9k-&d9Vi7bxy%+>TxtxNSdKgFPR#+o5=|MH^UaygUrGMXZ5&_$lpym36lrD2`qMZ}A?g^Fdq8t-=_ZOiFDP984OMEp8j~ zF4BtjOf&RBlrIo+fa1nmdR@4JeHjYQ3f_znN^h_V6vsI}A3a=4E?owm;yuh>INywz zy^aB+0gw;Ti2qHg?*g@r{xWSkclsjm`qJA`EKNIAYLN14G7D291cFfB8ay>BjYdlc zmfrORm@dd2vUvKsvQeq>+RVckBBKqjEnZw!$J3$y)?EZB_HfG(g0dp!kLn7m_DGm^ zq+8o37!-Q7mFe1 zlMt}>=y@scrAH~YVPoo4$zgt=j*$4OkjQu8uo7|a=oSvYhVT(KY`RKZpd!zy# zF!O-q7@6BR+#JSA3EDrna)x^s`1&@u%nV=%zMYALL1et{!mjc6@vbS{$TZ0`ba(Zi z#2nbVV1<@d4!7d=f7NZznl~42S-BfgIK{i(L`c|b&n-kwI>oG@VL{9t^T}Rx%;Zh# z;zG@jMzU(wGT%?fAGTxQixVaCnQH*9CVIb^t1LAM0U4bGMoSlZ^gW>Of6nk@MtHBG z0iP)`p$(r|+6~G24%-40+XYo8PiTovfLehI&Od+ltT{1Uf$xIVjwOp>FM@lbms8Pq z)yb9kxu-~A3Z=QJy?qIdo5ZNeBL=-0oiP(aM3g#+=?}GiU<@;0mV*7)d5acyEf7N) zF6aq39GwyoW{Jx6Wa7Yy}bX3QHZD(4pFy>ZdCwXu<5xGNxJ?bXvN{Q86aQ^IwD*^0icPwc~ zcG1?wqNYxq)Zil@3^_dljkjIS?8FYbZ6Pu_Bm8W`^2%^SuJ04H-l`cSsum>GBsrY>u<0Q=g4=+xruj|a8dU(5A#$OZ z-+@;aH&l%l$hIZc*12S{DZ^^g!!4gCpF3MSaJQdzi^agpGSTxP`BaAMkmd7qAqVwY z7Iez|w#3X?b-9W8(%=&Upr`Gw>ph!j43tYVd@AufAHR|K)#G<1eh1;#f!_`Ijlr)Q zzvB=wm-s93Zon@FxDoH~pcj}3m`0!fjGnm~@IU*U0Xr+s@yaFEqXc>qf7$buM_#lL zuV*M7hYq@re++sgr90U|2|!B6`;%PkFONK7alf*--vQE4xXT|Cy3+w2Ezp^OG!*Xb zD|E4imRM*Rpku_xzgygY06JE14_n-$fGPy{8$cRw$wItuG(lWX1jNx0EJXv-crOH` z>G&+5n7HNv9VgK7=$)1BWD8BR5N%wjD;LU+7ayG#cO9T(1xE`QO7|^`(hW(y2>N(0^$^|JaRY|Elhq`C=TdEalI7KNdnysXtF?Dz2Zt@d87i_uMl;?DF;6S zr0IPLkmm27EOa;uv(lXcNa-#Fq;!qebpfDLB#s;)<@xu3Dh2l^K z(5V7l2T0?{0Xj`^-?O;?w76ed-18PUU~&6nHlh5*0ewtDDFQlOpl<@wIPSD`j{`bG zTo1%(TwS>abG+b=wYXCNY1-NVsr;U?uD`a>|5)e@RC^A^%Oh(5O%v#CKx|pdBV#cE zogvV8K$@2y1EfCA0i?W~2S`i%6_&2oy7GFDruUB)*AGZJJ?vnt|41Ci0n+eJ1f;HK z0y1P0Gz73DMbRV(M(SXjB@Mc?F9iUSL*I;oi7Pr*m zzF={;THLn)X*t+xagPI1u6A17E{hwE##PgC6rkfI-bsKoMOA>*?>s3#@klHfL3+^;P3TR@u1*DP)?APsp0TJ5vM?^r+@?+F$<1(5o!v$!q`T?0r%IUeo4 zrsEnw)e_zx0BMSN21M!Lz;%p>-Um_$l}zrp>$xMvfjvXV9)~lA;j#y;u59}hidokR zi<@X6wkYbi(&Csu>X+qKU0LE3S8bsh>*`os!b0`db&kc&wa{hO6+k489|VBsYzxhn zZ{lM(rDHw@y%-+(_Rcl6BNPSZX!%4P2ZtM?+Fi(XrzYk&l9Kwup3sS@ld3*>X8pS1gm&Vm7?n&ePkgvHR z%z_Z6D}+ghFvSq&wh-p-5N3S{vo(a-8N&33FmH!22ix-MN@GF@Gd+aizD_U)FArhb zLzwGB7>-BXM_IckfVm%Efiq))b8K?hs<~O_^DfyCC)K*Tuo}>Iax-S4Nlb`4uvVZx zbvgz8b-I=i#6soE63pp>Na)lPg|7kso?1~v!6`FTleV_L4@2TxrsnRHY{+AFCSe}6 zC~-yjZqR?%6+073L&IXEW@*D!Dh*8*RVEC1u#FC$YQaH=%BV$FmI4CW59N@VIXcLB zxW+(*hN%u3C*|QgOq@M=LRg|6Qqso=p<>WIS4Z`yDcHnZ9MrIAsEo!(4N$bSYN%Yw zSk&5P4)-xLRG+Rf=&MAYVhdPB?Yg)FCCVHeRCT779ed1EHQHKtu8l!(@$@@TcGawwI?xD#O`U`q&Hd)SWfw{|%xXjvyBSv+(-$%2jO)n)#7LWTp75|4v{w=lm;BwhmZP|H$VtXIYjt)4EtfsW(}G4oIX zbh>;@a)<>I`@a{IA&EGOn#Pv|4y_@P^wdZ+yBvU1yrH5OE(0Qi1il(kR(KkcSRQ$V zkd{e=ah%S?*4WD;10d;j7l<~nk;1vQ*YI+1%5^o~;z45jnedVoN(!oDTejl2pa5yM z;yJ!~6y*f4;vKzYSy`q67Z&TwqU);5X2w!cl-uaKv!QusGd`1VU?*&kgX2z&k~_t? zyE!@n{wa?}hN8PrJhwt8E(A;1${ySsd6;Y&WI;O&=3rU&SCYcaMAUYOfBAv#eO2TL zcDpJVf#?K6kcIME*BU{u>pQ(%8V`vwC6x?OYvV;%=(L9ob2^!YNq{HAKTSLDODMp>a~L%t}s| z6F828a@mnUMB5ob!Hr0d*HJc&%$Q}^9A$Xe$sUhp*eTqn49clTd+-k$LXk17Ik5x| z!{V6D7!nsp^E#Ums~#J@h1DE^J8)d?IkK^2ReG9oVh*twu^dp}oOepD` z0y~RHJl~t3jK!Pb{Vm}`+XTvo%|CbEO-ONQUP2B`jQ7M40MAj!Sn)&-8mK?8dl*>Z z!HTrd>gg8ClMzfEc5kW9NjWmXf+-2x9~k#f*v{eJvxdY}Gh&3`V^28~CQYEBkj60M`Hzj{>kp_Ydg;u%IYbEYEJi*CRBq)Y*b-Ixm zf&0|9-H_%u+3szSQ=!zrm~>$dMhZAu@BqL2&)1VqI9bwx=p$9H;DC44UY;~*`g;81i1gtfvbcA35!@yfrZ za0dxX{6hqx(ktG{AU6Y1ZAuk#+AYi2QJ2R};w%5WBt$a5YOf^XMB?3K+Vm0ldy)mR zdWislL!fjBHut-2fd81>O3z@gUr!S75H9o4O_BS-jGQa{vt^$v&CLSTN^^pj^_CZN zqZ>yG5xQpzyK%$G;7z?D0PTkklKKrtc(0xGi`wEPW_;=ISno$*=!B=r@Fe#g$dol@ znS@uH>9c25-66`qBTz^mY-4CObm!i}f?5C<(z%z;XPBnqG2f16Nylj;F#J!?uToM^ zLhUnuY`&My1tmHuQ-0h6!u;GDs0XjSPdzA&km#ye{^tMh(^Fc9<33U^QCB20DX$;# z*q)z1)YH-pJUiq^zCY8Y%Sc}w$41WxeXm3ywLbn37oTi!1R8+|RQb}88p3tN2di29 zp%18Ir5AC?h&{+^cxK7qxaMq>5*GSK;e!ydoDZ-H=;)15V`(%C%=@MlWinD)t|ytc zdkkt4tDdatMKT#yN7Y`FRm(mpTJy4qHxeSy(EFY!A@WKh5 z36)dOdNeKVn%=bdYMxJ!0~d2}i!#FV88A?yYVjg%3t{qvrxC7N2!k0so^!mM&S_oT zkz5Y@F_fS$oTj;IVKdGG1<^=1!c!+#Av4cPG|^rV6eQrVNoQ;U zj_tJ5kdQtmf)6I2aOs4_6I$j>a3<7ExaiXnu3=GYGw+Q~pU^dm!ScOq@`SF*Tv_5r zfNBOwW?1*g&^`tcA&}sIs2x1bHOT__6!$;zlbyQwtjQNS@hKlW-Fl+~P9Oy`g$IoS z)UjEet*{@IT-dbeObPL%*hLHHx3{)9YUTt;#WW?MZvtPVN6lqIYnV_3W)CD8siK?Z z36QhB6Ch=xP2$XuHVJy*J{KSMGrz%DW(?l{>=PXf|NS1u$r(|(>_h8r?jnn08>u^r zcUfGIg{U1)UFQMPP_6uAV+7)5f|x*cfYe8eg}w$z zee_sp6QEc+NxPs05^O zyl!zkz@@kvK-sB;`)`Xo7Byb!CIiy+PP4dK7I%%stp;?GaF0J~y&3uC zLJ*LgE71LYu!y~U)^3Hkzt2+#DC&47<5wmSM~@1fVxdY4tq>Yg#IXBnJ_fzMj_-Q> zNQ3H#=g0E*{q0Nt+|WSe2${Tl!D}e!*bNObcb_x|7;g+=sBrx2=p-Fp#+H_==ic+L z+Z!M2CdEb;-WzAB2|nSy@$n!)wH)*uYtoL&gmkfFgrAcQ4NHMCGs|EodBwO(v6Qo7 zK4)ksRmEft1_*=svc<#<=Gy_x(7WaL251=C))3~I5ay2|OmHV0akX(TjNwHhE43m11ZG_Ww8ewtd7TO71}*v#GFz(z2lX-_Vp zl|a|hpCD2lFdt{OV4Idgsy+nFn=mtE3v~WsDY~+s8r*o+{D8eXp_2_y4CoguagAgy zZfbTN)l{O;`Lxye6RU1UB>G{5wy>q0mMBl1^7m>7{r~m6x)s~L|5<$q19Z1r*|!hX zu5)x7ZYNkL7Pd`U*kN)phUbHJp{GupMlw9yh1MRX8m*9W5Z;Aeiy_&~Z7beNzn9#(fl&eOeJ}YqyyqTCJse%<95BimHOe_~ zlylH1XY?rN;89L=lrv_OGj^17$SCK~QO;qboN=R^!&A3aJ(*s11a5C{-t^M2{x7=s zg*Z$rEysdm@V-@5@0P%YAtu31#+OZE*5G|Rek?uzUuKhxTF;FtMA^#-Ol~VEj^j#& zIIdJz0Jh|oMbMkNjM2gOaK^X>KcNYnbD)ReWw+yR@cC!eE&td{>lV`%eEefCOvS*@ z&||L?j5n6Bq3YS*HTy=T_Ol@PWNWWQI{Zyl1YRg}JKd}Bzsho1Eo;zXv z#nb{%V|665M4)i}t(=I{7Z7u~IrQ)w(EVT3-wMQ8;fhRn(|YNbHqr0m=bRXce0PQt zorRaw^FgOlsv-6o40u1nBieW3a=j6hw;7vx=&Rr%8l36PsNgo)zc@O z{8Q`e0ZIeKjr5h=JHnn{a$NfMH&A2Wk(-zkKXZlN!<2i&R)tk{#HVlCp+cx`H`wPA zcE|40@rBGCh%iz7!CmsYeJ3iDvtr8*d=(dzIn9}F+=$Iz`7~7ZItzO*czNsj`A0Xs z{ZVJro5xPtab@q3lQ!)pzh*-in?Cu?*r#0B`&8Y$F*U_=;~SV9XVdQE7DD$CmN_1# z5@PX!^=En4ViQ6XVPIvOvmZesl~JTcu9?y>CE9PN_@GGxE&*R#G1c|Vd-61m*sGxi zJbBu++PYo)JR(`AxPd914K2k7?7g1%SF2N3xXNXmVu9(G@S^wMd;?&YS*IX{2shAs zfgLy;z;-(KW%$i!;BaJ1UxrvdqO9wR2H{`yf$eU=?h&H>vQs!`d|$c|bO(d3P#}aJ zXG|%j_fWA(l>00|Y`m+U8uyZ`Zd~H>K0Q2{dahK%zNOn)v6)FKF;?zQNqK@I04fyA z#F(x5XZNOWfNNQDR3Xzs-@VC6PVr`uMAaj+t5k%_O4XA%9RY;~ha&}3QN|#D@dJH7 zAQT>DD5clK}f^?2QG`Tp^nXxoruDBmW>aHVSO%%)bt6e|v{J;RDI)F11$+O+v zptE5EblAYm*j4{_Zn1pWHtvQ(zm=9bU(JcsMsMGQgE<48J8SdX5khL4li$(*i*A$9 z;y8ATA&-e-^?Us}fBH}b#*vZ==8D}mE9~x6e2zI!7IR#sYfnIdcrxbvV4Zq`V+NclSt8p&s|P0_CyzSzs@*F=29>=$&W z&6;SxrsAv8epTaZs{L~CRjpq*#nm^4;rg7jse3mTWdI1BF3M=HqK%pA;0v==ehPIq~psOcRMcxeVe#Ouy zxTz_Qus8niOHoHa37rF+m@kq#T(`UtcP`e_@=b%*L#9_{~ zZBVpC)4*Qt$tkZ3^iUJL-0tLmOIvHsv=@_W%y>S!?m*!I&WCx9`Yy(Kv7Vl=)3#)7n&9dPPRw3q!gxYuNTv{%uiSkNL>m3+_sNZ zIDUEjig<&LAJQ|=h^6kPwQ26oM4U;lGluBOoAFUwriOLf;w#R&;Jj$|3&1H==AHen zN&;Jd;p})c%hR5M?{Dm`&3wK(lKK(?8J@Z_eb$MoHmyND7!yV^Z;wcxnR)xb<(kY76IAgMsfN09USuBi?(xc&}2*8w}+=9%VF_ zL=*P=?SBL9U;bH<0?dN5-9y#+5X7E9#-V6tj`n%IOBE(Zk|0j&ZibOLScsI-D#Q#s43B?*bTAb?uFx2>}9vC#WDOwxbO- zRKNs55*~GiBygroAo5UJu_T1Va1D@>8Hq}1WG2ArI2v2q+UKRW_Flf$w)WN{QXk z&6S)#00KQpdnf$tH_oweFnE7?k?$OH$Eoo{k&luNt#2%goY(rsIgyXE2iiJ-sf*IzurFAQ zFHJ8uvpjX~CT4l8WJ^C%1W`cC0iy4>3DoDo?Dy37>qtY8P~9Oe;0$rIFuYmm5sgP9 zIhb%zI~Q7@G6ywI8NfjhQJquvR-!3SRNa!RValE?;b#=~OW=p2-Df%F2M64Yu73}R z+F|)R%^f*$^yo8}MW1)i`SP$UD)j{m(~}`RX8cL1&=)PA(h_C)?ssXFtdyh9>In7s zB;8S9bX4UyO;6V6m8{Qt)%q1DAduj`*Y7XxFacIPs&o%m~hZ z_MmCdx*Er{k3gxDdwd-BFkxFql!;A9{a%_NbBbY5oWn^4+fkV#+Bh<_GX^Ja z;2`BrEKWx~o(dUeIHo5Y2oso&M5m{@3JQBAI%mF-soLks@`Q3lm@g+zr#&N_E%Kva zlplBT4Jw5?I|xbhEAHt2zNbX6Qh$kOhFpZ}9Y2H+Lgh!{)c$3z#UkTq#x*Wo%L@hT<7L(z%n!S zX5(&i#O5k|O1^e+^$a@5^o*0WtCHl+5(Or1*v5KiN4E!VPDjVi15GAmKRk0*#Bc5> zQ+8p&??v!Eb5`^P@;=vVLiX>m{^`0$a%awn9t-Y777$)tfB+pose1A|Z}=h{Wcf2P zoQtTh{{bCda`D1m`>QO3NRToCp!C4TA7^%P-v1I`$Ue;50^<)#wp(Y+Fyl{4B2OUx z@2hOLQ5%za=T{|_j(T!HaYudZ4W!bMED!YBLMkg!F*+y%y_zGV5Jr8uy_vF-mAKrU z)4I%;p3nv|CbaJSAY)D&w3qZP1>^+KNVGVeV4mv=US`{yXfp2nIeJs-1$K8M75vj zT|)ic6PSgMNjh#}vC40BnAZpnSib62xqwK2E z^v#f`m3^+*E_N``v-+RM7_&YBiTQ(#rGkHBdp6@IVaTwOiwl;4BzcS*s?VVrI5}}E zI{^E)&|`+o%7OWiox-I6Q5LM}U6)u^uq^f_F1y4KUE5QUg|T~??C|yD5}OHxYRlV< zu&=B4h?J8;blYIy-ElWD*ID;rDOC{E@Gw^bMwQ0E75&-ZQu1433s+Du8{#mlmce3g zeu5`5OU(Ep6b>myzP^)-5#2k}^gXTQg}yt@r@p&RhIKGkiv<1{q3Jc$Zboo8SAP+GMJB&;U>BL zo8;#rpmy?HTk0}EPW_$-5h3xl?KlAB7M^1fJaNg%8H1c5NpVrC2NE^evw@z%iLW_C ziI^##EmQ3y1knVtC8QFV@B^)8UW;VFwoRerr*NPfR|u3^O;%`w(;1j;zbAoMpS)jC z0@GmO@rSI~8$R;}-nnlr`8?!O0xiDbX4_8%%0adM2Ox4#18B@k^=?7rK)d?^&3SA= zGMQ>a#;wG6$Q4Yk!7ANrnR8(S9Lrf}pmZVo2}e<$+i=XbLYCV1uRT&`WE!IdqDG2T zyBZq*gcJgas7P;MTH(^Y<|bNabR@0bd@kaN6JGQvxek|ZVXS8SZ1FmGblBd)S!MAd z)Bw`xY&{J;fj)t{-bG4~v{>K8hwOH?+SEGCb|~kB6AQqnTPTuPs;LRPo`JN4yOzNr zl&~PbKMlQHk)IBm)2C9L}Sn9>J;Q)U)_e{2~1K6MXK>L%CAF1SI?jo(bkq;tTCs zv^cnM@#63zve36(_nH3nr&+srT$1##%`7JP<%U7!FA1WCPu$7bDUB~XHU3vXlGyWFp2<}|ebKTQz7D*b47WZM# z0{U}hsvpIWmZCma(uI<+FU3{$`u57w5z(?>XN>&>DFLTE<~KFZ>GyVq7t9UKFApsW zmHMJ%tet>@v%?kTq0-<$Gd=@(Q1rg8l+$3dZ5YA@Td&TYWw!YMTFFIkhLWLyynYm* zDoL)FW6@ zLq8q7u5?jwQP^y|lKHsq>H*=2p@q=n&#z7q9-LARmQw2VODnm_D`%s9NbZo4w)Kcv z4Q{!Z3hT}hEdg3GzoUeGwD#KjRutyqFdjMR&$L5@S{theJ9Md}!s04;_0NJo>4R9g)v0wvNj z9VIR~^0>obuRg0H{-H=Z?$C>KgGQ>AsLnkg5GD(%n@SfF9*mvy>Fsmy7D|rA$Z7f9 zK5hSip+cqo129YoQ!e9GY%53Vm>nBThJfB(&mZHZ2~;#kv9^;X6DT>m5Su**n?Je2 zne=haavkw}95-|b#H1ckS8lk*Mgnv2?`&;=3+q*K!=AV#{|bZuJzfH9jRrf^1tX*{w6;-1ag&xwBdB z!3*_IRB~j@TaMkTYzI9!wU(~*N1rw(H2$z+jqx&8ryc@P-7zqAIY^35IgZ#NeJ#-| z?hT=xXcJpNqq$g}k!!YUv6`#YXa#Cc%n31Ouh3xG+j}nNq2`VOGiPla6YC1h{N(yG zu&vh7e40DyoH^?Yf12qxZ@h~=cj*)8;|SPKHV!^0TdY58{DWYqaB@zb z?ueqmGx`~3+dX7|XX0_6n@f({k`(4)$O#s0#&n_8rh472TbLT%pa z0vlIR%oz`|_8e?5;*%^P`Nmw3?<%}i<;9nRr4VzTp$l;j zS|Dns?FJ+iO5l1j1h^0`fQ$GA3F}gqjHsXDLtu)4uAOSh+h+ra8{)|@x1J%zyn>ay zk9b=Z@@Ao{M$#4vei70Xvn0qUIH(u#Iyd#wkTWj04t+jDiEl{`Ly1ViXlw!nkH-tR z^O+YJ)HwjzLb>PV1v@K93bkxAQ;7XlN_L>48GjkRq$Kv9;tr7YT<+`2P6p-5F;?QM z?DI+R;ckJy(t(vqHzk-x*^DTIAQhz{8X}S=C7ZGFixHN+$a7?Y*tK~m^pgNHvYq;d z(C;kCBH2t`-NlVxRiDz2V6mq`?e^jfhLRP>bGSnjZkt7*b50&3aO$@fsMJJ}P#nqf z8Dd_O43)&y*F}nHePXR3EpJg4o28>cgsRDLF({Ur?B3ma3T>$TPjCTZtQl zBRV(pn-6jG^044YJRh|Yg0Ni&pGR(Rs~$WMznB$I{ShN?LMKaxe<((K60-qS(Y znPinyP-`J9ZH(@WRUR1rEON52oLO+l<>Z96FeE2iK~qmo(5#H^DIUUo7ld{M#S`X2)t4PAe8);m|~JsIBL#}2=PVRXX=|7o{gxqcA+5-*+D6A37En} z5xl-ngKziSsh1Emfpkd4scH^Eg$T_HrG}w+YV+XtWct`f3^r{g5JZA^1y~iyIVHQu zKJ3m9BY^Z@=pa(3iLes$&NeVb15sQmG2dTAoaKpxswf;7xfH1d6HAQLMn%;^Pf^rL z%u?pU{zFR0t~$G;Y?eHNVz%W;98@qJ2mX2{1X16UsnlMT3=W|jR;k55D;%j9$C;-@&O#L^mrSV|_-oJ5Wj<`MF>F&G+vkI!gL(3RqMT}96KdNK z|0{BeeANy-+kxpebdWK0@}Q!D)wxXrs&YCq;vSe|3|#0d%JKtkKKZlz(VISKfHBC8 zn|WC1-vq!_c>e}}MSzdseFykqCSZzZkCQiu$Ga0f zL>TZvymKL(F9V#9_aI0w4TSNgE}tg)$NK;dJGBBni1%6O&~5?j$9oqtb1UEuyi@qQ z9q=){Z^Dtloq)IDU5f+!2LLzWeLtGhZvY>}dmL8t$)ud7tj85qE`YV-eSRU*M>)sU z(i{M;PUCK~fu)QEOBVA2D=j&M%KdXH7MEFY@y}jR{^`rcHD5k+T=OUUcQN|+n}s#X zl-Ua9uznRTw?rfU8b6YoWbk|lR!NMqU{!E-C>&b+X(Jq3wAfg*c)`L7V^KvI)-hB< zM#a)#WoSN;!G$<^R4i~{gt`>Hk38ZrOi8egEF#yrpwe-YF}3*H;>*NVS5{#tN6YCit9!R=;z--5qy z;g1@znDvVJi$i6>#T6tPFQaFo3}eAO|7FPDCBbm09L4jGD=xjPs2FFur(QU%r1bL3 zL3vgL3hh5HAST&*fPNdA^{I&io*Q{N?#!pR%jy(wK4_IAS+fcJ+RrBg* ze=}|$i5U#~cPPt3I~Fe{_-jP*;?>?LU~EJ^b75H|nx++xsZXTFfx30tPKC;oyWVAR zSqW=Ns4KOcr~yB%l+;`W10JwEQa34$$31))XOIi~o)SRSL2X@QBOPjMVWrxyyiM|t zt3}o-5zUIVEo2u>Ls(0JMTwdAF=Bs6+6NyC$m4dQ1@S&W9hGC;e2<>927Q|vTx+W{@eSoU**HTpAY+7J^|<3eJgDGm($O8d!A-Ge*EPd#z5qS`Stp5cgpMH zKJ5J6$b^wM{?TS*-{*teH|iV5-}24Vs^{Y`*Wls03kB-HFZm$XcmcoD1bPL(B?9p_ zn{wq%@>0PS1DY-nRn_n+O0KaP5J&Y~gZG{}&B`^t3+R&qao4*@pg#gq@$uF$@2}(< zZ5rY>T2OGW0GcfjrzB+peI1Yr`(2IW1YP0I0=-olqrn9#X4)31kg&8PqWo>pP#jRX zxIPVNjzC@7H2~Q|g_x_Mt2Fd^4bcp$^0!k%k7?+?H1x8DdH~Ip)CwWTs8W6gkR`Yz zppZbfX$T^mxb)N@REdIU>Ne~x>z;&H~l)oc@!h$;m(*uPYqoE%GQnB0#NX2pz`ZE>F zDS%W6S_)CnR6vRoW7^;E0V$sRIQmA#+NLxNCg90#QGcM=XODBP)l6z)8YyFlZP0=iscnR13#vl)U z5zq>Oz7FWq0&NGR>gZ)a^8|OsIWE)!NR{aRkGaq(1unD#kjnjY8hS;$#>Tm=_7OnJ z-xGioP2UEjICk2{F_)Ee=K@+O&@wrxZ=*IGKK+2WMRRiMh(E;xGYYfs5TtG}i z-LO_r9=;JJaOkKV*L)43D{)-WKpoey8uDvb5Z7@m8pqmGVH>n-qsBF9D570kG;V{2TD5CjU#49@+_ zgGt5-OM1-lgQ!mEhq|n|Dx8k_qrh-&IE^U=hN~56%uHaoo}n}uUso@$!S09;fGHi{`#xIY~5^JhyE`KS7c!# zS(sQB=Brs4_UM_ZQ$uGa=0Fzaa0Uh|y8Y;Qdo{xkW8~VJdfbwpnuRII!c57+P)lfL zJc~0hQ1ey0x~Z?9nhZa5jb>rmvM^uI!f?z|k6VfzS(trUm`AcOFJ@tek^SXyV;-A@ zp{?6YKOEmOF`+EXvMfw<7ABU3`BoO@$61(t85mH0HEf{w$ zJT5h;eKixqHMC3&ZS7`a{v``Tjjfq}93@;px@mn=`!Sq$O545eqgwZ!S(trUm|tgL zsQJ~SpU43-GzPB59spD>W2>V-*IKP{@BQidQ`+hJjj>kQwUfaF7Qv!Tt_dz~Li`mW z*1(#Y8i`gx%aZJD^&d=B35rkGyq$ckjy6VC!Gai+J43TxgNlpx+*V`bspg70g{YMs zspX!XHpfA%;z>l#USeH8o}dyCn?b9W*Vjed6js*&rmlcpPo#z&cvgp=c+aRn+VL}vuy2- z4rgSrr^`rQ6^^>FUZhv$A@&7VHrB0!lE<2+W-y1xUpgD2oXhJ|^gzP4Tw`Qy^QwN8 zLegR$>dZA`mucLOU)r`_Qxhx_qK+NIfB0OP=2l6W-i1Tuivrp5TA00GUphe~-;T5Oz&%4K>+|kv&JL zS@X(OSGZa!;lt~pUz3cgrR&|%bfMGM_(+lTmt+{dgD!j8Nr)v|s>^AeknFg8Z49udG9lgxL(***wThYfD9KmZP$(YgzZdp{ux?M1=F;yj`kEYU23y5qB?B}N=2PK2}1UR zC3dC&j#b$ZH<-e7BK08CmLuKKMv=zbqCMJ9YxMwv{-}BF8ua6$3-i6SU=|lonS6nt z54Gs2;s5sY)XbA>Cf<39JMQ*<`;DqKT3$T4Wcl2(N=JL}1Q$(J zzz+I?k|}~Nvx4|PxoCOSg7Bw{FDRPohN&nkw<;#$cTsR6qC|`n5!A8CFhRL4d>1zz z5{bGYnP^7He%(|^H)9jsjCn%7o12qY=uP$n0Fp@&nOzpg(J3AC=!qj8(pa%>ZKRQF z$YSebVr|33Xw7v0IsW-L{t}!q8;3zwo-^aBS?83No-@IJP8q9aRdlrnHFxdWD{zQH zTg~O z#D#S@|I!?3##s)@-x3_&k#Wt3dB@Q4>_g`_%s-_7z*;J3(tDE3ou}*nZbeR~&S*9q;INe{jX5x}X z6YADD`Bd$>xTwg9SM$bS$!7>j-pgh*Iv~yugD;SjFh=Qxlcr7W!x(P)6qmmLb_8Xc zCn{g@hgUwFmzp%CbZYUW3#Xl+d{g?Vzl;u{xM&Isa)Q32zxtc<;gxR+%7=d^DBCoY z&C8elWp-Lt4_I6zIP{gXf)}Ox%E?l!4~Z|Qy<548+2*|E%B-(qX;{+L7iMI?|KX?xe5mMFvB0hGE}1<2>*gb{-u~+ zE=TV*EpyntuxRR};z`9*`<+)hmlL4Lf6@hR|L6u_Cy3{7lV|j_(TOK>9u{pjRyQ}* zq-K$4`*+)?>icvH`J4LP{+q3v@L%6gdg9R;>o1lJNA@j$r@rm~iN49W zrg7DZ6U)c{p!TZg`Te%n%yu?+Hr6|^>ftQ*IBOpzs)3*2m)re=a55$T1nxxh@Q3@i zngE^_=e^H)KjFMzbKcaB!{-*~UFe)EnB}}Lao($(H&43p;c2x0KRySYeDn1|=*bgR zd`?8qBIn$}{}g)iWFemqN>83bsg4><1s?EL8r7e+Y`|NRa0ta8Gih@RUVcRvqU;`wJCk4R7c-R_k01M{a- zF}t039&_IA_}=4u|FiQad4o~NFsVi@hbU3zYFzW=Av)1~YGzW+WHc)!{sj)4Ct zQu>Tz8X7&)#rZW6=|qMLjet08miLJQVmsW zs6j)1+*emQDALeU4OMHXK|@U%YSB=uhPG;`T|>8MXq$$%Yv^_j?bJ{c?!>EHwQ6X) zhHlpo)$A#M9U3~Ip@SMatf3eA3L4fSYYgiSGWPSsNU` z7*CEd9>31*4R!fJ?$i)mwc0()j6>|r#!y_Mh%Cn*nrkNfz0NjYFtuc=9Br1f&1%75 zF)kb`(JlLIa|h;Zyz#x#k+m_b86U>kWrbMhvh@DnhK z0^Ylu#Pd#NA^crP01xYw{`#{JJ|!!@sz4u0K?e}r903*6c+)Nr3>(?Mj=i1}nHGEf zbTfW0(7hy;(P>-I6Ms}I>Rof&}g5=8mDeIFspeJgGO-jmD>;m06`dW^57xm=%om)}e=Vq`Bkff>wmxdg^wV>uCm7EF>IGRYAY(%jU+j7&+cK_*G!@$uA?_2v~oeC`lF{_<44+4KN_EB3%!3LhQ#sD^WOHxLK$hK;Z4N8$Zd$NSn> z;qXkoSpyF>aHx41p^naHJou^kBY;Byx_^tm=NTbBKKCL5ukFIuE6>5t-uj@q@ff~d z!q>)^;PfJ}NR)9g-p5uJRKuAOO8D;o25xad1ESoG5J!N1^*KfY>xNAS1VXMhriglw zKgjfBjRj5kEiY)H9@jZ&2^9n`2Q7Ev&nP}hn~-r{$EM}w&jZKrC3uTvkBYXVX4|*n zYC{ch*G>Qi)s-s^$W%PwXsAXdRZypQI|7#OF|Yp#oPx0)Scv*QpmO_u`=Hn`;;qZ6Wx+YWUQSrdC3WS@Z?q^5#8 zjwW-dIsUM|+w!5y7ZEVe4+B|zC`fAuz0l{pJ=T$fc%!2vend+%5ve2a%6`?DNkC!JK2Z9qK7u8BaaRoLvVuG>f)YW@^VA(*mWcWJq&HK#Y9*X$%5A8iv0)C*zIb zZ_aSMIsDBZrl{Z;w6uY@Wx1( zZ|+!JP!-%disRtjz_G(ior_$tWqb{avg_O1IyRn)mZ};B3Wsc;4F_q2f=tnjmK6Cs zl#RS_;~M}{FQbqcSD|>l6`|}7`_#nZfp6K12fUSP??LP9Fz;ME@SS=f-bsA{2$yk! z_EAr_9*n)}OI8eG*B*>L=j)#Dbn8DvoKnNWBNg$Z5ilhC_1nOQe{G*0*#K_Y_#@Rc zbYt3&#zcDyFd91wCg2j~BYP_C@=-mNFscG;hU|pLgxJV!bkq3%PVdg|MVi&?Wf zg7zrVGiWa!^j4}IXqTYGypx&?Ogo=(D<`@Cjd6`FMz8aaDf021Im|e-;Uwc!-xwoX zAGu-t!r8lcziU!c5I5zhTw^VM^91@9e!0||Yut+8Qv`YizsmI(`WXei3P}082;B>m zs~|)rga_r?0!X=j3aw4yRsmADn>2I?kjlZIHAE3mh4>mE72;n3sl4oilX86kFXdW~ z@~c>o4a`s|L9;JZ5Pefv=a7V^A-`OQ^BdI2)Az}qqmjBJGraxd=4e=0>hpN#6d)?* zXzUd;AMbnuWP~5~1IH25C)&Js42HD{M#%n6IJwG4+4Gn17=~m%q4+4| zqY``-_jXU!qxme1lZLtF`}l=D@!-}$vA1*08^4Or`#@bIXx@7{Y!BX#s3NmyvQU}B zg_VxT5?DnWWsN^(KaxD{OUc|SSONdf_ydv8N{s6-)gcjQ+f&iKv9||ooQ*+rLeS1F zkZ~>BRC75p@#Z8LJ`couA|sKLNPciXW=6%Zs0Z`#YatG33*46nmnjR+X&V`ojxuJ` zu@|h6Orbe{o{0H##B!w&&YeZDMlQs_v5GF}+KUfkV6tEA>zGQS*B2?r+;IwKryb@9 z2oSArOgH1TAXmA0?=zv~Mo9n9n(?7PSg@*91X;TnR#lEtQY%Cq_(4|?vfO^A3lKq& z(~Lg@IEc9rMp+2Fzrt5&_j9?{_yeIK_aowSEw~}#=)MX{nR6LC$cYFyz*t+dDaR^( z&D``A1gj73zCRC!?FubULa1JkNgyWyYkbNo-5+Vj$8d-PiwiD-1hdgkx+wsVyBaecShB=7TJ1XMo(eI*&(W%IO^njIU zEGP`w@1$NA${WGfjlSv8pMuIc!MmrENaT#0;izU)lD>rrBWN-kG}&!#x(+!Inn(p8 zE>s7|^9fW*>U#)i!Aw?R>eqyXNTvJD_z+>W)E`g?8RYek4+^BSY=F?#$fo|rc8pXY zKc9TOSD?@0YFOItLU49jdBq&@;Q2|r*Q}_;U0v5HjdwBX{eC5f^ASvqxV-+$(J|MU zjQlZgxd!Km%9Yaw<+=ldiNaB@xWduQp28uRtiGyoTgEWykJUKFUxlM@1u-S%3Ls-t z?{76!)O<8gn#|5ig=Z+PYm%xW3lJe|n|{30ex?$QM`5z11J(#fj`Z_)lMX!N2D|tE zR%g8P=DCofNCLM%5{zVqRwMQ4lk^j^9@QnO2=yM34 zq7-H5Z=*%k$nwTX#Tt&nSc4~UhHxR}7$epUI zf&bU^Wc0VDdxuLx=gm?1{kF(#&g>H@KL1{v$(UU^`b3<`w&kfz57@Y}#@!J3t7@`z z@&!uaiPWT8b{`5MIKXW5BiHf7$F1yvl;CGv4__aKTvvc}ZssJ#^PEVo+X;VLu~*55 zZL&YP?g)CvgYdV{@kdGrPM|^Mc6O+qha804MjnjnX^+6)3r>6>krBwJoG2GDwO{tJ z$KdaHUw_kzwI2fXC&INeA#vloWRVqnq0q7)mbHz4hbJo$5^Lhh(j!bNN>D2?AM(Wm zj{Qeq3mGA>kN{+|O~(o=aS5!;9*SI0{FGj8&3%H><3$iQl=ve-;H@+F35fzmy{*zm z*FEOML%WXyD8R(_6<+pPs~2nQA1y~pj<=t5Kkj_fd2f4${CC|8Od@#KJ1CuN2RHG# z(Va4Nge6uOIV)nWJL3f%OdF4^CF1*Tz!)6F?EoF{(BDA?D(NMhh!vua5ls!99s72> z0{Gwp5Xd1Cdv87^k7~>A6hW^PeKd^!iQ!sMVn}NVOw5wc?;#)1CTVq76w-*DQo<_Y zMGEu)D}@ftu9pmx#)Fin;C;-k$A+I{yAOePL6+%t!a**Ql`{D(w|lJX_7Uu}X+-)a zzI+7p^B^@7qkzMk@RC3jRTm+`#OB2)qGRi}bFLrmhCMgWN^IT+$g&5!MTA9Onp$-V zKLWC!mH63ck_~1-L*2?ngI@h!e6fWot~Cdk8l@D+qNE7<^VD+f8=unL&=b_B^Wvd@!Os^RT-Km=Q7 z78ud9rDjt9lFkq^$U24j^N#^pe4Hk)6B`PeVD-{|k)|)PBCVGiS$*4>o5bcqkh46o zos|h2qe z;;M?3xV@b`pV)Q_UcHaYdh^A3m|p#2B?9}*Ew|xA)-=g)OB3x?^hf@aa#<=}1S;+~`cLC7ev2i?>i{8!`S%$KAF$!6F-Y+1dx45Wh-w*CpDcJD>5`gRL zSnpFoD%+0oL)8bCH0gmm4>7z0SbSV75xH4$8Yogl;hf~ncnRr}&VprovS8USfd%_! z0R@WWxj`(ly1(b;F*Ik|RV?8CMID z2N*eM*NQhNioFbWNQd#o$Bk$=iYb)GmYu};qN+u~1@B^WcFe>-0S3JU^@pkvN3^K6 zN-URE+NnzWi0er^O@>oYx;2Em4B@hT)WHX;{!_`wq=6C)#8lY|Bm2y#%C^EGS;^mF zWXZm*V7oX+3L0D{2-&JX*o#=*!GdMR1hb*i?y~Ir(?w=y;3w^3FrOLECxpsQmQQ*; zY~Nkbj;Kk+sxZ>IMLu9m6YuV&?NZpDtfG7$tYswzCyK(p=ij~1*V1RKGml#*Rt)`C z{A%>XI?Uz$5o#{Ngh=IMSqV>oQ;_@V9I%%67kDTWObiYuS56ubwx2Ig6owNmNdE1? z=H^N0m}O-hJ@yI&)|EFB4%nzHXbFR{TN%6kXAo1n{~Vsfu!u^=tHdrK z3%(A(7Z~w2yx4~{!7#k~A`ATsqOu0uAyK6|FpkOi%#n$_Cx)`Y7cNIg4#J74a6+CU z1x*+c$KCT8#+=!urv8X6jQVzQNiR}J6=W9;aP}&L>;q@3xHaVWQy~3iqRXozsGf~u%?I8)E#1|_+6T#k5LHKPF)6f zIyT84tK~`QQqZoEE&C;hRaH+W-4I%kipJ^7+5*_AbI2Zs2++W)$fB>e6O5^0#^-c) zZ3V)by{Q(r-SipYWppoo0OKGSSdHuPLTL0szgM0Yn)I@TmUsZ7MzK;Xz)(1u$j*EO!k79LlT-r<+kp=nfY%l@;}lf(h($c$fxj-MO1;LP{}4gxTN zU4%Lc+i$Y(v%2%J&KfT5ZayPq=l%|5Mij*laH6F1@w7J|RzigjB`bZHqOgy#?AfCw z{_i6nvPm4_s2M3(8n)jdM_ZNlUv#=ynr*URl)bupE+%Dh1VN@;jvsL4XqBv8p^-s~ z`H8a8R&3@mBQi}5nPnxu5SFgvWo-3{VXw#tfuYguo~`7BR~fU!213pMO(j9N{Q71Mt-i8*(NUA#nWOyT0%)r9c!g4*pl_$1R zJ`N{Zx4RkfGT>zy3Ot2OwrE^6&PjZ5`25fg%&6QIRX;BwK1GYQ|*@cU1C@IKlh4 zT9Jyu8`y{ai~Ue4!j|D_<^d0tyO#U~R8XPvUQCk>?YK9!fONE9SI#O>s!(#kA>&Mh z?B17N&-dB`KXoW}>CftSm;OFvicbgr{**`J` zTe}WskVUiTB!&cG%7az@#-@7|b=E(_MTsR`;#Ot^pmk=1#|9*I zgs!M*t}~jWEBF^#S664uu34!fSh6rYomOo7q!(FtH57pQVFws`LSYYiRdWMVr4nxF zR;SwP%>2PxHT0sciuj>wMhq!?tU7zk;n>x6;$i&bnx~IzT-i7M70?muziL&Dp9_e~ zp{{wkV4PCHw)5(>RDg=_^7+&K*zzA@;57rDYSy{i(~BGG*42rrW9r2AN1!+zRD!Nj zSXZuVCS8OS%-$lV|24K}&(q<7KMZgKI%#ZA7_I7+m1I*NOh=#ZfAnXYleg9rB=mk) zu}=`q3DI17oQOZ{K53`|5H9xsw_4+p8uvRuSOtOWF%6AJDcHbrjcI_C>qQ#JetWdI zQs!ogxyIMEzwZL#Zdk5y2cWYAdIC_9KwW?+5y6%jYEs2~79i#pc?L8_pf3SZdA=3U z1%i7}LoaIRW0)8!fAayU_?BvDwT7+%q)N0I&=iSp7a*Ph$u-^q^ihF=xvpziL)C!% z;u-;@sLNFa1<^)}itpDN`Xe9};x+9r7h{tO!BatJOMJBZdyYWA0Q50|_5)J!Jqd`D zxLo5efK=ID19YL_PQfHbLFWQeu2VEF1W2W}5Kw`Hs0TDopv{0(8s7k<()cl;kBe(B zAQkgijFBql@qiSLdJPora*b=zP*S^oL*pLQxL*UBCTaWyP>Dci<+(9`4p6D!S^%k9 z-2q7DG#6_Y%5^LtggX9+`7&+c=k!*)@U5>$}3!(#ytV(TnX_sAVsS`15&i= z1ym@mr$ES8T>J?@DwfHB6gMpZG+zAG0aCGC14y-sI3N|`dO)gGJPAmp`wSozq8pG( zmj=^Rh=G8dS^zXd(wGeB69O#Qsr+3EXriQB4M1c+qCOW?fNz#mHP>h zJXFk60I3{Yq;YdK?sI??#lHh<^9k@cPuWQ`2) zv7R!Y4|Z1IAc({mGoSs=C%QGHH6hc{`Fg~8lk%jrVLU6pimD3px`QDN73O4A&o=y_ zQ+6hV)z|D+q54S^TR9*&+Mqj^+TB?6Z2FChG#)D zPlPz;PduTrPmt1)CyUj?v=~peExH`lIN{CB&&VuHK^CSY3$r*2!&5x&qcXBK3$q~u zvjtzCLk$j?VWg?nDSN+en8INm=SGnkPHJqq^h^Y49%yA<^SgO|-$`U#P6RBjRFh_7pfiWzTK2Y$RLLmlXmV&TN^WMl#JNiTMF^A)P-ax7Rp!r+o?6v-1@ zj3{}&n{kY|u}N1U3arRA{P}-ChYA4%XR<@ldt|DAG1=OUaCspTtOgbSVuUReO zls<-}Tw_k+2LF+@S1xzVK4mait;2%iPuWr$+DL1L@MND7_oF+=_4MZS^WUe_-Z#M20f0bBsomOdE*kWYhPhqzkfw16P&eh%##D+S9 zlmW0waB)6-AnGCFshw$bccwFB*$0>umL@}3XMP~EAe=yarTLNh;l#qcN;u_JA_Zcx z3mK`Zv@gz6`A+%5iJ?~KY|5m#ADv^_7ET%ka54!eXu|e`VeBsS9zj`J=^<<*vIio5 zH)GwqRDQ#DRbKaxJ^ASjNXEOrq1@&4Q;9huQs76jIMwk>T)}2WS6GR8lH*Tf{W_0{ zE(KRB;*?Vfjxlw=XPL_XR}`N0y;rYowzre@_1{SY zjguO3j6o}MihR{+Nt&`fA3y&79eei^N9=<#pGN0XXxGntVLjYE z(v)=Y(zAO^DZ1YX^yu+C>gzl0D#`8fLx?s&SV4|$a8i7w`@9p?uboaYDk zw);*RWSrz1VdNGKsLpBfk$lDi{@{7Py#?1Su%H5(a}|(0nJX)+q)o1@CyWpXKL#6- z>Qxk!hj0F=0n_DYX@h;J08bfb$>}`6$2_yH)6YMyRkA#pPj;(R{aB_ib^n356Sd09 z@+r$h6ei_y=Uk+wdRz=wvokTXT!cYCbMe);b))4WVh^?!a%0Q#=rxhG(NzXhUebhn zb9DmF!5&Vdf!3OF1>n7J1WuXek@dK$WEdS-Q7#ZDTh=3oZ@{0c>l@38$p1gUR;K4> z2eT5u-wR|s&(mLPT@3dLV9D<|tThtf;;+w*z-r)I;jam0<-__7oZ#g65yj%-k3WGE zoE+zgxZ9lgKqBYlIQKTv4>{2fe>?j4OVNu*sI0I%1f_TUab8?H1Kdm>(-AvzCQoYb zP0Lsrz03xPIQB!9{b-m6Le%*)d(X}@kpzUlkEJ^vTs3?>-Ql47Q71!j{m;|mhz!b3 zEcSxmIRT54>vypvJczrOQr7gu{L%b?)CLg|i1RJ`g5FV(h)=fc!^o>2otMbK>JS>_ zvAo_<=-_%s6+hMeJIGk-5H~QzPxa<^Kgjd(;RIyo1f<~ydaLr}N@5|Rh?7!=dx9Pv z=_5S4o>-LETa|BR$KIiiw0q?>if*hQ`NPnYI~#DHUez}^*BCr`Kv7P$ugT~7@$6zV z4^9=zDSx$c%(kFp7WRw*{CyLDq|`RPk)Yps^TOZ+z(si1;Ez%h-T3tFt(G}BKOOP( z=N{+>Pru&h{f-Xau>HZ~fb`=p*SK6mO@Pi8+(!JW9W)z|+J)eH@EPLTjbHL(E=B?u z;tHk00dPW`21vyMz>ziCv{i3SDpRgd>*)$d>L`d|l`CsU;V9WE$gf=sG_FuX6SQlQ z#<7l6SW31kX3BC37tm0-cC|Dvtf4CH3P8g8WE^EI%EpC){Myycl}~m|l`9-&pOBPN z`-BRrkZ&J=^*A^ea^9II8=R*f%z2Br~T0SA+Vw_#BJ+=f3H;qgXaBERpx1MpqP z4{NHw9RNE20)K29>6m{B3|of6WJ~llaO236e*ST?Lm-`q17*t&i{ZkNCjF>UTYW3p zfxJK{^Lf(we79YK=NvyAomE}D;b2Hrg&7Wt@L>uHa~3fE49t0sAL5mtsTr8c@~QpE zGJy;~h|s9i7&on@8JIeJd88Hx%v>pT7EeVlUZ%@xwd%Y2>gAASme-3|<9tMwxZ`}K z*YM!cUCv_}#G&6*ow)mTlN`z9h;cYc>2H;fj8b{mcy+{HWID$3(A<(x-%e- zPW|ooaoo$`AFUH|^{Um%u)SYB?^TnNFT9|5ig@J=TlIrgpD~Opm<^1m-u{x9Rt!?V zLYwRe@k^cY{4iwp5_B?QZc2Ne{$%zZF>cqlpaC$n!Gh`GmX!?^oW@n&$B z`$RJPSa!Fbhcf%5mFsW{4@)4VgE#X3?2O}SW7LmAbCxUOy9TD%i`nL#!*m;mMY*s)AM+ar|;F92C z&La?yq-6gxR4P%Jv9YL1ptm6g^UkT9G*uKI!u6L{aC_<%Vm}(d1)Vp1=H|EY1qBy5 z^+EfBQ1Y^zP;5_5s8fQ%g`NhOn-2r3OnjZ?a#9PA$26fQ$K3oFaAoGb@iELU0_P&K z+%j{=-DB;fE4UY2Wj28Zn1-8HPjel8e$ z_9FZK-G4bHxcluvv&|j3XUCqq$lNir6!!t~o-lrnxuak_A}Akn1iwSN_|sz#aEcmA ze4T^^u8Z2&{1l4mn^Oz=IHxn&TEXg?+8+ER!QEU=q#QXy;~bgz7Zya6aw>xgul zcMjwkuX?*I$E9<^W-+YN1CfWIhy-*69ik>wyWBiPiu??UdLRUqJz}T6S?S-FE+Zkd@56crWIN z2>;q)YYe#+`GM*_U*r?`&57n(11@fnI~m~Y7Sk%dxMc%&M{a6IJjEUEKFR?3=3VAi z;0_i6=d9k=h&d{@C~!kEC_5AN+%bt&k9`w+4<#ywKmf1` z+!?S0*BNM0?^ZGrpU%K&zO2qxW|v(_XKO1lc+3%jLUTmxHh|b~$|K5~182_Lxj&;< zP;GU5M;IkQPcR1U9os4B8;;>tR`g8Ecg(V5!UZ<;>dF0Wr~IMh&C(}8Sz{N|!d+te z>;9GFE^7+Br`~x#Q?%?~Lr-of5o!tB4~NdPNm~^TYKuVf!H8)AaVMig zu(n}^?A_3nqx#M6JnRce|LjDux7}TnKyr_QnJlyjXzzjc&yO?rpSGWrVxkd!rNi9O z;p=c}1Di^5rpaqI(I;`a-_1lhZ&ON`a%7@PGBL-(0!#D`VfF5N)qYfQNB14_;rhM)X0ZR(c;6bI4n!jyNpw=fq!*@4(c621kMXx42ltC z{N@f5s;4fr5~p%a2jx1od#3dJi7IYeqFEe@oL4e5`WG32oam@f3E9}|MutKMoV6fz zWlGh96tnw~X9cXj-QhpAQwZ*357RanO$G^>ZSNq5iC`7`q;(n@!RU0 zyVQAC^Id#YHYTM7U~5tujUg&GQ`GUQ${}~5QlCwKqgsu=;XD+~(9#flVRUhCW#YTc zdk7=DGw9g3=Nm44+Kin-x+bSqqvE0Dv=uLm4L8e(6SNPRJN5*3|2a1pd&a~tI(F37 z-_?UThgr~Se8hxStJ4O-hq;pD}LwxB;XTzbUZRE7^}OpWmBmSR&r zvF46DWK3|&0J=>z2AFM2;FFG$8$sf(Y5>SoA%2{8mJH^EO82dshHS@0bZOl%5E*V8 z2rsDm;X~DRzThr0uDZ1JaX7jCpJeF?+}X-vESh%)gVDoKBy9KyI`}t zCspO*CEOqAbrycoYvfA0#maJ#oIT(YIWJ*HdrXku>|suOg^AC{cmDl$D@|j0|!*##)FqiFs8>po9rn_GJMr7j-(rZ)aJH zxTU+p&a%-C#_c{kW39yCF-J5*w2=-}y87c~W6>v^L9R^9bM7h+!+8C370;&ZU}iT z{wa2vi5LTgSQBsHa$Y(5M?dy0ICT4E^chZHv7UF#O^*`dCBGlYz}#zreN|5*eZN+c z=*TgYG;t@^Gw|%`5q39|CQV= zE13 z4fk8gis8{=JU@kLOlyfh@>*r$syyjK6baayc*feWEjdV?<@N^{yTgfQaI+qcV@Glv zU))YR6no}v%y(>+<>%1>ss2nZa^8r@5qjx+r}rZS6gsP1v0%K(%y<74l)6?zI2Fmk zkoS*HX#6A5kAiG$XnX*&74qqx?X(Lknb?W%O8Y?A4x^Fz9#jRvWnRB0XxNqp z9J=oHUidb*{8&;H5zm^%0-0N8OFpZ5t?Q^q-!!+JO`0XjTBJzv?;)HuL%2t2ZAI)d z!UL~_*i;v9Av^i^-5>Jp2aQvY0tvna2sNMsjnoz)B)bZRb`y^hPI?mmOGe_9OLgKm z@gtph>N$kf?F)ClcX38JKl!bbNSN^W2PxUc7bCt{560mu;Yj@>?5M(tvOpLIOa_x0 z?3LpG!mGd{6Z1-?bXj`|B*_+-I+B+TGksgKpPDYED@UhVHd@lTAJH?N_%;Bb9;Z!a zyb`oUZ=V~*NkWx$Vg%)PUbOG@!6&jZFOb%S!_#__pFi@twB+YgZhm}HPoDhH)T^7H zpTWPhKXwlZY0MxMJ@avUg~8&hl_-h4jW@1S>zS5MJahh|N@xubp2HVe50k%C4!n8B z=UK=On57t4r|unYcoG+(xu@-rfTa`?oZ*t7JOM4Un9Xo2MG*lDd8C5~yr`GngQ9C?ISTy=FN`!Eob0{A6#WehP{07 z45w#rA-Ys6Q&jK_Pj7 z5^Dy9ygd9PYSv%^F9Ap~F2@y6Z|XPVim`Gd*;CEEQwNAt)ddYjE(5Hg4-Tt~lvgAQ zRrBx){S0=3O)f<-)*CxD_Urc3N1iAwJ{scE0j&d7+P`AAv?7#fSsF}KRY8IPh zc+5=;9`g|ALm}V8)_AB-ghWA2$sqO8#GGWw__j zoj-6}iWlG2e5cM8Kdpq_JfCZB9)kjhlP!l~N@sw%h0|6PU>07WjnY|y<@r)*6MF=U zVGqY%huNm%a6P^oMB*Vr&Nrrm>>$)&sO&zz8{IS4PwfLi*pV3g4i?R6_TY4&>f4=! zeCw~mf{hH{zRsPWV44}Vu<06PHIz8LGC3cnb)N1Kdk>*R_;f(wQ9V?IGaf_!4s@v6 zR0M(Q+jkWTAv&$`ds44So(8A$G{`;>N-Q3XJS`rCJRJ)|<@Wea-vQU$PXY5pb3Y<& zrt?H|KY4HqCQgT~2$(QI!C)>TJnF5~w~-AX%sa!UlW^ft@1(v6R4_3(Xd}5Gl5-48 zbOK%9eyP&BnFy9}exRm1A+7^qxU1onc4%MM1fBjAE((^i5N_4fVBOW!Q>i&{vHK@M*f9Jn4asH>7|2pf?igL2saZW_Fb7c%Nv6bywsez2tLT!O6a-Jq*}>DOZ-S&I{ps3fD6-mnuSb zeki>sB4-7i_R6;UKxCa0`(0e!U?Hi?5y~)=(8_1;hKaiYs-^I5%`Xu*Z`OF1LU@~{ za}$LC{HJs(w?igaHcky<57k~Y+HFIVT=@p;#Bkv*2D1|YF&E`yiCVk6>;3Nal?5&V z5+Nw-!${I31cUa=k**8wq9D1lCgwe#8TRhS$N|l67`}7%19qOroVs2D-ZPJKUB;7M zgQUm$hv1%_Uc(1U&pq>r3gG?;6h&h6qI`hWGIzO%{U`fQ_Ms>-$8yl=@335?`%XwD zky@C@>gC=WSQqgp=TnuIT?UB-e4dmfn_IZuwQPTG5!?qp{YS_I$yw8%L%$D(I1rmR z7UmNM4t-XAcOq~JmaE7LWE68mS)tU1b4=Bd-<+ef(C5}2=R6J@Xxuc~Eo}lU+Mn!nIG5p_rB71d>azJ7qyPb(dw%elXbk+i-$v9GE$T64hqV zVGEVl^BUv>ON5;d3)s)vpw)kE676x6o%G;S~4x zm7K4Za-4lF_fLAi*#5P1q3`on=XJL*5j>nfU5?GjBe_t4C_P(pBr7h>jgfOK`(NoD zr@7G^??n%NDDnxoYejO=-+P>*_ot^y(mxj;%|NJBJScB}_E3*VbyHA(j=`h324uh;8eYkz* z@yIx`R}%_=S^1Sk;H(lNS|G^duPlHjjFlf8j!**(Zx*@b!C;P0$jib&e${m;dYN(d znX#)!W0i*oOwkFtBLR0*|Is7C@yHjf#7V5T5msUl?9N1nuQ-UI;O zL{ILk4A*;EKY6iCd`GQiC@bb(DRQal{qb4wOF;l?k5&oxe1OF1K`mIA{R*> zTov$tpbPhTKF(;%$mFMSVgSpo8B7kQ=G>0Fp4hA!-^OZ3;XM3TV{wI8>XdY*#vG8- z0u2-^f;`e;V0_-#gfLCYvm^avdlu!au|W%$SD zijptYpoBHdk3knb{@tM_Q7V!?2Rv7O z_lxjo*(IUmC0f>h{r$=MP_^vJ`lhUj20Q17z^|4xWwGgrQ0JVbqzT^De0M#8l{V@^ zo)fSV4f*6qZYgsSE`B-Y+}K4Hd0l0-gKafFhaMcM9X6T=h1o;@sfX9$v80nFx8rs^ zlGBH!LWwyT7CItVhHYF7r+RH@&Yv^7Ya7-`t;Fhl_UcId2tMI!Q|iBv3wJzZ`{}xZ z)+jq;J!hD0zo323d-3D0mpYQ2jI*ilam_%jC);zpNln#BvFq6YZ?fpfh09a}+_Zer zXZ$teV|Cwo_Wy;x(~NIGm3jM5P-qB^cfG&<^D*f^e{zJ?IDF~v@Ip6ADSNkw+TMZ^19Q0O`4%%8x5QaCk)-)v*|y zYih9)Tcl@}`oiKpr>vOcKV@$H5@I<%cP#AQZe@Il^;OuOMlX7X$gzo&)sTSw5KwDi z4rfR>UO5FO<(6Z}cq+0GzLT>!t||W~Ioq=K8&1HJkYu3s>S5EP(_63RR%~#1bcAkC z?tUyzNnvn(Dta$A1Fhs|p*G^MmMTz>PF(P#GVxUOE8V|k{U(9|(sRC*Xv$}uW zveG@)ZI6ko@?k7)^d!V>nW4kt;~r#edYRy%uf_Y!a1}4DG;D(IF*NaHz zN{+mvPsn}ZG?M3$y%CDHjsOxO`VM3N42X4JDkUcLzy~(8D2_uW64cPY|T2E zxbA*h?J?@!O7+n$Ge1`MdbLHW`?u=Co$g<)lMY4q+I0o;`pG(3DCqv7slWTI2a)N| zGECq;WhO&9!uB&NwD{vKxbkr~lWHxSj)`>K(F#R=z&4E-V=tV+#@DI}`#mYRiF(pO zQ>K<>)j5RJ!eB{zMY<_~_UEWSd?1=WPjrK*eHEnunSV$PEefp@9e`{xag)mCM-0nT zBa2#=j9}BmLwvO?8A(ZH+b^?kLW(?n+)G%#8g``eoN0j<=pTym@jyAHHa%)3 z^sYP_H4%uUBqDX&jA(l7{m|6{Q6s?hH{}nlJ5EJMU$Ti4_sYy;Tb3M0Y|g=M%aX51 zY`)So*u+B;uGyy8G5WDQs3el41Yr1EG}F2-&LYDJY;uu{q_Y`RMZTk zKk*slXzI3kYGcHuhzKPe{$ouv$Is}x1G`aHJE>6H*@wZUqBtnGx3EuN&$tZyND^ef z0CNSwd)emY$fYovj}@t!B6QpAXETIUK^G(PdiIbUY(!Fzuat}_UDVPL) zNX*DmeBT1O>q2^DLSH3bJ;9$$`$#V4yS%+p>ihCk1=|;7A5PT0C6$V6VtJ~}YH6m% zAJ@_>HU5lY89CbGYdM$wH{_qN-1(;JTycDS@Z+|k0Oq@4WW@=_MJM9(jX z;o^5xq!+@+_hToZonHyCDCnnl^RM^;F5Te4qZHfizlA$c*L zF<2w-*<-UGZllXzGR)r0GQBKCPgY_s%h6J47nd__B2_kAsu!owf?dbUqQAb<2}SRc znZ3u#WfR9TPM#q=+(Fom>~-a#R!%%`?3d;b2q+wtW3PahY{(nb-P6J=|mI9 zDY%zoKKiP;sJ*LqM9GuABUIDn+@Sna*~wJ^@?o-6HCX-?&kz&0n8rr+Gkp%v8M4ol zTF{@kpNg1*dooV66wHATTE}K}VYMil&fKFDJC)Vb3x`ZOckxM)4Zf4rgnmK9fA8kT z5z_T<7nX^~{>1Nu4Mvo>!NK_jS?+&y+K4IV`d8d4B`3!Ne_RG!?1Gk#x-&}zE?w_6 zv6rToo|zR3fAUx@2hzr7BIi#YBw^(u@yU(Iv~oofq@m2Vb)9xB?P)goUo~0U(`@q1 zn!KeC`AWz-sPP0Kmzp)wqzUJfI&HZ5P$M%$Q8aX49|3p zB*A?IHz8}D8FJ!u#HlaO6u%Uw!k9Wk`9o!qz-#!ek5N!N$p+uFY6sj_A!_fguy;9^ zOWD)an6AT|7ucGE^wwMc%+2ZtG2)c& zlk|n0h-y_@BwpAYE7_1^^KnU>viUAZwLfHuvL}7Stn5mR6RWVua{egEHS<&dSUzO? zgO?*Y@)5*9=g26~rRf?Y2j2A?k|!TXB+{w_noX88K-LB34U_#3YqI2gw(XUCOHfS< z4wdmumu50Ov{5>po_`6+s4zRM-3};y(M-l)EIClZAJxTlennwnkJVaUp^XK2(!K4F zS+j%;32jvU)Srhos;=ixLK{_w^q$a03X|2H4sAqQt?uMu3Qj_<({^fOm z3`ktzU(om`sdOI3gmlZyix!TT1SyZC9n~If7Nk5{CrDD~JP1dePgtS{SF6P{p9L&=jz|FWyk0alTq-HRVe6`8n{fZvX>cczFM3z71`P6h|*7%#P zboos$Gl#8)p*!7SXj5VL6K?;D(IsQf-$#}|p6&h)_d_*R;-1+rdQP}+#(r#-H48KJcZKqm+ptNb>b8ZvI>fis2Ws1 zurj|rZ>NZsc?RZL11I`KIfv!T(udtcbHFR?}7yH=l%dc#=|Hw>k&msN8FCS7oxT>K3h{{3j z`8)GEbK)WHvw4{v$G(1xnWw9=ubJ>~^C9>*WRNvvVut^Sf+f|2{0ez)<&iSp!qZ7R zA=QJtPoTJu1_yYb!gD;hnD>010Jxs_4|s~eYk14q0GY%K@V0r1!EL;cB(N#qLf+*( zQLyZ?{3FkFa69iQR6JGSAnyTGvUT7>-ep8ariEnZ-?xs`y5_5R%Y6oGq04*mC^kHT zTX{sWKbUu)-mR}ts=!EL->8*5ps zz@5B1#_QX?ck=$)Dfk6Fz=B&9(3NH zpF^6!a_z*eQ%DQAVGbwtQHYF!JX?9T^X%v8Ifh%pd4fFSdED!XxCH6zvB2z_n!x;6V{P5s!0g7r z>;P9Y)pIKpURmd!OuTsNNcX(2!{c!zD<8F`6#cRy`c6y`7mG( ziZg4tMd>_i@*I@W%w5#5V1j7)ux8iG9Z%|ps?!%$$7*8}P`X(=dx0f4S)E>AH+%j< z!^QCY#`;B#^VLmJnOI2LN`xk^JxsGsK433mfOwHcTiJUDTpk-1BmJ zUlVmnR3-|UI36y;Nf-PPB%NEe=~l#ukS>YXA3Wktcp% zb>Cy$x294rESPk+Lvo43>lC#+vAU4fU%Deok+;H#L zpVkfT_k(@DA925%Tyq(T$ZwhZ{kZbGkZ>TP3_$4=gq(2#<~Ry7uDZ{I{T)Z7dPLsB*W8FPPfjM zlB(6STQ@avHCoMtdKB)<&26=$WuBWJX@9bRGQ}dlzVuD5J!u28f7@Joi%abE^4q1W zUFetv4v~l1{tO#(-g(*I-Zo9|ooy!gzpL*rFoFB%7B$4q86z5~W{Fy&S#I^(IOb4> zQoqfro^wdEd9|}^Y8wviPOHLiIHbE671tpRq}r7L4{3N<1Fy0^q${bs4{1OnBlZ6w z%|yG{Aq_;`*O?1zoLZ+YNe<-idbmUHT>3 zzqbtf1f)%WbgXB(4y0*crR%HFtMnyx+PXkGXDaAZYT5@NP3!s>kM_AirSvh&RjjTD zY5#r*x<=8qfVA5a>2qp(TS1!k8t5WrZxTIEO}hl7X+`uvwTqP?&9z^GG>7T}=$}?@ zzXQ@P{tTL_Xzv>|`b5v?`$5+#({&*2qGpU|dK*a7-UjJ(d}z>TpzD;|<4^L?9U#r2 zbz?mje*n!=_6DEq(L$gqMY|ECU8F%ey}t(OaQ7NCn7*Q>odnYMP8#QN;|h?D-|ZmH z=frr==bmqPreA<`T&ADu@vj-A-KIfWCSNwDznOsUR~6H(pg9V?3DPk*>NL-nvq9RI zX&}v)%MI-sLyH;OErxcdp{+EudkyVZhPJ`bHXGV5LwniKJ}|UT4K4q4FMdNoI(|il z_DzGP8Pnf@bj}nOdu~qyX$~zgw4^~lG3XD*UU`Y<_G*J}097ka?lQDJ2JJJ*F(^3E z^QGFL+dw)le+B8XF!2n}-duwggLG~^XlUy}ItF_UZ9ho+S2oG>oByJ4DDS*`>UZ1EA_%11=3*@8QQ6acCMjKGqlSM?HWUCFtjCxmNc{<7~0Pb?G1z8 zHl}0F@nZE2kd75bbVHkAkhGfG=PE<1F=(DKtuwTG zgJQ%9yS;v^55;HKz9&+5-kXWK171v~>n;G^Xu_ zw$-5R#&n0F?KJ2GW4g!C_8Qb_O!pgFmqG6t(*uU~u|Yk?^zVjd`MkW$2kAU2Ftnit z6&h2S?VF7I0oG`PWY$l+4H#OHLF0_+sfH#K>e?5X8Pskk8`>0ug2ps#Xc2>C_E5X6 zG_>gk%`m1j4Xw(c8e=-o&}7z8$Ex0##tg05pryvN#n2K4wHnhq4Xw?fmBw_Hp{+J( zjWJzoX!jZPfH8f@&>k^poiW{LXzd1VHKyAQZHGZSjp+-9w#T5o#v>$IaIU9dA&;pdy3D8FZ>a#Rg3>C~Q!~pr}EW22D3;hCwq8sxqj?pf-b6 z8nnuw)dsCGNM?|w_llN#gMtP{45~D!-JtCT?KEhQK{AgrRr%ay&;f&b45DayF)*mm zpwR{e3>s&UtWW4LCL0tqC}L2hK{E{M%=g@OfutPytOEx17*kn1(WWfGxJcGEbhx7p zEnv_%V_IxzlMMo>T@W2lv{lVz~OEc_z*j5 za$Je($N=%l_&geltSDtDvI9wYpP`%yMYxxtgrT(OP_BRyB$*jIv!Pg|G?VrPVkd`k z3lv$C%D9sHQDy@*Wp-oryxL~Vsv;HIpPTAuRoBgKY-}+UVT9C{vWAuM=hskVB`ZS_ z-I21Mm7z!-CaYRPAzJ*Tj*_*l45b%}tZ-#0!?jgw2=))h`EOuH*1|Hb&VwQ=Vj0S% zP-I;!L%GiNdGJ5*c?ou81uf%B=F(*yEkjuiMOM=?lwU)UHMI=oaVWB~rYY`pWMgNJ ztV)d|D{dKA`@~fav0*%`A}q4E<=&}MAqgq zlvz+@g)T#hi5*7ano=E$HJ-+3wVgO+r0%=oiqUq))mm}IDxRif>xw6{$x~U~lO9y& z_y3oc{Qfs^PbRLpzy5b?^boDvax7^r`kJIt>T9Dko}Xh!J|2~n@}r26E@?4yf7$xr zDRkJ8lHLEe$@PaK=9U!MGc7+U1v&|iOA+bKv$&g~y8afiAwREted*fKl)2S)iyCXS z4VS{QV2wvGu8u@1^-uhn+gMwBqen1yzM5l4j8ExDDeXs*J6-k9i{TahDA(suShx>;i-_4=mbJn%kUVQ#7$Bwvqupeb}Kgu)xDEs)tQVn!;EAJ05cHHzB1pP4%9&Tr+cxh^%K6<(jG6 zMBJ)s7He9w8s{&mwLF3>WzACZ<5ApehYv-|aY>t^zSVLM**Qx|nE6t{x@kH@gmM;% zX6f6RO{652DtzNx=1Uf4^zF{dP<{3>RT1G*@7eXNL+P8a#jaYOW42J%q%|(Fa-*Rg zs{583W|6*(zut0|4q51PW>?=hOYI=Y^+U`~DkqtB zGR3CM=RduICgYn}?c58Oox# z%XwK8@qxv^EWXG^X4}ikgXUR{i@2U~iDFdqEK+gC z#94C})l+M#DAnAuFzdcn`64M{t$Ac6D`aqss}rspf+6>O~8LOWNz~i_lfbWTD!_;>pO(v(-BJTsJ1l4%;kh z34Gxqsokn&0U57rZ)%$D#y9txa+i;aC;E1y1=>sRI-`Gnb7k?FXXu-9kfC|jFUb9|**zUG+RszPocmdBM}`Sg zOWEslb7d#Jh%mF@^&xR(S-W_Ghq<}3h#A)GU+@sO;PhZ&dOv%Iz6B==?|uxA_aH>m@<+}d$ftV>le4|qS7mToL6p4}>%;32`}x*r(dlxAlXIF!s@^T< z4Tqty9)c(g*fO_`OTHyZDjMDIqOIYo9DNOulJ{j7Kf!V$^rZ^>3636jA4fQ-v_gZz z(xS;N%X-K96K~-MXM$Qvt){own|o`d`uzyn?znM54ARpVa4cZxOSnr#@((@{L@7gc zWkIxh1o}=mA3O5$s6G9q!cR5{f0fzLzGm^sgBO1-Rajm^Z6Mme#Sc+v z6>lFME#2O#x_lj#5Zx=7p6Ev$UfPXjN0hbh|uzV0elTD z|4d%~#2NfOxGCUID8;(fDAuYh?EaD7^-XsAIP4{P*&WE7CJ4p9T()ee|M4THrAIy* zPRA-y#ns{C4hk>(UJEV%vW2Mm?|OrblcNQb!>L%&xbnx4yp{rAo)s?rTlofTScB_& z2Za35zm%{${>icu6;J=8zIac0EW&$A>1{WqD}UeeS;^ud<^Fr0_uqaZK5}ernSaGe zq`tiRg?Lw44aW!#XnEz)5P#zRlH+wymm5aGtb&8N7z zO1ZgcXhrptxG6t`o0d{!d3%_B;o~ClJ-y}eCs5Z`*5gdzP=Fh67_`|Re;Ti%>6^Hm zHHPGuE?GPpK5{%lY7?WnMCC81j+{0&o5KKsqS{~4Va-H;awngfJpnC7wGdj~;^g2< z1S!YsnhTu;z_yn2i~PxB#CrNtB1vwSiS|z!LYAfH_BsPGvU^%~_<{#J@d2b7`T{a}t^35X3Oh&4g z7L5y+et`u4)hSc)f$twU=KzB(&$S3XO_2))o+RXh9RYvRh9&Xm0zwqM+wtendj5ek z0J!{}Ud;H4KbP-($N>z*^&7D;ge=<#}A9 z5~IK=8R<_~=oriKw zk0w6}IqH(TpH$U_vx7+MLU=Y+7-iip=+0t%%j7TIK-AVrW$094f>7v0U%>~4g$0&A zKQ+z$&Ue4h(BBB6c6^flri-HOk8r;|_XFJTJlFn5#1H?!;<+S)eS{i|VvU{5=}XXi;-C%^zV5N5SO}=VF7D+?kvq6LYS6LM<7dSY6TuK>;_~ z0yy8y8Is*x^Mn8wN6w{a#fES5i3W=qt~L*D^4b>a)fCkZT(xfdQB-e6>5&$s@msl; zA(CEQ)Gp#Jn!;XG2hUd)$&{*`Od&*d`25F1an1c?MG20%J;UTnL{v<3!n@>Ph5a^X zS=W#kLMxs!)}Q=>xQ1G8^U(xP#AhjbQa}Tyy_0Iwh+l5`R57Cj?&YMO{hn70j}|Fw z8eEpXp372tn+9Oy)zF(d2ZU2A^S4Tjt2gFv=Nfay=!ME-Nt8NE+efsbp8{h3#IkH;P2E_ zB405nJy4c8Ow*&=X{l&XPuTmS_;3 zjsb4hk0liC!K>my9**%NPaMj5ayb{JQV~fdRIEb>HwU@J15u1rqx4v5{fvmx?`Y}_ z-5CMn(;)HTTjE39Lw;-sH{4t{L5kGneCNfE*ycNhmd(e9Pd)h;LK*cn%om*U&#(siMk}QClXI2{<5O)v17qKQ)d&(JG!Im2}fX=pL85m|>ZS;S%H33G4=BWQr88q7v%VF+zlZJTyH8O4 z4eq|6+n~z_DirV^M_hvuD?mWG*sSR_7?*sOXyD;wX$Hq$N9NUvnPAhsVSN;nHVBPU4nbtEE;eNpxPr zOvJEhILs)F70k7ZoxM2b^&+ozb4jG)8Hf53x4_f>l6j#s8@h;yx+;V!RRSYr1HEP{ zzV8!#ZWaXs-y%8o%B@l{EA}Tp6;IRGQG*{`cAPVZ%<#rP@F(8w^WXk2QhVjF=q=|J z)C8=P#Q^wuTS2Jw^`!%%<9jG!!?qK^T>rSubN#39YB*ZjxexunbJ6lxQa;d_$Hfq_oUc zgvlv!Y3@SniIf#VKVj%G4C!69i!O^|RfM(?TqK<+k{u8_3P>{TJ4FmV8&MnO>gDnG zeC3~fL>`YkI>b$F^dmn*-9xnWmB!aO(M+G({>Xkx#iL^UJ7wcP50C$>jLJLlTLL4u z?>Z<WN*?$Txe#fgSKg2S-= zQJMX0_faC>>1n-kK7PEIa=~D>n7`p1!%6z&?%P@&xqyVgd*OrfJR$o>!b}KUDo$8Y zQ_KpwRm$sRiljftt#();6e1lf6MhE8elhl4tB-hA-K_E_@+7CQB+X3ki^>~XV}If_ zVn{nm&w|bXqFzEyNePpF(C?s>amhq!P0{4WuQD@ohW&)%R_2LP*VJUjr!r33x`#cvY$`%p*TO6xBa26--qG7L{h}m2lgEZp)PtTp@&Nu zp8iE{=japqQfSO>`22V6Bh{hw%(HsChqt9K@RjcIC%TCyD!+1^?03p>BB7*bsPZ5? zmXMilKkX|asd{V#G;wAGwCOG9Xh|od?aY#}Fcs3VjV^_$k%y9Y@RIRde=JR7R?XD|uCNtP-$7`beJ-x9=cG#hruEO3FNv|w=h!&Qc!$kYh^F%>3bbON`8rPagYtccG zMmeOkSTbCbXpfUYS`U$IStesNrS+R08KtoMUsQZ#2=2}ItqrGZ`p@@~FZTPP<$rI% zmt{vYAJjCY3?-0A`2HrUq4z7Q-$zl#0#Ow=Ahj|75uzBaek5NsPw4qGe^QQSs0!VQQvmCQZONwn4mn8V&;D|Pp)j|K0SKesR2sYxqT#525I>W(q1Ry$A1aS z!@g}YXp+00)p$+vCU?A+8h~BqMDw;;VX!&$!DQhEXLm^T9Ce z098lVum3`^lc^BV{5IJghHX|+QsXdT3u5WF&m*RUmKlhV1T_we(*`m_TZlaN=8VFY z7FEe8ESNP4`?Ra~ZFoq3q$+{Z;;ArHWCv*?KU%pXl!^Jx(p~pIIz*K0MeG5LXWn*> z!=f2)tH?!Dnvv=%#;+5Fko`p{{#F5(sMAd;h20g^?IHS*lnKURTg#VIf2na;XBn#* z!w8CCwpn9D;NtHv;QESc)G71LIOblT3f}=)76~eOCoWiTJxXjxOWR{d_#Z7y>~7jG zUAzeP@zbAZq^ivESM~TA?@*MvrOeBCHLm&wd?i?xDayFuhm`|jy#`vibx0(2ZX|sb zX&)g?aV$H=O^ z%o?G;X~ zRh)C)z*Ho#X;}OncL?T##1QN=8XYwR6Pc6|*sbJ5UzxnnxgM&LkK~o4%l=FS#WWmT z8OYcRJ##YZ3Q099V=t+8MKY3q6?aIo)X)CAWP2)%pssM+y`1#n7yL`dCi;|8!~Hm= zA(R_6-C@|l+X~7`KVHT#>_ER^*a+2r(L>Hge35A8g;%NGTqP5tI zFrXS|*A-2!u-}#S!tFBtdRN9@48M*IwO-EX>nYJ!$mr{h3cK6x3fueWeN>Ep9+$-_ zT!zQLQa1i&X;Ra8ScY`oHCobQ?+cILEDNDk6{VZ~x4%gSl-WC?^!&%afUPFKvlEiy z3+1k1gy*{bk(q+7nvdsYYW6|Jj6txNvdz3Q#zGk&?^g z9rD4*Fg-^^?yfk#M^hsRkf^xjOqB<2?@C|JijER;B)X|f6^hV$C9G6la^vPUYl3RJ z1~9fdDD(IOwpqneO45~5el_F$iJM3%aYb*cSIpEHsz;BZUc#e_(mywxjd9d|B}%0w zH#wW~sp>+SSzSG<_(V%LH+5Bv|1$;YG+ldrBHgoeIcbEm@A83X_ER~csfu1YR^oG> z!aUQyR-~_CodIVLQ_DIx=sH>Wg&s;N%E@C$GW_~dEZr@NiOcLaR4c0aRo<~pc;bwc zuDNJ%y!&Se9rZC|ddidx-lS%B5;AhLcZrt?QCUdlFlZ|!sl-)P#!NE~@HxN1EVM1J znD|!M&pUFlw%x<{jIkLERYNn$TQHq!e{zw=gu=`$SZY4I0#N?R%dEyC(`sC%Mq;}3 zpD5*7FL@jTlqy#m0XnL`p-YSQ)pjP#sYRYAK`bP7QBcr>s&AyEbLYG586}UZK0Y$S z9q44Wu8&(o?7VzirD85#h0>Sl3=w^BB$CwAe{e;_t8X2*zHoXZS~UNeS8ji4%v{^M5gUL3p z$WwYL5G7Ai;++eiXK}Lo2?mCGU{TVpMVu>9)1#!5taOuhuYFtz#4v*MY8|>DV(S(Eax!pov-?HQcMwbWKr}^xz~{)!^fB{rQ8YKmX6x@2TK|?i#-C&JPZy7m|$! zoASj-c1~n<=U*Vkve>eRH|!%K{$w+0Vy!VKi!GTBy=Wa)E|rlqihHH;p-V5TEuG+X z!e|6OvR&KLv(s72EzglkS#A+F(FH6fkIZt5+kU|+)TZhJf&Sc9>S87GQuO7N2Rcfn zckW|~e9G8Z1=HuxpkR6VR>`ECj=Z-{k>yz=y(o|6gsQQ|$De8+^YATV|5Zi?ODW*p z|Cyl8LN$UXs|{tURE1^V+O`4nqb$Q>8-HlL}MXV7A+C~9cH(u_Mg@D^u&w2zuV4+zS+ z8*}_-6(=Z~gp}Jd5Ykyjq%M}aKO>|F=nKxDs7X9|)cx;` zN}klh%@}&@_7~CWCux?{g!62&!>rjnD;I3LYc>oOXwQcW*Q>k|!t6J(6{#Mhq7YRJ zI|#CKZ{chNPE6Uy$S=~wIVMT@?`&IQ#L=B@<9EG#6+>+ufyMge{ zS&voIzfgHg-$~YFl)N4QQlhtaBGTfh-3Cps$5N;(ASw1Ix*tP%Mae>-;W_LTU z&?P?{|C2SaMy>Y9xJ%~C-4!4IU6=Bqf{}4{rXEq;4!Fr^x{f5sicsU9_3Do!$x^d} ze?wwIzSoow-SnngB;nW&mwtriO%bQV_!)a8Q~$V$aE>JjdeT(JCNj8DoXW0-rIZTG zoGUSv!eGWGqn#^pZjW{@={q(NJ>Y!{$Ax-{=o8d*~-b4JE;7zKgm644|MS6k^=hPaR>c3?Bn@J{+~YL5Cl(vkDMo|z9iT>RvAIK}8zGNTObf zDl2(4v;o^{C5kTiR*^(nZ@uiqm3^kXsP(5v{C&nhA5tWzkFr{?G|NxB8#`6S8MY5F zBpUy2c>K=r_}yg*R(I+NONJbx0~_P<+x5cJ>Y^4xjWPf@feR_R2em~@Uv6Nc!C@DQ zuQ;3@IV4p2F1MZ7&!j75-AR_rY}OamvXknc7vV9&$J$dh8BFI)aw$;*hDsOvJ&;U& zhowF^MGHfgOsQg}X1~KyM|^>Nl4-J7bXBfhabBEN=##s#nr87lHJs67SaaK-_yxg< z)frxenW=w7D|mcMX8C9#F&8OQ;mF+V6L39J%6PHiEW>Z9^$shmml6e6PNSt?G(9f^ z_QWgny;VWlC7p1$KFIb$qUTj7{^XH5#Z(fA=}&Q@+Z)v~B*`1KAhi@ALmEU+uSYSW zd5w0$Te&)iF;)6IbpJonD;M~r)X4-{#7D_Mu8p9B3EO#AN#H-uLQf}5&QmLeG z^pW#uFV0j$s(CW4-dq@g)Hz#ZF~+N7g3uUk1h*s@(u;HLCl&k0B_%&j0yH zTH36os6|ji_Lt5Wvcqefmte`osQs?vi`PD044|C*iId7(Ej9f*E1xnjbuN**fx43E zxfe;D>lv$RVdty(lj#qzUd2v%Z@r4n{y36pbzS)ZQpFCnLK%*fv~yGAAT|+B-hw<~ zR|%hDp(18&VQf>kG0o7ICCYSv@doSYB@9J9S87>I-T(E939RdY4(tqsU>uWCTzoZC z*3R@j91$pJ1F7_~)ap5vUb~JKjlk^`vpVcmUA?o(ubM0F6+H)1Zc@cYMQLFgJ z9Zu;-G$gV?71^krC~8xNvT|VGS+q)h#Jocck}8ve$(UJPC%Y*qAqA6(?|4Z8jcXp4z&vZ<ZT*e~{C0FxY%QKs&mIsCKmh^6J;%VZ!g(nSdIqxKoE#Exf z%li$!-{QHO z@Ar8pc>j&}r##PqeR`aakX~1kE zJbwUO#`_wcbzsqjB8y8?c!E4(9?^Re<*DSE&NG8&KX$u#-s3sI^D$2k&)<10%=38) zc!u&6@{Hse&2v1Dgi++aze~8q;7L3Z-aiX>CU&ZLYIx@H)bZ5w#CV!{mh!alBzRhR z?&N9XS;@1CXApU`hWA>Y`*=>|`yt+s@T}w6$g`bitNY%;dneBeJbQTd@^tdN$77AH ztFca#KYYtsA-32@nd=p8t9#{}u1G%5DxQ_c5+C$~tmWWAkSD?SeLN5F1Sr^vlL&t- z>Hj+ZpGCnzO#*0-qNYmC+IyCC0+-UUbzj&zPcn>W#XoEqU3_6{o0NU*bARVjGCwjDEgBn0O zRu3E6kTG7YHiEP-`$0Ol&Z2~B^e4)xHnl0qnl==IMzsb#Y|t=DyEa{7(6a`KhFonb z+aI*gFB{sJ@t)~rAZ@zBpob0GV9>5_crNlz@z5CtB@KGgpuAH(pQnO!T-pq+e1gZx z1W23SZ_qx2M7ypwy_6n^j_LIVZ2)Q0lPL&iDtVa+l5^1c)?J{p75XuVprQQ?qtp;hgH-og>J3-p*V2T9M!Iwf12>_jM&<~91j}7ff zgRrdbV9~lZ5j<;v>d7G}prOXJ&>)I}rA-lW*R8nIZUe>?v2tl-zKbL^+ARrpX(H9y zt)xbqPBFBgL1AMWF|?>bmBw_sq0KO8rZKHDv>Jov8PhsLt2ZcSOq&gDsX;BqG+}71 z2Hj~)+YD``L92}EYC~IN&{|`9pP@Zq&_l-b5kp&N&_-k0ZfIK#+HOpD7}`#QUNEM6 z3~jGLoyHWP@+}`}^H707Lk%i4Xrw`-4LaVSfI&qDjWg&}gNhBBWYA=TrWh17C~Q!~ zpr}EW22D3;hCwq8sxqj?pm_$>8B}jj%%En2mKxMzP{N>AgYGn_&7hSAtukn}L2C?J zYtVfLJz&s720dcXI)gSE)NasLgSH#A!=Rl8yX__8^`m7{23%mXqq)pp^!# zGHA6yYYbXz(0v9yV9-MbJz~&0gEkt}ZqQbPwi~p=pq&Q2V9*|e_8Qb_(0+ru40_L? z0|tF;P>(@>H^|EKxSMZKfk8tJlGBJf7e*Q+`}Z{Mc!L54$)c1t9cR#~1{E7L$)L#w zO))5FP}rb|K~aM$4VrGy41;DGRAo?&LGui%GpOF6m_f}3Ej6gcpoBrK2Hj~;n?WlL zT4m5`gVq?d)}Z?gdcdHE40^<%bp~xTsNJBg25mQJhe10HdcmMQ2JJPd)1U(eeQZ#V zL4P-h4wx$ka^P4?M1euFQ$*7W4H{|CXoHS7C}2>LL89eW`*Ny5veQY^CK)u@peY6g z4GJ41+Hkeos6kZHmZ%Y+=|nt5a{GUJc5zH5l}Al?Hk(XBPV?zCcA`PY<%O?7pr z(d(A2&YFTn>mHt}9Lm2#k(o{LS%>voC^Em93F}#Lbz(Njh!n*&4W*gdpwGI}vHk{QBz}-AR7$%2;sG zPf4l#5GwpRRpIPE{dJB0E!)`O`(1w|mvyeH9p`*W?r4g%f8I}1UhYTvtD$&u=sL!s zNAYy|Y6>zRTU6)yD|Vpt(e^2(|KbUo@n?KL%Gv!W;T+1``leX57Zh)8c$u*y6wwEq zqnS?>4jP@9+J{5xr6k&-g03;PsG)XF(_HR5v{0J2s9H4b>3XL|PlL^>M3r)h)>XH_ zn;Ww{Ls2g|J2uy$!E(LX~0WLn*miaP#3@=4g-X<7<{#iB_T~ssP=Y zL^no8$=*LorH+HAj!%DiHKqR2Y4up?X*1OP(>C1sNH5r2=Y8Vj+0DtBL+C=x4QJM@ zS=IAyY>eGFYeAzmYu5Y)^-yM4H^gSmUo>ad+@^)qP#16^<>Fa4d%;f=6@s}666ZIn zY{)Q7Y27pymC{Y~C8BFSM3bWW@U##vxG5Ghss;mrfYu}kFj!O0nlwq#CYMf}s6Zg2 zZSeN5>bVyghh*1nBG?Cx*4hR~j@Du>1uO8splvWrI4ei$FulJ)tG~9vDH!g-UQ`-v zetsThuaCCDHI%}Uv|jsMd&88ys^IC9#8u`;qhme7%0Tunh_=DgOU}$Dsnx;#*sFne z@{?*RScttzG6$Ub6#_rT-on22&dRNy#a=!m1K-}#wvPE(Sq4^&@f1fzIASJm{c7@Z6f!^gh}H zIa08^cm(WD{bn*R+522wjerxY4pr+xn6A75%u|46^T|ZjpODI3mdG`=Lmk}{W%Aw` z3pC>#5#h*q8vTm0gUum6oTSO)>T=n&S8hMS_Shl*gpYv2_Pgu}jPF|(+2kBi9{*yQ z|Bm0{Rs5-z3cCw^5YyRxx2bEmSU_8s|BnCEhL~I#wl`NOr{$ZRQRVR-^vU@##pqka zS^AA^&u8PGzVyC4T{rN^$a40u^!oiPE+A-cn}Y517P6y9CG9j^aSEXXeSn)#ucVR~ z+IB=?MfyT^0?jO%E{6_Bm9*QNIrhP(!J#8UtwRgLrJW7$<6S+zhSo{DCSMFh5@Y|$r5Yb|nOW57Dgj5N?mxu{0oDnH~!k-u>U*n%BPYJ6PLcR!V| z4#fiMlT=DE!B$M@Jw^)04}_xP9oi@rl_NX0UAdf!)~}Zw*^H@n#d{)?krtM_rqp)nJDgdrEFqo<=TkR3@a1uYS~$N%WoX{}37_f2cf zKV9Xp?B6eT#^9}Ti+w-t*x~kJO9Aq8Ksku{#er7Y>GTp#NqY(UPzRCk5qlv=^OO|) z*F`|&Cn+bsBwyGS)S@J`Z4ZUb`3SN^Y6h9LLFC_)5T{PWJhL-R_|&IX9Oq)$Hn8r+jp)>k2j@-ynPCIGlKTg}sYZM>**kpfXci{9F!+ zBB^$Jn?Er@Nd<8$FMTT3SU&!#h|ggcc7^?-vZ*RVo0=?QQ?gW{XH#?3UR2Oq$Z@D^ z%TkFVNh3LTZ&t!W@r{Z+$iLzdOhXx4N=&QsZ;$wPiUxup!lr%gkO2z8IFXJE3k3ES zA`tPdYz3QjZD?lbTCF6O-EZH45%&rsBB@`Acc~RB2C3f*L*hLHQN77P*uP>9A;)_- zFFKx2Imej%Izj2e0fQ}^f|M{3j#5{Q@3WGt zNqZTJ6OV|{YDQ^0Y0dq=-WA#O#u4SdUD48=jRVUP?ah0m_N9UBl&E7jEqD`3tt{G0 zqHI;L@H{z}kUCm~Ch|ibbx_!}TumG8@>bsw~%O16&LaqO;wN1=#y{{ozkfL z{CC`dlL)#%slDZ(bfjcAZC^klmld0XhuJqh_g~@uzYjf2mn%Qpn+`|H9|8a`+zDt6K#*R3;myaI=AI zmoVKBWw+}1E6Kr^BLjZWqm0x`8EeNX93`(=eqTuBBJo=b+1OtuP`62KIqCi>o1{s% zSErPb@|LBjJ@MP;03R?eIk~4%?F{ijvNVik-OMAiG1HcV=7doyDgQ(egDNR}+Js*7kb6%691 zHksQ`s3u?3C~&U*zf@PKS|FOfZNNp+wQj9BQ`c9m;WP7eyd^+BXrxFDJZIr=?Ng%f9zpmO^*>WK3s zrSvn(?LocAY7sbADu_FUOhM7@gcLd5z2IotH${LB6(4`%c9-chsM|T3btRvV@sL}i zl&kSusIMr%ujr_tqe^1)BXMPy@myOVkYq>shvVHs2Sh(&7A3EcH;B zTJ%}}=A0_fxj|D8SD>UMxrNF(k8&b?YG*bji*W4^BozBYJ>-;j>v5#t(&NqxoeOmA z82MuD@QJvD)?E@|Z*tSXbipV$9sU*nhKHH7jKOY)>Kn?s2-UMxH6fiKgwU0|c(GL2 z%)AVal=k@Vd|Rw?Hp{Dm?Z?C(V?C*T( zm5brjFUa3Y9^rw!7xOR{uv&PIBBN!BF~Iv>vf@;*_nTHXpDTC*<>3JHuh+-s1s2S2 zWE#DCUTw`efp3qkYr59DvXP12K()3wzb5eYv5jAcSlb|%90le#24agA1?pxuTwm+C zka_yWiyCSUX{bXkYiL;15Exq%Xyg(a@xS7->C*$#F1_TEfLuaT+ZeNC%6C@HA`H(7 z$dx#?#HZ$3YuciP3u~)m^A{}))XZ<>4k7uft+6g#gwEmeE5wVkX=-jxLMm&nSH^*{ z#S@$53CwAV1+K@gN6_)PWRZ?RY*GFE>cHGZO$%#I3tX_ML2Skr1+Kh28qk+41?I=j zw>mBB^4bNnnZPFInsMg@#xAJ|$a+PiRWZAH{(`0j0lBy-AU7ceYMZNTYio#Q8NWb? z--V&_ODvdpb8SOzI<8PjT}Zg|xEzR^p8~hk#;lQK?3yFlwauWjlA^g0JcIX49$}qM zMdokznv+mlTqBW$^HeiKmHr|+r*2XjJV`s(pO@c&y{OREEP%WU-{7nsh?_W zUHsqO{p~vYFTbRmu-Vtjw`TBH8jO7FdH!-WCFmW4?xBFnRC>PkDCh)*WKRm4hoOCG zkSJvhD4Gmev@erD+TIk)n}Mj$!b-v0r8UHP{Qbh1L-#`H9@P@7%@ z(x%@x=y_v$Hzh{fdl01U^?-C9eU*jVamwfUAf3~1f^>S1qLk@$oC?xz%RxFt*MW3Q z;~<@)Um5f}kmg@6NXOvoRLRONXPGKW4gzf9>>hI=D{fjRf04(R)I7(dO(^Rg)BO0bS6mir4poLun?sA zayv+e`v^$K`3aDA@vfnL3eqm7QAcPO4}!Fdbs(Mct%kM>q*J~Jq+KjK%5(8ukaqD) z&?$fR!fen$6Z$v?%_gz z1v6fqyG+>DNre9SwFoKKodv^ab5*$sTTVD z-g3XGaItf0A5;B#z@

public partial class PageVodDownload : Page { - public Dictionary videoQualties = new(); - public int currentVideoId; + public Dictionary videoQualities = new(); + public string currentVideoId; + public VideoPlatform platform; public DateTime currentVideoTime; public TimeSpan vodLength; public int viewCount; @@ -81,29 +85,32 @@ private async void btnGetInfo_Click(object sender, RoutedEventArgs e) private async Task GetVideoInfo() { - int videoId = ValidateUrl(textUrl.Text.Trim()); - if (videoId <= 0) + bool parseSuccess = UrlParse.TryParseVod(textUrl.Text.Trim(), out VideoPlatform videoPlatform, out string videoId); + if (!parseSuccess) { MessageBox.Show(Translations.Strings.InvalidVideoLinkIdMessage.Replace(@"\n", Environment.NewLine), Translations.Strings.InvalidVideoLinkId, MessageBoxButton.OK, MessageBoxImage.Error); return; } currentVideoId = videoId; + platform = videoPlatform; + try { - Task taskVideoInfo = TwitchHelper.GetVideoInfo(videoId); - Task taskAccessToken = TwitchHelper.GetVideoToken(videoId, TextOauth.Text); - await Task.WhenAll(taskVideoInfo, taskAccessToken); - - if (taskAccessToken.Result.data.videoPlaybackAccessToken is null) + IVideoInfo videoInfo = null; + try { - throw new NullReferenceException("Invalid VOD, deleted/expired VOD possibly?"); + videoInfo = await PlatformHelper.GetVideoInfo(videoPlatform, videoId, TextOauth.Text); + } + catch (NullReferenceException ex) + { + if (ex.Message.Contains("Insufficient access")) + throw new NullReferenceException(Translations.Strings.InsufficientAccessMayNeedOauth); } - Task taskPlaylist = TwitchHelper.GetVideoPlaylist(videoId, taskAccessToken.Result.data.videoPlaybackAccessToken.value, taskAccessToken.Result.data.videoPlaybackAccessToken.signature); try { - string thumbUrl = taskVideoInfo.Result.data.video.thumbnailURLs.FirstOrDefault(); + string thumbUrl = videoInfo.ThumbnailUrl; imgThumbnail.Source = await ThumbnailService.GetThumb(thumbUrl); } catch @@ -117,37 +124,24 @@ private async Task GetVideoInfo() } comboQuality.Items.Clear(); - videoQualties.Clear(); - string[] playlist = await taskPlaylist; - if (playlist[0].Contains("vod_manifest_restricted")) - { - throw new NullReferenceException(Translations.Strings.InsufficientAccessMayNeedOauth); - } + videoQualities.Clear(); - for (int i = 0; i < playlist.Length; i++) + //Add video qualities to combo quality + foreach (var videoQuality in videoInfo.VideoQualities) { - if (playlist[i].Contains("#EXT-X-MEDIA")) + if (!videoQualities.ContainsKey(videoQuality.Quality)) { - string lastPart = playlist[i].Substring(playlist[i].IndexOf("NAME=\"") + 6); - string stringQuality = lastPart.Substring(0, lastPart.IndexOf('"')); - - var bandwidthStartIndex = playlist[i + 1].IndexOf("BANDWIDTH=") + 10; - var bandwidthEndIndex = playlist[i + 1].IndexOf(',') - bandwidthStartIndex; - int.TryParse(playlist[i + 1].Substring(bandwidthStartIndex, bandwidthEndIndex), out var bandwidth); - - if (!videoQualties.ContainsKey(stringQuality)) - { - videoQualties.Add(stringQuality, (playlist[i + 2], bandwidth)); - comboQuality.Items.Add(stringQuality); - } + videoQualities.Add(videoQuality.Quality, (videoQuality.SourceUrl, videoQuality.Bandwidth)); + comboQuality.Items.Add(videoQuality.Quality); } } + comboQuality.SelectedIndex = 0; - vodLength = TimeSpan.FromSeconds(taskVideoInfo.Result.data.video.lengthSeconds); - textStreamer.Text = taskVideoInfo.Result.data.video.owner.displayName; - textTitle.Text = taskVideoInfo.Result.data.video.title; - var videoCreatedAt = taskVideoInfo.Result.data.video.createdAt; + vodLength = TimeSpan.FromSeconds(videoInfo.Duration); + textStreamer.Text = videoInfo.StreamerName; + textTitle.Text = videoInfo.Title; + var videoCreatedAt = videoInfo.CreatedAt; textCreatedAt.Text = Settings.Default.UTCVideoTime ? videoCreatedAt.ToString(CultureInfo.CurrentCulture) : videoCreatedAt.ToLocalTime().ToString(CultureInfo.CurrentCulture); currentVideoTime = Settings.Default.UTCVideoTime ? videoCreatedAt : videoCreatedAt.ToLocalTime(); var urlTimeCodeMatch = Regex.Match(textUrl.Text, @"(?<=\?t=)\d+h\d+m\d+s"); @@ -172,8 +166,8 @@ private async Task GetVideoInfo() numEndMinute.Value = vodLength.Minutes; numEndSecond.Value = vodLength.Seconds; labelLength.Text = vodLength.ToString("c"); - viewCount = taskVideoInfo.Result.data.video.viewCount; - game = taskVideoInfo.Result.data.video.game?.displayName ?? "Unknown"; + viewCount = videoInfo.ViewCount; + game = videoInfo.Game ?? "Unknown"; UpdateVideoSizeEstimates(); @@ -223,7 +217,8 @@ public VideoDownloadOptions GetOptions(string filename, string folder) CropEnding = (bool)checkEnd.IsChecked, CropEndingTime = (int)(new TimeSpan((int)numEndHour.Value, (int)numEndMinute.Value, (int)numEndSecond.Value).TotalSeconds), FfmpegPath = "ffmpeg", - TempFolder = Settings.Default.TempPath + TempFolder = Settings.Default.TempPath, + VideoPlatform = platform }; return options; } @@ -243,7 +238,7 @@ private void UpdateVideoSizeEstimates() { var qualityWithSize = (string)comboQuality.Items[i]; var quality = GetQualityWithoutSize(qualityWithSize).ToString(); - int bandwidth = videoQualties[quality].bandwidth; + int bandwidth = videoQualities[quality].bandwidth; var sizeInBytes = VideoSizeEstimator.EstimateVideoSize(bandwidth, cropStart, cropEnd); var newVideoSize = VideoSizeEstimator.StringifyByteCount(sizeInBytes); @@ -426,8 +421,9 @@ private async void SplitBtnDownloader_Click(object sender, RoutedEventArgs e) VideoDownloadOptions options = GetOptions(saveFileDialog.FileName, null); Progress downloadProgress = new Progress(OnProgressChanged); - VideoDownloader currentDownload = new VideoDownloader(options, downloadProgress); _cancellationTokenSource = new CancellationTokenSource(); + VideoDownloaderFactory videoDownloaderFactory = new VideoDownloaderFactory(downloadProgress); + IVideoDownloader currentDownload = videoDownloaderFactory.Create(options); SetImage("Images/ppOverheat.gif", true); statusMessage.Text = Translations.Strings.StatusDownloading; diff --git a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj index 0095a00c..cd1c329b 100644 --- a/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj +++ b/TwitchDownloaderWPF/TwitchDownloaderWPF.csproj @@ -1,4 +1,4 @@ - + net6.0-windows WinExe @@ -102,10 +102,24 @@ Strings.resx - - - SettingsSingleFileGenerator - Settings.Designer.cs - - + + + + + + Always + + + Always + + + Always + + + Always + + + + + diff --git a/TwitchDownloaderWPF/TwitchTasks/ChatDownloadTask.cs b/TwitchDownloaderWPF/TwitchTasks/ChatDownloadTask.cs index d228c48b..0f43966d 100644 --- a/TwitchDownloaderWPF/TwitchTasks/ChatDownloadTask.cs +++ b/TwitchDownloaderWPF/TwitchTasks/ChatDownloadTask.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderWPF.TwitchTasks { @@ -56,13 +57,13 @@ public async Task RunAsync() return; } - ChatDownloader downloader = new ChatDownloader(DownloadOptions); Progress progress = new Progress(); progress.ProgressChanged += Progress_ProgressChanged; + TwitchChatDownloader downloader = new TwitchChatDownloader(DownloadOptions, progress); ChangeStatus(TwitchTaskStatus.Running); try { - await downloader.DownloadAsync(progress, TokenSource.Token); + await downloader.DownloadAsync(TokenSource.Token); if (TokenSource.IsCancellationRequested) { ChangeStatus(TwitchTaskStatus.Canceled); diff --git a/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs b/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs index a768cb62..e886781f 100644 --- a/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs +++ b/TwitchDownloaderWPF/TwitchTasks/ClipDownloadTask.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderWPF.TwitchTasks { @@ -59,7 +60,7 @@ public async Task RunAsync() Progress progress = new Progress(); progress.ProgressChanged += Progress_ProgressChanged; - ClipDownloader downloader = new ClipDownloader(DownloadOptions, progress); + TwitchClipDownloader downloader = new TwitchClipDownloader(DownloadOptions, progress); ChangeStatus(TwitchTaskStatus.Running); try { diff --git a/TwitchDownloaderWPF/TwitchTasks/VodDownloadTask.cs b/TwitchDownloaderWPF/TwitchTasks/VodDownloadTask.cs index 73d1cac7..2d808d75 100644 --- a/TwitchDownloaderWPF/TwitchTasks/VodDownloadTask.cs +++ b/TwitchDownloaderWPF/TwitchTasks/VodDownloadTask.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using TwitchDownloaderCore; using TwitchDownloaderCore.Options; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Downloaders; namespace TwitchDownloaderWPF.TwitchTasks { @@ -58,7 +59,7 @@ public async Task RunAsync() Progress progress = new Progress(); progress.ProgressChanged += Progress_ProgressChanged; - VideoDownloader downloader = new VideoDownloader(DownloadOptions, progress); + TwitchVideoDownloader downloader = new TwitchVideoDownloader(DownloadOptions, progress); ChangeStatus(TwitchTaskStatus.Running); try { diff --git a/TwitchDownloaderWPF/WindowMassDownload.xaml.cs b/TwitchDownloaderWPF/WindowMassDownload.xaml.cs index 37dbe3e4..446339bb 100644 --- a/TwitchDownloaderWPF/WindowMassDownload.xaml.cs +++ b/TwitchDownloaderWPF/WindowMassDownload.xaml.cs @@ -8,8 +8,8 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; -using TwitchDownloaderCore; -using TwitchDownloaderCore.TwitchObjects.Gql; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; using TwitchDownloaderWPF.Properties; using TwitchDownloaderWPF.TwitchTasks; diff --git a/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs b/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs index 1ff65b10..d8d1a820 100644 --- a/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs +++ b/TwitchDownloaderWPF/WindowQueueOptions.xaml.cs @@ -404,7 +404,7 @@ private async void btnQueue_Click(object sender, RoutedEventArgs e) VideoDownloadOptions downloadOptions = new VideoDownloadOptions(); downloadOptions.Oauth = Settings.Default.OAuth; downloadOptions.TempFolder = Settings.Default.TempPath; - downloadOptions.Id = int.Parse(taskData.Id); + downloadOptions.Id = taskData.Id; downloadOptions.FfmpegPath = "ffmpeg"; downloadOptions.CropBeginning = false; downloadOptions.CropEnding = false; diff --git a/TwitchDownloaderWPF/WindowUrlList.xaml.cs b/TwitchDownloaderWPF/WindowUrlList.xaml.cs index 08e5e914..0f931c18 100644 --- a/TwitchDownloaderWPF/WindowUrlList.xaml.cs +++ b/TwitchDownloaderWPF/WindowUrlList.xaml.cs @@ -4,8 +4,8 @@ using System.Threading.Tasks; using System.Windows; using System.Windows.Media.Imaging; -using TwitchDownloaderCore; -using TwitchDownloaderCore.TwitchObjects.Gql; +using TwitchDownloaderCore.VideoPlatforms.Twitch; +using TwitchDownloaderCore.VideoPlatforms.Twitch.Gql; using TwitchDownloaderWPF.Properties; using TwitchDownloaderWPF.TwitchTasks; From e45d8af9c0d874126791b41ee39a6883cca6a7be Mon Sep 17 00:00:00 2001 From: lay295 Date: Tue, 26 Sep 2023 18:16:34 -0500 Subject: [PATCH 02/37] Render Kick chats --- TwitchDownloaderCore/Chat/ChatHtml.cs | 2 +- TwitchDownloaderCore/Chat/ChatJson.cs | 8 +- TwitchDownloaderCore/Chat/ChatText.cs | 2 +- TwitchDownloaderCore/ChatRenderer.cs | 74 +++++-- TwitchDownloaderCore/ChatUpdater.cs | 12 +- TwitchDownloaderCore/PlatformHelper.cs | 171 +++++++++++++++- TwitchDownloaderCore/Tools/CurlImpersonate.cs | 13 +- TwitchDownloaderCore/Tools/HighlightIcons.cs | 2 +- .../Kick/Downloaders/KickChatDownloader.cs | 34 +++- .../Kick/Downloaders/KickClipDownloader.cs | 6 +- .../Kick/Downloaders/KickVideoDownloader.cs | 4 +- .../VideoPlatforms/Kick/KickChatResponse.cs | 10 +- .../VideoPlatforms/Kick/KickHelper.cs | 140 +++++++++++++ .../VideoPlatforms/Kick/KickVideoResponse.cs | 4 +- .../VideoPlatforms/Twitch/ChatRoot.cs | 2 +- .../Downloaders/TwitchChatDownloader.cs | 12 +- .../Downloaders/TwitchClipDownloader.cs | 4 +- .../Downloaders/TwitchVideoDownloader.cs | 4 +- .../VideoPlatforms/Twitch/TwitchEmote.cs | 9 +- .../VideoPlatforms/Twitch/TwitchHelper.cs | 189 ++---------------- 20 files changed, 473 insertions(+), 229 deletions(-) diff --git a/TwitchDownloaderCore/Chat/ChatHtml.cs b/TwitchDownloaderCore/Chat/ChatHtml.cs index 44e49318..7b5d06a6 100644 --- a/TwitchDownloaderCore/Chat/ChatHtml.cs +++ b/TwitchDownloaderCore/Chat/ChatHtml.cs @@ -37,7 +37,7 @@ public static class ChatHtml var outputDirectory = Directory.GetParent(Path.GetFullPath(filePath))!; if (!outputDirectory.Exists) { - TwitchHelper.CreateDirectory(outputDirectory.FullName); + PlatformHelper.CreateDirectory(outputDirectory.FullName); } await using var fs = File.Create(filePath); diff --git a/TwitchDownloaderCore/Chat/ChatJson.cs b/TwitchDownloaderCore/Chat/ChatJson.cs index 2d013c54..b1704471 100644 --- a/TwitchDownloaderCore/Chat/ChatJson.cs +++ b/TwitchDownloaderCore/Chat/ChatJson.cs @@ -8,6 +8,7 @@ using System.Threading; using System.Threading.Tasks; using TwitchDownloaderCore.Extensions; +using TwitchDownloaderCore.Tools; using TwitchDownloaderCore.VideoPlatforms.Twitch; namespace TwitchDownloaderCore.Chat @@ -71,6 +72,11 @@ public static class ChatJson returnChatRoot.video = videoElement.Deserialize