diff --git a/.env b/.env new file mode 100644 index 00000000..37b3c42a --- /dev/null +++ b/.env @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +AWS_ACCESS_KEY_ID=secrettunnel +AWS_SECRET_ACCESS_KEY=secrettunnel +AWS_DEFAULT_REGION=ap-southeast-1 diff --git a/.github/ISSUE_TEMPLATE/alchemy.md b/.github/ISSUE_TEMPLATE/alchemy.md index 819ced3e..ea79a5b6 100644 --- a/.github/ISSUE_TEMPLATE/alchemy.md +++ b/.github/ISSUE_TEMPLATE/alchemy.md @@ -9,6 +9,9 @@ assignees: '' ### Present Context +
+Helping words... + Where we collectively investigate and interrogate the problem space and iteratively scope our approach. Breakdown to landmarks that communicate shared context we are working towards through 2-tiered task list, CRUD list elements as development unfolds. @@ -25,8 +28,16 @@ Strike the scope of code that reveals the most about the problem/solution FIRST ``` --- + +
+ ### Groundwork +
+ Helping words... + + + Introduce us to the problem space. Write out what you already know about the terrain you are the recce commander enriching us with details beyond the fog of war. Where have you tried applying and encountered difficulties? @@ -42,8 +53,15 @@ Emphasis on previous or current practice to discover what is ugly, missing, or u INPUT UR ANSWER HERE ``` --- + + +
+ + ### Reflection +
+ Helping words... Where the eternal wheel returns back to practice and what we finally implemented is to be outlined. You are the historian or archivist bringing clarity to future-yous and us about your foray. Emphasis on approaching timeless solutions for well-defined problem space through distillation by decanting that which is un-needed and abstracting that which is essential to approaching the problem space. @@ -54,4 +72,7 @@ Add any reflections and internal links to future potential and blindsides. INPUT UR ANSWER HERE ``` +
+ + diff --git a/.gitignore b/.gitignore index f3517f0f..c55eb206 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ npm-debug.log # Any Secret Configs /config/*.secret.exs +/venv/ diff --git a/README.org b/README.org index c9b810f8..38459b36 100644 --- a/README.org +++ b/README.org @@ -6,8 +6,16 @@ Wherever there be anything you dost not comprehend, cease to continue writing -- Vyasa, Adi Parva - Mahabharatam #+END_QUOTE +### CLI Helpsheet + +```elixir +# build script +mix escript.build +# fetch from domain/path --storage :mode +./vyasa fetch shlokam.org/hanumanchalisa --storage file +``` * Forms of Prior Art -** [[http://worrydream.com/refs/Nelson-ComputerLibDreamMachines1975.pdf#page=57][Xanadu Pattern]] +** [[http://worrydream.com/refs/Nelson-ComputerLibDreamMachines1975.pdf#page=57][Xanadu Pattern ]] Ted Nelson the granddaddy of hypertext media, need I say more. The introduction to [[https://cs.brown.edu/people/nmeyrowi/LiteraryMachinesChapter2.pdf#page=12][Literary Machines]] is instructive to delineating the problem boundaries for literature diff --git a/assets/css/app.css b/assets/css/app.css index dfd8fad6..8f4956a6 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -2,6 +2,54 @@ @import "tailwindcss/components"; @import "tailwindcss/utilities"; +/** + * Root definitions that serve as overridable css variables + * +--chili-red: #E83A21ff; +--pearl: #E3DABEff; +--black: #070302ff; +--dun: #D4CAABff; +--blood-red: #5B1208ff; + **/ +@layer base { + :root { + --chili-red: #E83A21ff; + --pearl: #E3DABEff; + --black: #070302ff; + --dun: #D4CAABff; + --blood-red: #5B1208ff; + + --white-alabaster: #F3EFE3; + --linen: #FAF1E6; + + --aerospace-orange: #FD4F00; + --coral-orange: #FF8349; + --atomic-tangerine: #FF9B6D; + + + --brown: #922E00; + --sienna: #7F2800; + --rust: #AE3700; + + --color-brand: var(--aerospace-orange); + --color-brand-light: var(--atomic-tangerine); + --color-brand-extra-light: var(--linen); + --color-brand-accent: var(--aerospace-orange); + --color-brand-accent-light: var(--atomic-tangerine); + + --color-brand-dark: var(--brown); + --color-brand-extra-dark: var(--sienna); + + + --color-primary: var(--chili-red); + --color-primary-accent: var(--chili-red); + --color-primary-background: var(--white-alabaster); + --color-secondary: var(--blood-red); + --color-secondary-background: var(--dun); + --color-text: var(--black) + } +} + /* fonts declared from priv/assets/fonts */ @font-face { @@ -10,4 +58,10 @@ url('/fonts/gotu/Gotu-Regular.woff') format('woff'), url('/fonts/gotu/Gotu-Regular.ttf') format('ttf'); } + + /* This file is for your main application CSS */ + +.emphasized-verse { + @apply bg-brandAccentLight border-b-0 border-l-8 border-black p-4 pl-8 rounded-sm; +} diff --git a/assets/js/app.js b/assets/js/app.js index df0cdd9f..0ef6eb47 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -16,26 +16,36 @@ // // Include phoenix_html to handle method=PUT/DELETE in forms and buttons. -import "phoenix_html" +import "phoenix_html"; // Establish Phoenix Socket and LiveView configuration. -import {Socket} from "phoenix" -import {LiveSocket} from "phoenix_live_view" -import topbar from "../vendor/topbar" +import { Socket } from "phoenix"; +import { LiveSocket } from "phoenix_live_view"; +import topbar from "../vendor/topbar"; +import Hooks from "./hooks"; -let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) +let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute( + "content", +); +let liveSocket = new LiveSocket("/live", Socket, { + params: { _csrf_token: csrfToken, + locale: Intl.NumberFormat().resolvedOptions().locale, + timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, + timezone_offset: -new Date().getTimezoneOffset(), + session: JSON.parse(localStorage.getItem("session")) || {active: true} + }, + hooks: Hooks, +}); // Show progress bar on live navigation and form submits -topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) -window.addEventListener("phx:page-loading-start", _info => topbar.show(300)) -window.addEventListener("phx:page-loading-stop", _info => topbar.hide()) +topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" }); +window.addEventListener("phx:page-loading-start", (_info) => topbar.show(300)); +window.addEventListener("phx:page-loading-stop", (_info) => topbar.hide()); // connect if there are any LiveViews on the page -liveSocket.connect() +liveSocket.connect(); // expose liveSocket on window for web console debug logs and latency simulation: // >> liveSocket.enableDebug() // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session // >> liveSocket.disableLatencySim() -window.liveSocket = liveSocket - +window.liveSocket = liveSocket; diff --git a/assets/js/hooks/audio_player.js b/assets/js/hooks/audio_player.js new file mode 100644 index 00000000..7d0cd23d --- /dev/null +++ b/assets/js/hooks/audio_player.js @@ -0,0 +1,171 @@ +/** + * Hooks for audio player. + * Leader + * This hook shall interact with the html5 player via it's known apis, on things like: + * 1. playback info relevant to the audio player + * + * + * Additionally, it shall emit events back to it's corresponding parent hook (MediaPlayer) + * so that the media player can effect changes to visual info like player timestamps, durations and such. + * + * In this way, "Playback" state is managed by MediaBridge, and is displayed by the Media Library hook to follow a + * general player-agnostic fashion. "Playback" and actual playback (i.e. audio or video playback) is decoupled, allowing + * us the ability to reconcile bufferring states and other edge cases, mediated by the Media Bridge. + * */ +let rand = (min, max) => Math.floor(Math.random() * (max - min) + min) +let isVisible = (el) => !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length > 0) + +let execJS = (selector, attr) => { + document.querySelectorAll(selector).forEach(el => liveSocket.execJS(el, el.getAttribute(attr))) +} + +import {seekTimeBridge, playPauseBridge, heartbeatBridge} from "./media_bridge.js" +import {formatDisplayTime, nowSeconds} from "../utils/time_utils.js" + +AudioPlayer = { + mounted() { + this.isFollowMode = false; + this.playbackBeganAt = null + this.player = this.el.querySelector("audio") + + document.addEventListener("click", () => this.enableAudio()) + + this.player.addEventListener("loadedmetadata", e => this.handleMetadataLoad(e)) + + this.handleEvent("initSession", (sess) => this.initSession(sess)) + + /// Audio playback events: + this.handleEvent("stop", () => this.stop()) + + /// maps eventName to its deregisterer: + this.eventBridgeDeregisterers = { + seekTime: seekTimeBridge.sub(payload => this.handleExternalSeekTime(payload)), + playPause: playPauseBridge.sub(payload => this.handleMediaPlayPause(payload)), + heartbeat: heartbeatBridge.sub(payload => this.echoHeartbeat(payload)), + } + }, + /// Handlers: + handleMediaPlayPause(payload) { + console.log("[playPauseBridge::audio_player::playpause] payload:", payload) + const { + cmd, + player_details: playerDetails, + } = payload + + if (cmd === "play") { + this.playMedia(playerDetails) + } + if (cmd === "pause") { + this.pause() + } + }, + handleExternalSeekTime(payload) { + console.log("[audio_player::seekTimeBridgeSub::seekTimeHandler] this:", this); + const {seekToMs: timeMs} = payload; + const timeS = Math.round(timeMs/1000); + this.seekToS(timeS) + }, + echoHeartbeat(heartbeatPayload) { + const shouldIgnoreSignal = heartbeatPayload.originator === "AudioPlayer"; + if(shouldIgnoreSignal) { + return + } + + console.log("[heartbeatBridge::audio_player] payload:", heartbeatPayload) + const echoPayload = { + originator: "AudioPlayer", + currentPlaybackInfo: { + isPlaying: !this.player.paused, + currentTime: this.player.currentTime, + duration: this.player.duration, + } + } + heartbeatBridge.pub(echoPayload) + }, + initSession(sess) { + localStorage.setItem("session", JSON.stringify(sess)) + }, + handleMetadataLoad(e) { + console.log("Loaded metadata!", { + duration: this.player.duration, + event: e, + }) + }, + handlePlayPause() { + console.log("{play_pause event triggerred} player:", this.player) + if(this.player.paused){ + this.play() + } + }, + /** + * This "init" behaviour has been mimicked from live_beats. + * It is likely there to enable the audio player bufferring. + * */ + enableAudio() { + if(this.player.src){ + document.removeEventListener("click", this.enableAudio) + const hasNothingToPlay = this.player.readyState === 0; + if(hasNothingToPlay){ + this.player.play().catch(error => null) + this.player.pause() + } + } + }, + playMedia(params) { + console.log("PlayMedia", params) + const {filePath, isPlaying, elapsed, artist, title} = params; + + const beginTime = nowSeconds() - elapsed + this.playbackBeganAt = beginTime + let currentSrc = this.player.src.split("?")[0] + + const isLoadedAndPaused = currentSrc === filePath && !isPlaying && this.player.paused; + if(isLoadedAndPaused){ + this.play({sync: true}) + } else if(currentSrc !== filePath) { + currentSrc = filePath + this.player.src = currentSrc + this.play({sync: true}) + } + + const isMediaSessionApiSupported = "mediaSession" in navigator; + if(isMediaSessionApiSupported){ + navigator.mediaSession.metadata = new MediaMetadata({artist, title}) + } + }, + play(opts = {}){ + console.log("Triggered playback, check params", { + player: this.player, + opts, + }) + + let {sync} = opts + + this.player.play().then(() => { + if(sync) { + const currentTime = nowSeconds() - this.playbackBeganAt + this.player.currentTime = currentTime; + const formattedCurrentTime = formatDisplayTime(currentTime); + } + }, error => { + if(error.name === "NotAllowedError"){ + execJS("#enable-audio", "data-js-show") + } + }) + }, + pause(){ + this.player.pause() + }, + stop(){ + this.player.pause() + this.player.currentTime = 0 + }, + seekToS(time) { + const beginTime = nowSeconds() - time + this.playbackBeganAt = beginTime; + this.player.currentTime = time; + }, +} + + +export default AudioPlayer; diff --git a/assets/js/hooks/floater.js b/assets/js/hooks/floater.js new file mode 100644 index 00000000..33bb2e68 --- /dev/null +++ b/assets/js/hooks/floater.js @@ -0,0 +1,129 @@ +/* + * Ideally generic hook for floating logic. + */ +import {isMobileDevice} from "../utils/uncategorised_utils.js"; + +Floater = { + mounted() { + console.log("[floater] floater mounted") + console.log("[floater] dataset check: ", this.el.dataset) + const { + floaterId, + floaterReferenceSelector + } = this.el.dataset; + }, + beforeUpdate() { // gets called synchronously, prior to update + console.log("[floater] Triggerred floater::beforeUpdate()") + const { + floater, + reference, + fallback, + } = this.getRelevantElements(); + + // TODO: this is hardcoded to the media bridge, refactor when more sane. + const offsetHeight = fallback.offsetHeight; // so pretend it's lower by this amount + const isReferenceOutOfView = isElementOutOfViewport(reference, {top:0, bottom:offsetHeight, left: 0, right: 0}) + if (isReferenceOutOfView) { + console.log("[floater] Reference is out of viewport, should use fallback", { + floater, + reference, + fallback, + }) + } + const target = (isMobileDevice() || isReferenceOutOfView) ? fallback : reference + this.alignFloaterToRef(floater, target); + }, + updated() { // gets called when the elem changes + console.log("[floater] Triggerred floater::updated()") + const { + floater, + reference, + fallback, + } = this.getRelevantElements(); + }, + alignFloaterToRef(floater, reference) { + const canBeAligned = floater && reference + if(!canBeAligned) { + console.log("[floater] Can't be aligned") + return + } + + const { + computePosition, + autoPlacement, + shift, + offset, + } = window.FloatingUIDOM; + + computePosition(reference, floater, { + placement: 'right', + // NOTE: order of middleware matters. + middleware: [ + autoPlacement({ + allowedPlacements: [ + "right", + "top-end" + ] + }), + shift({ + padding: 8, + crossAxis: true, + }), + offset(6), + ], + }).then(({x, y}) => { + console.log("[floater] computed coordinates:", {x, y}) + Object.assign(floater.style, { + left: `${x}px`, + top: `${y}px`, + }); + }); + }, + getRelevantElements() { + const { + floaterId, + floaterReferenceSelector, + floaterFallbackReferenceSelector, + } = this.el.dataset; + const floater = document.getElementById(floaterId) + const reference = document.querySelector(floaterReferenceSelector) + const fallback = document.querySelector(floaterFallbackReferenceSelector) + + console.log("[floater] getRelevantElements", { + floater, + reference, + fallback, + isMobileDevice: isMobileDevice(), + }) + + return { + floater, + reference, + fallback, + } + + } +} + +// offset: more positive is more in that direction. so if left = 2 vs left = 3, then the second left is more left than the first left lol. +// offest is to be applied to the value of the rect so rect with offset top = 2 is as though the original left +2 in height +function isElementOutOfViewport(el, offsets = {top: 0, bottom:0, left: 0, right:0}) { + if (!el) { + console.log("[floater] el is null", el) + + } else { + + const rect = el.getBoundingClientRect(); + const { top, bottom, left, right } = offsets; + + return ( + rect.top + top < 0 || + rect.left + left < 0 || + rect.bottom + bottom > (window.innerHeight || document.documentElement.clientHeight) || + rect.right + right > (window.innerWidth || document.documentElement.clientWidth) + ); + + } +} + +export default Floater; diff --git a/assets/js/hooks/index.js b/assets/js/hooks/index.js new file mode 100644 index 00000000..25afeba0 --- /dev/null +++ b/assets/js/hooks/index.js @@ -0,0 +1,24 @@ +import ShareQuoteButton from "./share_quote.js"; +import { + RenderYouTubePlayer, + TriggerYouTubeFunction, +} from "./youtube_player.js"; +import MiniPlayer from "./mini_player.js"; +import MediaBridge from "./media_bridge.js"; +import AudioPlayer from "./audio_player.js"; +import ProgressBar from "./progress_bar.js"; +import Floater from "./floater.js" + + +let Hooks = { + ShareQuoteButton, + RenderYouTubePlayer, + TriggerYouTubeFunction, + MiniPlayer, + MediaBridge, + AudioPlayer, + ProgressBar, + Floater, +}; + +export default Hooks; diff --git a/assets/js/hooks/media/bridged.js b/assets/js/hooks/media/bridged.js new file mode 100644 index 00000000..74b2634b --- /dev/null +++ b/assets/js/hooks/media/bridged.js @@ -0,0 +1,71 @@ +/** + * BridgedEventTarget can receive events and push to events that have + * listen to itself (ref EventTarget interface: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget) + * + * BridgedEventTarget is essential in the brokering of playback state between our media_bridge (the broker) + * and our media players. Our players exhibit a leader-follower pattern, whereby the actions of the + * leader (the audio-player) is followed by the follower (video-player). This aligns with our intention + * to be audio-first. + * */ +class BridgedEventTarget extends EventTarget {} + +/** + * Returns event-handling functions corresponding to the given eventName / topic, + * which allows others to subscribe/publish to this topic, or to dispatch events (to the server) + * using this EventTarget as a proxy. + * */ +export const bridged = (eventName) => { // TODO: consider renaming to registerBridgeEvent + const customEventTarget = new BridgedEventTarget(); + + /** + * Registers the given callback to the custom event and + * returns a callback (nullary function) that can be used to de-register (undo) this registration. + * In order to stop listening to events published by this custom event target, one may + * call this nullary function. + * */ + const sub = (callback) => { + console.log(`${eventName} event sub`) + const EventHandler = (event) => { + const data = event.detail ; + + callback(data); + }; + + customEventTarget.addEventListener(eventName, EventHandler); + + return () => { + customEventTarget.removeEventListener(eventName, EventHandler); + }; + }; + + /** + * Publishes a payload on this eventName topic via the detail attribute of + * a custom event, using the custom event target as a proxy. + * */ + const pub = (payload) => { + console.log(`${eventName} event pub`, {payload}) + const event = new CustomEvent(eventName, { detail: payload }) + customEventTarget.dispatchEvent(event); + }; + + /** + * Given a payload, publishes it on its topic and also pushes + * a server-side event to the LiveView. + * + * Preconditions: + * - if selector has been provided, then it's assumed to be a valid dom selector that can be queried. + * */ + const dispatch = (el, payload, selector=null) => { + console.log(`${eventName} event dispatch`, {el, payload, selector}) + pub(payload) + // customEventTarget.dispatchEvent(new CustomEvent(eventName, { detail: data })); + const isTargettedDispatch = !!selector + if(isTargettedDispatch) { + el.pushEventTo(selector, eventName, payload) + } else { + el.pushEvent(eventName, payload); + } + } + + return { sub, pub, dispatch }; +}; diff --git a/assets/js/hooks/media_bridge.js b/assets/js/hooks/media_bridge.js new file mode 100644 index 00000000..df553048 --- /dev/null +++ b/assets/js/hooks/media_bridge.js @@ -0,0 +1,238 @@ +/** + * Media Event Bus + * Hooks for Media Bridge. + * This hook shall interact with the display elements that give visual info about the generic + * playback state, as well as emit events necessary to its children (i.e. the concrete players.). + * + * Event-handling is done using custom bridged events as a proxy. + * */ +import { bridged } from "./media/bridged.js"; +import { formatDisplayTime } from "../utils/time_utils.js" + +let nowSeconds = () => Math.round(Date.now() / 1000) +let rand = (min, max) => Math.floor(Math.random() * (max - min) + min) +let isVisible = (el) => !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length > 0) + +let execJS = (selector, attr) => { + document.querySelectorAll(selector).forEach(el => liveSocket.execJS(el, el.getAttribute(attr))) +} + +// TODO: consider switching to a map of bridges to support other key events +export const seekTimeBridge = bridged("seekTime"); +export const playPauseBridge = bridged("playPause") +export const heartbeatBridge = bridged("heartbeat") + +MediaBridge = { + mounted() { + this.currentTime = this.el.querySelector("#player-time") + this.isFollowMode = false; + this.duration = this.el.querySelector("#player-duration") + this.progress = this.el.querySelector("#player-progress") + + const emphasizedChapterPreamble = this.emphasizeChapterPreamble() + this.emphasizedDomNode = { + prev: null, + current: emphasizedChapterPreamble, + } + this.el.addEventListener("update_display_value", e => this.handleUpdateDisplayValue(e)) + this.handleEvent("media_bridge:registerEventsTimeline", params => this.registerEventsTimeline(params)) + + // pub: external action + // this callback pubs to others + this.handleEvent("media_bridge:seekTime", (seekTimePayload) => { + const { + originator, + } = seekTimePayload; + console.assert(originator === "MediaBridge", "This event may only originate from the MediaBridge server.") + + seekTimeBridge.pub(seekTimePayload) + }) + + this.handleEvent("media_bridge:play_pause", (playPausePayload) => { + const { + originator, + } = playPausePayload; + console.assert(originator === "MediaBridge", "This event may only originate from the MediaBridge server.") + + console.log("media_bridge:play_pause", playPausePayload) + playPauseBridge.pub(playPausePayload) + }) + + this.handleEvent("toggleFollowMode", () => this.toggleFollowMode()) // TODO: candidate for shifting to media_bridge.js? + + // this callback: is internal to media_bridge + // internal action + this.eventBridgeDeregisterers = { + seekTime: seekTimeBridge.sub(payload => this.handleSeekTime(payload)), + playPause: playPauseBridge.sub(payload => this.handlePlayPause(payload)), + heartbeat: heartbeatBridge.sub(payload => this.handleHeartbeat(payload)), + } + }, + toggleFollowMode() { + this.isFollowMode = !this.isFollowMode; + }, + handleHeartbeat(payload) { + console.log("[MediaBridge::handleHeartbeat]", payload) + const shouldIgnoreSignal = payload.originator === "MediaBridge"; + if(shouldIgnoreSignal) { + return; + } + + // originator is expected to be audio player + console.assert(payload.originator === "AudioPlayer", "MediaBridge only expects heartbeat acks to come from AudioPlayer"); + console.log(">>> progress update, payload:", {payload, eventsTimeline: this.eventsTimeline}) + const playbackInfo = payload.currentPlaybackInfo; + const { + currentTime: currentTimeS, + duration: durationS, + } = playbackInfo || {}; + + this.updateTimeDisplay(currentTimeS, durationS) + this.emphasizeActiveEvent(currentTimeS, this.eventsTimeline) + }, + /** + * Emphasizes then returns the node reference to the chapter's preamble. + * This is so that @ mount, at least the chapter preamble shall be emphasized + * */ + emphasizeChapterPreamble() { + const preambleNode = document.querySelector("#chapter-preamble") + if (!preambleNode) { + console.log("[EMPHASIZE], no preamble node found") + return null + } + + preambleNode.classList.add("emphasized-verse") + + console.log("[EMPHASIZE], preamble node:", preambleNode) + + return preambleNode + }, + emphasizeActiveEvent(currentTime, events) { + if (!events) { + console.log("No events found") + return; + } + + const currentTimeMs = currentTime * 1000 + const activeEvent = events.find(event => currentTimeMs >= event.origin && + currentTimeMs < (event.origin + event.duration)) + + if (!activeEvent) { + console.log("No active event found @ time = ", currentTime) + return; + } + + const { + verse_id: verseId + } = activeEvent; + + if (!verseId) { + return + } + + const { + prev: prevDomNode, + current: currDomNode, + } = this.emphasizedDomNode; // @ this point it wouldn't have been updated yet + + const updatedEmphasizedDomNode = {} + if(currDomNode) { + currDomNode.classList.remove("emphasized-verse") + updatedEmphasizedDomNode.prev = currDomNode; + } + const targetDomId = `verse-${verseId}` + const targetNode = document.getElementById(targetDomId) + targetNode.classList.add("emphasized-verse") + updatedEmphasizedDomNode.current = targetNode; + + if(this.isFollowMode) { + targetNode.focus() + targetNode.scrollIntoView({ + behavior: 'smooth', + block: 'start', + }); + } + + this.emphasizedDomNode = updatedEmphasizedDomNode; + }, + startHeartbeat() { + const heartbeatInterval = 100 // 10fps, comfortable for human eye + console.log("Starting heartbeat!") + const heartbeatPayload = { + originator: "MediaBridge", + } + const heartbeatTimer = setInterval(() => heartbeatBridge.pub(heartbeatPayload), heartbeatInterval) + console.log("Started Heartbeat with:", {heartbeatTimer, heartbeatPayload, heartbeatInterval}) + + this.heartbeatTimer = heartbeatTimer + }, + killHeartbeat() { + console.log("Killing heartbeat!", {heartbeatTimer: this.heartbeatTimer}) + clearInterval(this.heartbeatTimer) + }, + updateTimeDisplay(timeS, durationS=null) { + const beginTime = nowSeconds() - timeS + const currentTimeDisplay = formatDisplayTime(timeS); + this.currentTime.innerText = currentTimeDisplay + console.log("Updated time display to", currentTimeDisplay); + + if(durationS) { + const durationDisplay = formatDisplayTime(durationS) + this.duration.innerText = durationDisplay + } + }, + seekToS(originator, timeS) { + console.log("media_bridge.js::seekToS", {timeS, originator}) + const knownOriginators = ["ProgressBar", "MediaBridge"] // temp-list, will be removed + if (!knownOriginators.includes(originator)) { + console.warn(`originator ${originator} is not a known originator. Is not one of ${knownOriginators}.`) + } + this.updateTimeDisplay(timeS); + }, + handleUpdateDisplayValue(e) { + const { + detail, + } = e + const [key, val, extraKey] = detail?.payload + if (extraKey === "innerText") { + this[key][extraKey] = val; + } + + if (extraKey === "style.width") { + this[key].style.width = val + } + }, + registerEventsTimeline(params) { + console.log("Register Events Timeline", params); + this.eventsTimeline = params.voice_events + }, + handleSeekTime(payload) { + console.log("[media_bridge::seekTimeBridgeSub::seekTimeHandler] this:", this); + const { + seekToMs: timeMs, + originator, + } = payload; + const timeS = Math.round(timeMs/1000); + this.seekToS(originator, timeS) + }, + handlePlayPause(payload) { + console.log("[playPauseBridge::media_bridge:playpause] payload:", payload) + const { + cmd, + player_details: playerDetails, + originator, + } = payload + + // TODO: implement handler for actions emitted via interaction with youtube player + console.log(">> [media_bridge.js::playPauseBridge], received a signal", payload) + if (cmd === "play") { + this.startHeartbeat() + } + if (cmd === "pause") { + this.killHeartbeat() + } + } + +} + +export default MediaBridge; diff --git a/assets/js/hooks/mini_player.js b/assets/js/hooks/mini_player.js new file mode 100644 index 00000000..f92d5982 --- /dev/null +++ b/assets/js/hooks/mini_player.js @@ -0,0 +1,110 @@ +/** + * Hooks to handle video miniplayer. + * */ + +MiniPlayer = { + mounted() { + initMiniPlayer(); + } +} + +/** + * Initialises a miniplayer by binding the relevant listener to + * the events that trigger (and aligns) this miniplayer on the relevant dom element. + * */ +const initMiniPlayer = () => { + const { + button, + } = getRelevantElements(); + + const events = ["touchstart", "click"] + const listeners = [toggleMiniPlayer] + bindListenersToEventsOnEl(button, listeners, events) + + alignMiniPlayer() +} + +/** + * Given a dom element and a list of events and listeners, + * binds all the listeners to each event for that element. + * */ +const bindListenersToEventsOnEl = (el, listeners, events) => { + events.forEach(event => { + listeners.forEach(listener => el.addEventListener(event, listener)) + }); +}; + +const autoUpdatePosition = () => { + const { + verseContainer, + youtubePlayerContainer, + } = getRelevantElements(); + + const { + autoUpdate + } = window.FloatingUIDOM + + window.FloatingUIDOM.cleanupAutoPositioning = autoUpdate( + verseContainer, + youtubePlayerContainer, + alignMiniPlayer, + ) +} + +const toggleMiniPlayer = () => { + const { + youtubePlayerContainer, + } = getRelevantElements(); + + const shouldShow = !youtubePlayerContainer.style.display + youtubePlayerContainer.classList.toggle("container-YouTubePlayerHidden") + shouldShow && autoUpdatePosition(); + !shouldShow && alignMiniPlayer(); +} + +const getRelevantElements = () => { + const id = "YouTubePlayer" + const button = document.getElementById(`button-${id}`) + const youtubePlayerContainer = document.getElementById(`container-${id}`) + const verseContainer = document.getElementById("verseContainer") + + return {button, youtubePlayerContainer, verseContainer} +} + +const alignMiniPlayer = () => { + const {verseContainer, youtubePlayerContainer} = getRelevantElements(); + + const { + computePosition, + autoPlacement, + shift, + offset, + } = window.FloatingUIDOM; + + + computePosition(verseContainer, youtubePlayerContainer, { + placement: 'right', + // NOTE: order of middleware matters. + middleware: [ + autoPlacement({ + allowedPlacements: [ + "right", + "bottom" + ] + }), + shift({ + padding: 32, + crossAxis: true, + }), + offset(6), + ], + }).then(({x, y}) => { + Object.assign(youtubePlayerContainer.style, { + left: `${x}px`, + top: `${y}px`, + }); + }); + +} + +export default MiniPlayer; diff --git a/assets/js/hooks/progress_bar.js b/assets/js/hooks/progress_bar.js new file mode 100644 index 00000000..1c9ff37b --- /dev/null +++ b/assets/js/hooks/progress_bar.js @@ -0,0 +1,137 @@ +/** + * Progress Bar hooks intended to sync playback related actions + * */ + +import {seekTimeBridge, heartbeatBridge} from "./media_bridge.js" + +ProgressBar = { + mounted() { + this.el.addEventListener("click", (e) => this.handleProgressBarClick(e)); + + const heartbeatDeregisterer = heartbeatBridge.sub(payload => this.handleHeartbeat(payload)) + const seekTimeDeregisterer = seekTimeBridge.sub(payload => this.handleExternalSeekTime(payload)) + + this.eventBridgeDeregisterers = { + seekTime: seekTimeDeregisterer, + heartbeat: heartbeatDeregisterer, + } + }, + handleExternalSeekTime(payload) { + console.log("[progress_bar::seekTimeBridgeSub::seekTimeHandler] this:", {payload}); + const { + seekToMs: timeMs, + originator, + } = payload; + + const shouldIgnoreSignal = originator === "ProgressBar"; + if (shouldIgnoreSignal) { + console.info("Ignoring signal for seekTime", payload) + + return; + } + + const maxTime = this.el.dataset?.max || this.maxTime + if(!maxTime) { + console.warn("Max time not available in element's state or dataset, ignoring progress bar update.") + return + } + + const playbackPercentage = (timeMs / maxTime) + const progressStyleWidth = `${(playbackPercentage * 100)}%` + console.log("[DEBUG]", { + maxTime, + playbackPercentage, + }) + this.setProgressBarWidth(progressStyleWidth) + }, + handleHeartbeat(payload) { + console.log("[ProgressBar::handleHeartbeat]", payload) + const shouldIgnoreSignal = payload.originator === "MediaBridge"; + if(shouldIgnoreSignal) { + return; + } + const playbackInfo = payload.currentPlaybackInfo; + const { + currentTime: currentTimeS, + duration: durationS, + } = playbackInfo || {}; + + const playbackPercentage = (currentTimeS / durationS) + const progressStyleWidth = `${(playbackPercentage * 100)}%` + console.log("handleHeartbeat, set progress bar width", progressStyleWidth) + this.setProgressBarWidth(progressStyleWidth) + }, + /* + // The progress bar is measured in milliseconds, + // with `min` set at 0 and `max` at the duration of the track. + // + // [--------------------------X-----------] + // 0 | offsetWidth + // | + // [--------------------------] e.target.offsetX + // + // When the user clicks on the progress bar (represented by X), we get + // the position of the click in pixels (e.target.offsetX). + // + // We know that we can express the relationship between pixels + // and milliseconds as: + // + // e.target.offsetX : e.target.offsetWidth = X : max + // + // To find X, we do: + // console.log("check possible positions info:", { + // e. + // }) + */ + handleProgressBarClick(e) { + const { max: maxTime } = this.el.dataset + + if (!maxTime) { + console.log("unable to seek position, payload is incorrect") + return + } + + const containerNode = document.getElementById("player-progress-container") + const maxOffset = containerNode.offsetWidth + this.maxTime = maxTime; + this.maxOffset = maxOffset; + + const currXOffset = e.offsetX; + const maxPlaybackMs = Number(maxTime) + const playbackPercentage = (currXOffset / maxOffset) + const positionMs = maxPlaybackMs * playbackPercentage + const progressStyleWidth = `${(playbackPercentage * 100)}%` + this.setProgressBarWidth(progressStyleWidth) + + // Optimistic update + this.el.value = positionMs; + + console.log("seek attempt @ positionMs:", { + checkThis: this, + elem: this.el, + event: e, + maxOffset, + currXOffset, + playbackPercentage, + maxPlaybackMs, + positionMs, + }) + + // pubs & dispatches this position + const seekTimePayload = { + seekToMs: positionMs, + originator: "ProgressBar", + } + seekTimeBridge.dispatch(this, seekTimePayload, "#media-player-container") + return; + }, + setProgressBarWidth(progressStyleWidth, selector="#player-progress") { + console.log("setting progress bar width:", progressStyleWidth) + const progressBarNode = document.querySelector(selector) + console.assert(!!progressBarNode, "progress bar node must always be present in the dom.") + progressBarNode.style.width = progressStyleWidth; + } +}; + + +export default ProgressBar; diff --git a/assets/js/hooks/share_quote.js b/assets/js/hooks/share_quote.js new file mode 100644 index 00000000..3e6436a5 --- /dev/null +++ b/assets/js/hooks/share_quote.js @@ -0,0 +1,106 @@ +/** + * Externalised hooks object to be used by app.js. + */ +import { getSharer } from "./web_share.js"; + + +ShareQuoteButton = { + mounted() { + initTooltip(); + let callback = () => console.log("share quote!"); + + if ("share" in navigator) { // uses webshare api: + callback = () => { + const shareTitle = this.el.getAttribute("data-share-title"); + const shareUrl = window.location.href; + const sharer = getSharer("url", shareTitle, shareUrl); + if (!sharer) { + return; + } + + window.shareUrl = sharer; + window.shareUrl(shareUrl); + }; + } else if ("clipboard" in navigator) { // copies to clipboard: + callback = () => { + console.log(">> see me:", {"floating ui:": window}) + const { + chapter_number: chapterNum, + verse_number: verseNum, + transliteration, + text, + } = JSON.parse(this.el.getAttribute("data-verse")); + + const content = `[Gita Chapter ${chapterNum} Verse ${verseNum}] \n${text}\n${transliteration}\nRead more at ${document.URL}` + navigator.clipboard.writeText(content); + }; + } + + this.el.addEventListener("click", callback); + }, +}; + +function showTooltip() { + const {tooltip} = getButtonAndTooltip(); + tooltip.style.display = 'block'; + alignTooltip(); +} + +function hideTooltip() { + const {tooltip} = getButtonAndTooltip(); + tooltip.style.display = ''; +} + +const initTooltip = () => { + const {button} = getButtonAndTooltip(); + + [ + ['mouseenter', showTooltip], + ['mouseleave', hideTooltip], + ['focus', showTooltip], + ['blur', hideTooltip], + ].forEach(([event, listener]) => { + button.addEventListener(event, listener); + }); +} + +const getButtonAndTooltip = () => { + const id = "ShareQuoteButton" + const button = document.getElementById(id) + const tooltip = document.getElementById(`tooltip-${id}`) + return {button, tooltip} + +} + + +const alignTooltip = () => { + const {button, tooltip} = getButtonAndTooltip() + console.log(">>> found?", { + button, + tooltip, + }) + const { + computePosition, + flip, + shift, + offset, + } = window.FloatingUIDOM; + + computePosition(button, tooltip, { + placement: 'right', + // NOTE: order of middleware matters. + middleware: [offset(6), flip(), shift({padding: 16})], + }).then(({x, y}) => { + console.log(">>> computed new position!", { + x, + y + }) + Object.assign(tooltip.style, { + left: `${x}px`, + top: `${y}px`, + }); + }); +} + + +export default ShareQuoteButton; diff --git a/assets/js/hooks/web_share.js b/assets/js/hooks/web_share.js new file mode 100644 index 00000000..574f2aa6 --- /dev/null +++ b/assets/js/hooks/web_share.js @@ -0,0 +1,60 @@ +/** + * This file is for helpers to interface with the WebShare API. + * + * Ref: https://developer.mozilla.org/en-US/docs/Web/API/Web_Share_API + */ + +const sharers = { + "file": shareFile, // to assign to window.shareContent + "url": shareUrl, // to assign to window.shareUrl +}; + +/** + * Returns a function that can be used to set various webshare api attributes. + */ +export function getSharer(sharingType, ...args) { + if (!checkBrowserSupport()) { + console.warning(`This browser doesn't support shares like that, please copy the url instead.`); + return null; + } + if (!(sharingType in sharers)) { + console.warning(`$Sharing Type of {sharingType} is not supported yet.`); + return null; + } + + return () => sharers[sharingType](...args); +} + +function shareFile(title, url) { + if (navigator.share) { + navigator.share({ + title: title, + url: url, + }) + .then(() => console.log("Successful share")) + .catch((error) => console.log("Error sharing", error)); + } else { + console.info(`Your system doesn't support sharing files.`); + } +} + +function shareUrl(url) { + if (navigator.share) { + navigator.share({ + url: url, + }) + .then(() => console.log("Successful share")) + .catch((error) => console.log("Error sharing", error)); + } else { + console.info(`Your system doesn't support sharing urls.`); + } +} + +/** + * Returns true if the browser supports the navigator.share function, false otherwise. + * */ +function checkBrowserSupport() { + // TODO: implement this + return true + +} diff --git a/assets/js/hooks/youtube_player.js b/assets/js/hooks/youtube_player.js new file mode 100644 index 00000000..4d259f7c --- /dev/null +++ b/assets/js/hooks/youtube_player.js @@ -0,0 +1,199 @@ +/** + * Follower + * Validates if required parameters exist. + * */ +import {seekTimeBridge, playPauseBridge} from "./media_bridge.js" +import { isMobileDevice } from "../utils/uncategorised_utils.js" + +const isYouTubeFnCallable = (dataset) => { + const {functionName, eventName} = dataset; + const areFnAndEventNamesProvided = functionName && eventName + if(!areFnAndEventNamesProvided) { + console.warn("Need to provide both valid function name and event name"); + return false + } + const supportedEvents = ["click", "mouseover"] + if (!supportedEvents.includes(eventName)) { + console.warn(`${eventName} is not a supported event. Supported events include ${supportedEvents}.`); + return false + } + const supportedFunctionNames = Object.keys(youtubePlayerCallbacks) + if (!supportedFunctionNames.includes(functionName)) { + console.warn(`${functionName} is not a supported youtube function. Supported functions include ${supportedFunctionNames}.`); + return false; + } + + + return true +} + +// NOTE: the player interface can be found @ https://developers.google.com/youtube/iframe_api_reference#Functions +const youtubePlayerCallbacks = { + seekTo: function(options) { + const {targetTimeStamp, player} = options; + const target = Number(targetTimeStamp) + console.log("seeking to: ", target) + return player.seekTo(target) + }, + loadVideoById: function(options) { + const { + targetTimeStamp: startSeconds, + videoId, + player, + } = options; + console.log(`Loading video with id ${videoId} at t=${startSeconds}s`) + player.loadVideoById({videoId, startSeconds}) + }, + getAllStats: function(options) { // this is a custom function + const { + hook, + player, + } = options; + const stats = { + duration: player.getDuration(), + videoUrl: player.getVideoUrl(), + currentTime: player.getCurrentTime(), + } + hook.pushEventTo("#statsHover", "reportVideoStatus", stats) + } +} + +/** + * Contains client-side logic for the youtube iframe embeded player. + * It shall contain multiple hooks, all revolving around various youtube player + * functionalities that we wish to have. + */ +export const RenderYouTubePlayer = { + mounted() { + const { + videoId, + playerConfig: serialisedPlayerConfig, + } = this.el.dataset; + console.log("Check dataset", this.el.dataset) + + const playerConfig = JSON.parse(serialisedPlayerConfig) + const updatedConfig = overrideConfigForMobile(playerConfig) + injectIframeDownloadScript() + injectYoutubeInitialiserScript(videoId, updatedConfig) + + // TODO: capture youtube player events (play state changes and pub to the same event bridges, so as to control overall playback) + this.eventBridgeDeregisterers = { + seekTime: seekTimeBridge.sub((payload) => this.handleSeekTime(payload)), + playPause: playPauseBridge.sub(payload => this.handlePlayPause(payload)), + } + this.handleEvent("stop", () => this.stop()) + }, + handlePlayPause(payload) { + console.log("[playPauseBridge::audio_player::playpause] payload:", payload) + const { + cmd, + player_details: playerDetails, + } = payload + + if (cmd === "play") { + this.playMedia(playerDetails) + } + if (cmd === "pause") { + this.pauseMedia() + } + }, + handleSeekTime(payload) { + console.log("[youtube_player::seekTimeBridgeSub::seekTimeHandler] check params:", {payload} ); + let {seekToMs: timeMs} = payload; + const timeS = Math.round(timeMs / 1000); + this.seekToS(timeS) + }, + playMedia(params) { + console.log("youtube player playMedia triggerred", params) + window.youtubePlayer.playVideo() + }, + pauseMedia() { + console.log("youtube player pauseMedia triggerred") + window.youtubePlayer.pauseVideo() + }, + stop() { + console.log("youtube player stop triggerred") + }, + seekToS(time) { + console.log("youtube player seekto triggerred", { + time, + player: window.youtubePlayer + }) + window.youtubePlayer.seekTo(time) + } +}; + +/** + * Injects the script for the async download for the iframe as the first script + * so that it gets fired before any other script. + * */ +const injectIframeDownloadScript = () => { + const tag = document.createElement("script"); + tag.src = "https://www.youtube.com/iframe_api"; + const firstScriptTag = document.getElementsByTagName("script")?.[0]; + firstScriptTag && firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); +} + +/** + * Injects a script that contains initialisation logic for the Youtube Player object. + * */ +const injectYoutubeInitialiserScript = (videoId, playerConfig) => { + const iframeInitialiserScript = document.createElement("script"); + document.body.appendChild(iframeInitialiserScript); + window.callbackYouTubeIframeAPIReady = () => { + const assimilatedConfig = { + ...playerConfig, + videoId: videoId, + events: { + onReady: onPlayerReady, + } + } + window.youtubePlayer = new YT.Player("player", assimilatedConfig) + } + window.callbackOnPlayerReady = (event) => { + event.target.playVideo(); + } + + const stringifiedScript = ` + function onYouTubeIframeAPIReady() { + window.callbackYouTubeIframeAPIReady(); + } + function onPlayerReady(event) { + window.callbackOnPlayerReady(event) + }` + + const functionCode = document.createTextNode(stringifiedScript); + iframeInitialiserScript.appendChild(functionCode) +} + +export const TriggerYouTubeFunction = { + mounted() { + if (!isYouTubeFnCallable(this.el.dataset)) { + console.warn("YouTube function can not be triggerred.") + return + } + const {functionName, eventName} = this.el.dataset + const callback = youtubePlayerCallbacks[functionName] + const getOptions = () => ({hook: this,...this.el.dataset, player: window.youtubePlayer}) + this.el.addEventListener(eventName, () => callback(getOptions())) + } +} + +/// FIXME: this is a temp fix, that overrides the dimensions if it's a mobile. +// there has to be a better, more generic way of handling this. +// Alternatively, if we can reverse engineer a custom PIP mode (with resize and all that), then +// we won't need to fix this. +const overrideConfigForMobile = (playerConfig) => { + let overridedConfig = {...playerConfig} + if(isMobileDevice()) { + overridedConfig["height"] = "150", + overridedConfig["width"] = "200", + console.log("[iframe] updating the player config:", { + before: playerConfig, + after: overridedConfig, + + }) + } + + return overridedConfig; +} diff --git a/assets/js/utils/time_utils.js b/assets/js/utils/time_utils.js new file mode 100644 index 00000000..17ac0e99 --- /dev/null +++ b/assets/js/utils/time_utils.js @@ -0,0 +1,20 @@ +/** + * Contains helpers relevant to time. + * */ + +/** + * Given seconds, returns a string representing it as + * hh:mm:ss e.g. 00:12:05 + * */ +export const formatDisplayTime = (seconds) => { + let formatted = null + try { + formatted = new Date(1000 * seconds).toISOString().substring(11, 19) + } catch (e) { + console.warn("Errored out when doing time conversions.", e) + } finally { + return formatted + } +} + +export const nowSeconds = () => Math.round(Date.now() / 1000) diff --git a/assets/js/utils/uncategorised_utils.js b/assets/js/utils/uncategorised_utils.js new file mode 100644 index 00000000..7db8a31a --- /dev/null +++ b/assets/js/utils/uncategorised_utils.js @@ -0,0 +1,19 @@ +/** + * For utils that can't be clearly categorised yet. + * */ + + +/** + * Returns true if the device is a touch device(?). + * + * Disclaimer: this fn may break. + * + * */ +export function isMobileDevice() { + var match = window.matchMedia || window.msMatchMedia; + if(match) { + var mq = match("(pointer:coarse)"); + return mq.matches; + } + return false; +} diff --git a/assets/tailwind.config.js b/assets/tailwind.config.js index 8c6a0d7e..83e22aa7 100644 --- a/assets/tailwind.config.js +++ b/assets/tailwind.config.js @@ -18,7 +18,18 @@ module.exports = { 'tl': ['"Tamil Font"', 'sans-serif'], }, colors: { - brand: "#FD4F00", + primary: 'var(--color-primary)', + primaryAccent: 'var(--color-primary-accent)', + secondary: 'var(--color-secondary)', + primaryBackground: 'var(--color-primary-background)', + secondary: 'var(--color-secondary)', + brand: 'var(--color-brand)', + brandLight: 'var(--color-brand-light)', + brandExtraLight: 'var(--color-brand-extra-light)', + brandAccent: 'var(--color-brand-accent)', + brandAccentLight: 'var(--color-brand-accent-light)', + brandDark: 'var(--color-brand-dark)', + brandExtraDark: 'var(--color-brand-extra-dark)', } }, }, diff --git a/config/config.exs b/config/config.exs index 93216f60..913ad41a 100644 --- a/config/config.exs +++ b/config/config.exs @@ -31,6 +31,15 @@ config :vyasa, VyasaWeb.Endpoint, # at the `config/runtime.exs`. config :vyasa, Vyasa.Mailer, adapter: Swoosh.Adapters.Local +#S3 Object Storage Services +config :ex_aws, + access_key_id: [{:system, "AWS_ACCESS_KEY_ID"}, :instance_role], + secret_access_key: [{:system, "AWS_SECRET_ACCESS_KEY"}, :instance_role], + region: "ap-southeast-1", + http_client: Vyasa.Medium.Ext.S3Client + +config :live_admin, ecto_repo: Vyasa.Repo + # Configure esbuild (the version is required) config :esbuild, version: "0.17.11", diff --git a/config/dev.exs b/config/dev.exs index 9b91ab1f..a9f55e26 100644 --- a/config/dev.exs +++ b/config/dev.exs @@ -10,6 +10,17 @@ config :vyasa, Vyasa.Repo, show_sensitive_data_on_connection_error: true, pool_size: 10 +# MINIO Object Store API Domain +config :ex_aws, :s3, + scheme: "http://", + host: "localhost", + port: 9000 + +config :ex_aws, :retries, + max_attempts: 2, + base_backoff_in_ms: 10, + max_backoff_in_ms: 10_000 + # For development, we disable any cache and enable # debugging and code reloading. # @@ -19,7 +30,8 @@ config :vyasa, Vyasa.Repo, config :vyasa, VyasaWeb.Endpoint, # Binding to loopback ipv4 address prevents access from other machines. # Change to `ip: {0, 0, 0, 0}` to allow access from other machines. - http: [ip: {127, 0, 0, 1}, port: 4000], + # http: [ip: {127, 0, 0, 1}, port: System.get_env("PORT") || 4000], + http: [ip: {0, 0, 0, 0}, port: System.get_env("PORT") || 4000], check_origin: false, code_reloader: true, debug_errors: true, @@ -51,6 +63,8 @@ config :vyasa, VyasaWeb.Endpoint, # If desired, both `http:` and `https:` keys can be # configured to run both http and https servers on # different ports. +# +#config :ssl, cacertfile: 'priv/cacerts.pem' # Watch static and templates for browser reloading. config :vyasa, VyasaWeb.Endpoint, diff --git a/config/runtime.exs b/config/runtime.exs index d2bbec88..49493441 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -115,4 +115,7 @@ if config_env() == :prod do # config :swoosh, :api_client, Swoosh.ApiClient.Hackney # # See https://hexdocs.pm/swoosh/Swoosh.html#module-installation for details. + # + else + Vyasa.Parser.Env.load_file('.env') end diff --git a/docker-compose.yml b/docker-compose.yml index 1699f8ef..d3743b2f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,44 +1,41 @@ version: '3.8' services: - postgres: - container_name: postgres_container - build: - context: ./GanapatiSQL - dockerfile: Localfile - #image: postgres - environment: - POSTGRES_USER: ${POSTGRES_USER:-postgres} - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-root} - PGDATA: /data/postgres - volumes: - - postgres:/data/postgres - healthcheck: - test: ["CMD-SHELL", "pg_isready -U postgres"] - interval: 10s - timeout: 5s - retries: 5 - ports: - - "5432:5432" - networks: - - postgres - restart: unless-stopped + # postgres: + # container_name: postgres_container + # image: postgres + # environment: + # POSTGRES_USER: ${POSTGRES_USER:-postgres} + # POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-root} + # PGDATA: /data/postgres + # volumes: + # - postgres:/data/postgres + # healthcheck: + # test: ["CMD-SHELL", "pg_isready -U postgres"] + # interval: 10s + # timeout: 5s + # retries: 5 + # ports: + # - "5432:5432" + # networks: + # - postgres + # restart: unless-stopped - pgadmin: - container_name: pgadmin_container - image: dpage/pgadmin4 - environment: - PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org} - PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-root} - PGADMIN_CONFIG_SERVER_MODE: 'False' - volumes: - - pgadmin:/var/lib/pgadmin + # pgadmin: + # container_name: pgadmin_container + # image: dpage/pgadmin4 + # environment: + # PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:-pgadmin4@pgadmin.org} + # PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-root} + # PGADMIN_CONFIG_SERVER_MODE: 'False' + # volumes: + # - pgadmin:/var/lib/pgadmin - ports: - - "${PGADMIN_PORT:-5050}:80" - networks: - - postgres - restart: unless-stopped + # ports: + # - "${PGADMIN_PORT:-5050}:80" + # networks: + # - postgres + # restart: unless-stopped minio1: image: minio/minio:RELEASE.2022-05-08T23-50-31Z @@ -56,9 +53,9 @@ services: timeout: 20s retries: 3 -networks: - postgres: - driver: bridge +# networks: +# postgres: +# driver: bridge volumes: postgres: diff --git a/docs/initial_db_helpers.livemd b/docs/initial_db_helpers.livemd new file mode 100644 index 00000000..9bd49236 --- /dev/null +++ b/docs/initial_db_helpers.livemd @@ -0,0 +1,781 @@ +# 2024 - An Ecto Odessy [Initial DB Helpers] + +## Root Section -- Common Utils + +### Supports Recompilation from within Livebook + +```elixir +defmodule R do + def recompile() do + Mix.Task.reenable("app.start") + Mix.Task.reenable("compile") + Mix.Task.reenable("compile.all") + compilers = Mix.compilers() + Enum.each(compilers, &Mix.Task.reenable("compile.#{&1}")) + Mix.Task.run("compile.all") + end +end + +R.recompile() +``` + +### Source Extraction Modules + +Convert json --> struct --> using changeset --> insert into repo + + + +#### Gita Source Extraction Module + +```elixir +alias Vyasa.Written.{Chapter, Source, Translation} +alias Vyasa.Medium +alias Vyasa.Repo + +defmodule G do + @gita_sub_dir Path.expand("./priv/static/corpus/gita") + + @verses "#{@gita_sub_dir}/verse.json" + @translations "#{@gita_sub_dir}/translation.json" + @chapters "#{@gita_sub_dir}/chapters.json" + + alias Vyasa.Written.{Chapter} + + def read_verses() do + @verses + |> File.read!() + |> Jason.decode!() + end + + def read_translations() do + @translations + |> File.read!() + |> Jason.decode!() + end + + def read_chapters() do + @chapters + |> File.read!() + |> Jason.decode!() + end + + def get_translation_by_verse(id) do + read_translations() + |> Enum.find(fn %{"verseNumber" => no, "authorName" => a} -> + no == id and a == "Dr. S. Sankaranarayan" + end) + end + + def create_verse(verse, source_id) do + updated = + verse + |> Map.put("source_id", source_id) + |> Map.put("chapter_no", verse["chapter_number"]) + |> Map.put("body", verse["text"]) + |> Map.put("no", verse["verse_number"]) + + updated + end + + def get_verses_for_chapter(chap_no, src_id) do + read_verses() + |> Enum.filter(fn verse -> verse["chapter_number"] == chap_no end) + |> Enum.map(fn verse -> G.create_verse(verse, src_id) end) + end + + def create_translation_for_chapter(chapter) do + %{ + type: "chapters", + lang: "hi", + target: %{ + title: chapter["name"], + body: chapter["chapter_summary_hindi"] + } + } + end + + def create_chapter(%{} = chapter, source_id) do + %{ + no: chapter["chapter_number"], + title: chapter["name"], + body: chapter["chapter_summary"], + source_id: source_id + } + + # |> dbg() + end + + def create_chapter(%{} = chapter, [%{} = _head | _rest] = _verses, source_id) do + IO.puts("CHECK THIS CHAPTER OUT") + IO.inspect(chapter) + + %{ + source_id: source_id, + no: chapter["chapter_number"] + } + end + + def get_chapters([%{} = _head | _rest] = verses, source_id) do + @chapters + |> File.read!() + |> Jason.decode!() + |> Enum.map(fn chap -> create_chapter(chap, verses, source_id) end) + end + + def get_chapters(source_id) do + @chapters + |> File.read!() + |> Jason.decode!() + |> Enum.map(fn chap -> create_chapter(chap, source_id) end) + end + + def add_relevant_verses(chapter, verses) do + relevant_verses = + verses + |> Enum.filter(fn verse -> verse.chapter_no == chapter.no end) + |> Enum.map(fn verse -> Map.put(verse, :id, Ecto.UUID.generate()) end) + + %{chapter | verses: relevant_verses} + end + + def insert_verses_into_chapters(chapters, verses) do + chapters + |> Enum.map(fn chap -> add_relevant_verses(chap, verses) end) + end + + def get_source([%{} = _h | _r] = chapters, [%{} = _head | _rest] = verses, source_id) do + %{ + id: source_id, + title: "Gita", + chapters: chapters, + verses: verses + } + end + + def create_chapter_changeset(chap, verses, src_id) do + Chapter.changeset( + %Chapter{ + no: chap["chapter_number"], + source_id: src_id, + title: chap["name"], + body: chap["chapter_summary"] + }, + %{ + verses: verses + } + ) + end + + def create_chap_translation_changeset(%Chapter{} = inserted_chap, %{} = chap) do + Translation.gen_changeset( + %Translation{}, + %{ + lang: "en", + body: chap["chapter_summary"], + target: %{ + title: chap["name_meaning"], + translit_title: chap["name_transliterated"], + body: chap["chapter_summary"] + } + }, + inserted_chap + ) + end + + def create_translation_changeset_for_verse( + inserted_verse, + %{"verse_order" => verse_id} = relevant_verse + ) do + dbg(relevant_verse) + + Translation.gen_changeset( + %Translation{}, + %{ + lang: "en", + # body: verse["transliteration"], + target: %{ + body: get_translation_by_verse(verse_id)["description"], + body_translit_meant: relevant_verse["word_meanings"], + body_translit: relevant_verse["transliteration"] + } + }, + inserted_verse + ) + |> dbg() + end + + def create_translation_changesets_for_verses(inserted_verses, relevant_verses) do + Enum.zip(inserted_verses, relevant_verses) + |> Enum.map(fn {inserted_verse, relevant_verse} -> + create_translation_changeset_for_verse(inserted_verse, relevant_verse) + end) + end +end +``` + +#### Hanuman Chalisa Source Extraction Module + +```elixir +defmodule H do + alias Vyasa.Written.{Chapter, Source, Translation} + alias Vyasa.Medium + alias Vyasa.Repo + + @chalisa_events """ + start :- 00:00 + Shloka 1:- 00:02 + Shloka 2 :- 00:24 + Shloka 3:- 00:56 + Shloka 4:- 01:07 + Shloka 5:- 01:23 + Shloka 6:- 01:33 + Shloka 7:- 01:44 + Shloka 8:- 01:55 + Shloka 9:- 02:10 + Shloka 10:- 02:21 + Shloka 11:- 02:32 + Shloka 12:- 02:43 + Shloka 13:- 02:58 + Shloka 14:- 03:09 + Shloka 15:- 03:19 + Shloka 16:- 03:30 + Shloka 17:- 03:45 + Shloka 18:- 03:54 + Shloka 19:- 04:07 + Shloka 20:- 04:18 + Shloka 21:- 04:33 + Shloka 22:- 04:44 + Shloka 23:- 04:55 + Shloka 24:- 05:05 + Shloka 25:- 05:21 + Shloka 26:- 05:32 + Shloka 27:- 05:42 + Shloka 28:- 05:53 + Shloka 29:- 06:09 + Shloka 30:- 06:19 + Shloka 31:- 06:30 + Shloka 32 :- 06:41 + Shloka 33:- 06:56 + Shloka 34 :- 07:07 + Shloka 35 :- 07:17 + Shloka 36 :- 07:28 + Shloka 37:- 07:43 + Shloka 38 :- 07:54 + Shloka 39:- 08:05 + Shloka 40:- 08:16 + Shloka 41:- 08:31 + Shloka 42:- 08:41 + Shloka 43:- 09:00 + end:- 09:42 + """ + + @chalisa_json_path Path.expand("./priv/static/corpus/shlokam.org/hanumanchalisa.json") + + def read_verses() do + @chalisa_json_path + |> File.read!() + |> Jason.decode!() + end +end +``` + +#### Seeders + +```elixir +defmodule SourceSeeders do + alias Vyasa.Repo + alias G + alias Vyasa.Written.{Source, Chapter, Verse, Translation} + alias Vyasa.Medium.{Event, Voice, Video} + + @gulshan_kumar_chalisa_uri "AETFvQonfV8" + @gita_video_uri "z4IQ4Laivtk" + + # generic + def insert_source(uuid, source_title \\ "gita") do + source_changeset = + Source.gen_changeset(%Source{}, %{ + id: uuid, + title: source_title + }) + + Repo.insert!(source_changeset) + end + + def associate_video_to_voice(inserted_voice, video_attrs) do + Video.gen_changeset(%Video{}, video_attrs, inserted_voice) + |> Repo.insert() + end + + def insert_gita_chapter(chap, source_id) do + relevant_verses = G.get_verses_for_chapter(chap["chapter_number"], source_id) + chap_changeset = G.create_chapter_changeset(chap, relevant_verses, source_id) + {:ok, %Chapter{} = inserted_chapter} = Repo.insert(chap_changeset) + %{verses: inserted_verses} = inserted_chapter + + changeset_chap_translation = G.create_chap_translation_changeset(inserted_chapter, chap) + {:ok, %Translation{} = _inserted_chap_translation} = Repo.insert(changeset_chap_translation) + + verses_translation_changesets = + G.create_translation_changesets_for_verses(inserted_verses, relevant_verses) + + _inserted_verse_translations = + verses_translation_changesets + |> Enum.map(fn c_set -> Repo.insert(c_set) end) + |> Enum.map(fn {:ok, inserted_verse_translation} -> inserted_verse_translation end) + + chap + end + + def insert_gita_chapters(source_id) do + G.read_chapters() + |> Enum.map(fn chap -> insert_gita_chapter(chap, source_id) end) + end + + # def insert_hanuman_chalisa_verses(source_id) do + # verses = H.get_verses(soure_id) + + # end + + @gita_chap_1_events """ + start :- 00:00 + Shloka 1:- 00:33 + Shloka 2 :- 00:49 + Shloka 3:- 01:06 + Shloka 4:- 01:19 + Shloka 5:- 01:32 + Shloka 6:- 01:46 + Shloka 7:- 02:00 + Shloka 8:- 02:15 + Shloka 9:- 02:28 + Shloka 10:- 02:42 + Shloka 11:- 02:56 + Shloka 12:- 03:09 + Shloka 13:- 03:22 + Shloka 14:- 03:36 + Shloka 15:- 03:49 + Shloka 16:- 04:02 + Shloka 17:- 04:14 + Shloka 18:- 04:27 + Shloka 19:- 04:40 + Shloka 20:- 04:54 + Shloka 21:- 05:07 + Shloka 22:- 05:23 + Shloka 23:- 05:36 + Shloka 24:- 05:50 + Shloka 25:- 06:05 + Shloka 26:- 06:18 + Shloka 27:- 06:32 + Shloka 28:- 06:46 + Shloka 29:- 07:01 + Shloka 30:- 07:13 + Shloka 31:- 07:26 + Shloka 32 :- 07:38 + Shloka 33:- 07:51 + Shloka 34 :- 08:05 + Shloka 35 :- 08:18 + Shloka 36 :- 08:31 + Shloka 37:- 08:44 + Shloka 38 :- 08:57 + Shloka 39:- 09:09 + Shloka 40:- 09:22 + Shloka 41:- 09:35 + Shloka 42:- 09:48 + Shloka 43:- 10:02 + Shloka 44:- 10:16 + Shloka 45:- 10:29 + Shloka 46:- 10:40 + Shloka 47:- 10:53 + end:- 11:08 + """ + + def seed_gita_chapter_1() do + gita = Vyasa.Written.get_source_by_title("gita") + verses = Vyasa.Written.get_verses_in_chapter(1, gita.id) + + # creats a map using verse information + verse_lookup = Enum.into(for(%{id: id, no: verse_no} <- verses, do: {verse_no, id}), %{}) + + c1_path = Path.expand("./1.mp3", "media/gita") + + {:ok, + %Vyasa.Parser.MP3{ + duration: tot_d, + path: p + }} = Vyasa.Parser.MP3.parse(c1_path) + + {:ok, voice} = + Vyasa.Medium.create_voice(%{ + lang: "sa", + duration: tot_d, + file_path: c1_path, + source_id: gita.id, + chapter_no: 1 + }) + + {:ok, video} = associate_video_to_voice(voice, %{ext_uri: @gita_video_uri, type: "youtube"}) + + @gita_chap_1_events + |> String.split("\n") + |> Enum.map(fn x -> + x + |> String.split(":-") + |> Enum.map(&String.trim/1) + |> Enum.reduce([], fn + <<"Shloka"::utf8, sep::utf8, verse_no::binary>>, acc -> + [verse_lookup[String.to_integer(verse_no)] | acc] + + bin, acc -> + [bin | acc] + end) + end) + |> IO.inspect(limit: :infinity) + |> Enum.reduce( + [], + fn + [time, "start"], acc -> + [ + %Vyasa.Medium.Event{origin: 0, phase: "start", voice_id: voice.id, source_id: gita.id} + | acc + ] + + [time, "end"], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{ + origin: d, + duration: tot_d - d, + phase: "end", + voice_id: voice.id, + source_id: gita.id + } + | [%{prev | duration: d - o} | acc] + ] + + [time, id], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{origin: d, verse_id: id, voice_id: voice.id, source_id: gita.id} + | [%{prev | duration: d - o} | acc] + ] + + _, acc -> + acc + end + ) + |> Enum.map(&Vyasa.Medium.create_event(&1)) + end + + def seed_gita() do + uuid = Ecto.UUID.generate() + _source = insert_source(uuid, "gita") + _chaps = insert_gita_chapters(uuid) + seed_gita_chapter_1() + end + + @chalisa_events """ + start :- 00:00 + Shloka 1:- 00:02 + Shloka 2 :- 00:24 + Shloka 3:- 00:56 + Shloka 4:- 01:07 + Shloka 5:- 01:23 + Shloka 6:- 01:33 + Shloka 7:- 01:44 + Shloka 8:- 01:55 + Shloka 9:- 02:10 + Shloka 10:- 02:21 + Shloka 11:- 02:32 + Shloka 12:- 02:43 + Shloka 13:- 02:58 + Shloka 14:- 03:09 + Shloka 15:- 03:19 + Shloka 16:- 03:30 + Shloka 17:- 03:45 + Shloka 18:- 03:54 + Shloka 19:- 04:07 + Shloka 20:- 04:18 + Shloka 21:- 04:33 + Shloka 22:- 04:44 + Shloka 23:- 04:55 + Shloka 24:- 05:05 + Shloka 25:- 05:21 + Shloka 26:- 05:32 + Shloka 27:- 05:42 + Shloka 28:- 05:53 + Shloka 29:- 06:09 + Shloka 30:- 06:19 + Shloka 31:- 06:30 + Shloka 32 :- 06:41 + Shloka 33:- 06:56 + Shloka 34 :- 07:07 + Shloka 35 :- 07:17 + Shloka 36 :- 07:28 + Shloka 37:- 07:43 + Shloka 38 :- 07:54 + Shloka 39:- 08:05 + Shloka 40:- 08:16 + Shloka 41:- 08:31 + Shloka 42:- 08:41 + Shloka 43:- 09:00 + end:- 09:42 + """ + @chalisa_audio_path Path.expand("./hanuman_chalisa_gulshan_kumar.mp3", "media/chalisa") + def insert_hanuman_chalisa_events() do + chalisa = Vyasa.Written.get_source_by_title("hanuman_chalisa") + verses = Vyasa.Written.get_verses_in_chapter(1, chalisa.id) + verse_lookup = Enum.into(for(%{id: id, no: verse_no} <- verses, do: {verse_no, id}), %{}) + + # parse mp3 info: + {:ok, + %Vyasa.Parser.MP3{ + duration: tot_d, + path: p + }} = Vyasa.Parser.MP3.parse(@chalisa_audio_path) + + # handle voices: + {:ok, voice} = + Vyasa.Medium.create_voice(%{ + lang: "sa", + duration: tot_d, + file_path: @chalisa_audio_path, + source_id: chalisa.id, + chapter_no: 1 + }) + + # handle video: + {:ok, video} = + associate_video_to_voice(voice, %{ext_uri: @gulshan_kumar_chalisa_uri, type: "youtube"}) + + # now handle the events: + @chalisa_events + |> String.split("\n") + |> Enum.map(fn x -> + x + |> String.split(":-") + |> Enum.map(&String.trim/1) + |> Enum.reduce([], fn + <<"Shloka"::utf8, sep::utf8, verse_no::binary>>, acc -> + [verse_lookup[String.to_integer(verse_no)] | acc] + + bin, acc -> + [bin | acc] + end) + end) + |> IO.inspect(limit: :infinity) + |> Enum.reduce( + [], + fn + [time, "start"], acc -> + [ + %Vyasa.Medium.Event{ + origin: 0, + phase: "start", + voice_id: voice.id, + source_id: chalisa.id + } + | acc + ] + + [time, "end"], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{ + origin: d, + duration: tot_d - d, + phase: "end", + voice_id: voice.id, + source_id: chalisa.id + } + | [%{prev | duration: d - o} | acc] + ] + + [time, id], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{ + origin: d, + verse_id: id, + voice_id: voice.id, + source_id: chalisa.id + } + | [%{prev | duration: d - o} | acc] + ] + + _, acc -> + acc + end + ) + |> Enum.map(&Vyasa.Medium.create_event(&1)) + end + + @chalisa_chap_body "The Hanuman Chalisa, composed by Goswami Tulsidas, is a 40-verse hymn dedicated to Lord Hanuman, highlighting his unwavering devotion to Lord Rama. It is a testament to Hanuman's strength, wisdom, and courage, as well as his role in Lord Rama's epic battles against evil. Reciting this hymn is believed to bestow blessings and protection from Hanuman, fostering spiritual growth and devotion to Lord Rama." + def insert_hanuman_chalisa_chapter(source, chalisa_verses) do + {:ok, inserted_chap} = + Chapter.changeset( + %Chapter{ + no: 1, + source_id: source.id, + title: "Hanuman Chalisa", + body: @chalisa_chap_body + }, + %{ + verses: + chalisa_verses + |> Enum.map(fn v -> + %{ + no: v["count"], + body: v["verse_sanskrit"], + source_id: source.id + } + end) + } + ) + |> Repo.insert() + |> dbg() + + Translation.gen_changeset( + %Translation{}, + %{ + lang: "en", + body: @chalisa_chap_body, + target: %{ + title: "Hanuman Chalisa", + translit_tile: "Hanuman Chalisa", + body: @chalisa_chap_body + }, + source_id: source.id + }, + inserted_chap + ) + |> Repo.insert() + |> dbg() + + inserted_chap + end + + def insert_hanuman_chalisa_verses(source, chalisa_verses) do + chalisa_verses + |> Enum.map(fn v -> + Verse.changeset(%Verse{}, %{ + no: v["count"], + body: v["verse_sanskrit"], + source_id: source.id + }) + end) + |> Enum.map(fn chset -> Repo.insert(chset) end) + |> Enum.map(fn {:ok, inserted_v} -> inserted_v end) + end + + def insert_hanuman_chalisa_verse_translations( + %Chapter{verses: inserted_verses} = _inserted_chap, + chalisa_verses + ) do + inserted_verses + |> Enum.zip(chalisa_verses) + |> Enum.map(fn {inserted_verse, v} -> + Translation.gen_changeset( + %Translation{}, + %{ + lang: "en", + target: %{ + body: v["verse_sanskrit"], + body_translit_meant: v["verse_meaning"], + body_translit: v["verse_trans"] + }, + source_id: inserted_verse.source_id, + # chapter_no: inserted_verse.chapter_no, # this assoc isn't supposed to be done @ verse-trans creation + verse_id: inserted_verse.id + }, + inserted_verse + ) + end) + |> Enum.map(fn trans_cset -> Repo.insert(trans_cset) end) + |> Enum.map(fn outcome -> elem(outcome, 1) end) + |> dbg() + end + + def seed_hanuman_chalisa() do + uuid = Ecto.UUID.generate() + %{"verses" => chalisa_verses} = _verse_info = H.read_verses() + + uuid + |> insert_source("hanuman_chalisa") + |> insert_hanuman_chalisa_chapter(chalisa_verses) + |> insert_hanuman_chalisa_verse_translations(chalisa_verses) + + insert_hanuman_chalisa_events() + end +end +``` + +#### DB Convenience Actions + +* purging of db +* seeding of db + +```elixir +defmodule DBHelper do + alias SourceSeeders + alias Vyasa.Repo + alias G + alias Vyasa.Written.{Source, Chapter, Verse, Translation} + alias Vyasa.Medium.{Video, Event, Voice} + + # alias Vyasa.Medium.{Voice, Event, Store, Track, Video, Writer} + + def purge_db() do + [Video, Event, Voice, Translation, Verse, Chapter, Source] + |> Enum.map(fn mod -> Repo.delete_all(mod) end) + end + + def seed_db() do + SourceSeeders.seed_gita() + SourceSeeders.seed_hanuman_chalisa() + end +end +``` + +#### Testing the purging and seeding of the db: + +```elixir +R.recompile() +DBHelper.purge_db() +DBHelper.seed_db() +``` + +### Exploring video-voice sync + +The following is a demo check that the seeding is working correctly. Once verified, the block may be removed. + +```elixir +R.recompile() + +alias Vyasa.Written +alias Vyasa.Written.{Source} +alias Vyasa.Medium.{Voice, Video, Store} +alias Vyasa.Medium +alias Vyasa.Repo + +%Source{id: chalisa_id} = chalisa = Written.get_source_by_title("hanuman_chalisa") +h_voice = Repo.get_by!(Voice, source_id: chalisa_id) |> Repo.preload([:video]) + +%Source{id: gita_id} = gita = Written.get_source_by_title("gita") +g_voice = Repo.get_by!(Voice, source_id: gita_id) |> Repo.preload([:video]) + +g_voice.video |> Medium.resolve_video_url() + +Medium.get_voice(chalisa_id, 1, "sa") |> Store.hydrate() +``` + +```elixir + +``` diff --git a/docs/schema/vyasa_6feb_schema.png b/docs/schema/vyasa_6feb_schema.png new file mode 100644 index 00000000..94fbd065 Binary files /dev/null and b/docs/schema/vyasa_6feb_schema.png differ diff --git a/docs/scraper.livemd b/docs/scraper.livemd new file mode 100644 index 00000000..51df2d92 --- /dev/null +++ b/docs/scraper.livemd @@ -0,0 +1,417 @@ +# Scraper Lite + +```elixir +# Mix.install([ +# {:poison, "~> 5.0"}, +# {:floki, "~> 0.35.2"}, +# {:req, "~> 0.4.8"}, +# {:youtube_captions, "~> 0.1.0"} +# ]) +``` + +## Root + +```elixir +# defmodule R do +# def recompile() do +# Mix.Task.reenable("app.start") +# Mix.Task.reenable("compile") +# Mix.Task.reenable("compile.all") +# compilers = Mix.compilers() +# Enum.each(compilers, &Mix.Task.reenable("compile.#{&1}")) +# Mix.Task.run("compile.all") +# end +# end + +R.recompile() +``` + +```elixir +{:ok, src} = Vyasa.Written.create_source(%{title: "rama"}) +# Vyasa.Medium.Writer.init(%) +``` + +```elixir + +``` + + + +## Valmiki Ramayana + +```elixir +url = "https://www.valmikiramayan.net/utf8/" +# fetch from root frame +path = "baala/sarga1/" +doc = "balasans1.htm" + +col = + Finch.build(:get, url <> path <> doc) + |> Finch.request!(Vyasa.Finch) + |> Map.get(:body) + |> Floki.parse_document!() + |> Floki.find("body") + |> List.first() + |> elem(2) +``` + +```elixir +defmodule Rama do + # audio n+1 + def parse(data, acc) do + case {data, acc} do + {{"p", [{"class", "SanSloka"}], [{"audio", _, _} | _] = audio}, + [%{"count" => c} = curr | _] = acc} -> + # IO.inspect(audio, label: "audio") + [src] = + audio + |> Floki.find("source") + |> Floki.attribute("src") + + [ + curr + |> Map.put("count", c + 1) + |> Map.put("audio", src) + | acc + ] + + {{"p", [{"class", "SanSloka"}], [{"audio", _, _} | _] = audio}, []} -> + [src] = + audio + |> Floki.find("source") + |> Floki.attribute("src") + + [%{"count" => 1, "audio" => src}] + + # verse n + 1 + {{"p", [{"class", "SanSloka"}], verses}, [curr | acc]} -> + [Map.put(curr, "verse", verses |> Floki.text() |> String.trim()) | acc] + + # nesting in verloc + + {{"p", [{"class", "verloc"}], [{"p", [{"class", "SanSloka"}], sloka} | _] = ns_tree}, + [curr | _] = acc} + when is_map(curr) -> + # IO.inspect(ns_tree) + # IO.inspect(ns_tree) + Enum.reduce(ns_tree, acc, &parse/2) + + {{"p", [{"class", "verloc"}], rem} = c_tree, [curr | acc]} when is_map(curr) -> + [curr | acc] + + # # n case before verse break + {{"p", [{"class", class}], _} = c_tree, [curr | acc]} when is_map(curr) -> + [Map.put(curr, class, c_tree |> Floki.text() |> String.trim()) | acc] + + {para, acc} -> + # IO.inspect(para, label: "div") + acc + end + end +end + +output = + col + |> Enum.reduce([], &Rama.parse/2) + +# # formatting & tying loose ends +# clean_verses = +# [Map.put(curr, "count", count + 1) | verses] +# |> Enum.reverse() +``` + +```elixir +File.mkdir_p!(Path.expand(path, "media")) + +output +|> Enum.reduce([], fn + %{"audio" => aud, "count" => 12 = count, "verse" => verse}, acc -> + aud_bin = + Finch.build( + :get, + Path.join(url <> path, aud) + |> String.replace(~r/\.\//, "") + ) + |> Finch.request!(Vyasa.Finch) + |> Map.get(:body) + + m_path = Path.expand(path <> "/#{count}.mp3", "media") + File.write!(m_path, aud_bin) + + {:ok, + %Vyasa.Parser.MP3{ + duration: d, + path: p, + title: title + }} = Vyasa.Parser.MP3.parse(m_path) + + [ + %Vyasa.Medium.Event{ + origin: 0, + duration: d, + fragments: [%{status: "firstpass", quote: verse}] + } + | acc + ] + + _, acc -> + acc +end) +``` + +```elixir +aud = + output + |> Enum.find(&(Map.get(&1, "count") == 1)) + |> Map.get("audio") +``` + +```elixir +aud_bin = + Finch.build( + :get, + Path.join(url <> path, aud) + |> String.replace(~r/\.\//, "") + ) + |> Finch.request!(Vyasa.Finch) + |> Map.get(:body) +``` + +```elixir +# # IO.binwrite(path, aud) +# # |> :file.read_file_info() +# File.open(Path.expand([path,aud], "media"), [:write, :binary]) +# # |> IO.binwrite(aud_bin) +# Path.expand([path,aud], "media") +# # |> File.touch!() +File.mkdir_p!(Path.expand(path, "media")) +{:ok, file} = File.write!(Path.expand(path, "media"), aud_bin) +``` + + + +## Shlokam + +```elixir +url = "https://shlokam.org/" +path = "hanumanchalisa" + +col = + Finch.build(:get, url <> path) + |> Finch.request!(Vyasa.Finch) + |> Map.get(:body) + |> Floki.parse_document!() + |> Floki.find(".uncode_text_column") +``` + +```elixir +# class_key = %{ +# "verse_meaning" => "en_translation", +# "verse_sanskrit" => "text", +# "verse_trans" => "transliteration", +# } +output = + col + |> Enum.reduce(%{title: nil, description: nil, verses: []}, fn + {"div", _, [{"h3", [], ["Description"]} | para]}, acc -> + # IO.inspect(rem, label: "div") + desc = + para + |> Floki.text() + + %{acc | description: desc} + + {"div", _, [{"h3", _, _} = h3_tree]}, acc -> + title = + h3_tree + |> Floki.text() + + %{acc | title: title} + + {"div", _, [{"div", [{"class", "verse_sanskrit"}], _verse} | _] = verse_tree}, acc -> + [curr | [%{"count" => count} | _] = verses] = + Enum.reduce(verse_tree, [], fn + # n case verse break + {"hr", [{"class", "verse_separator"}], []}, [curr | [%{"count" => c} | _] = acc] -> + [Map.put(curr, "count", c + 1) | acc] + + # init verse break + {"hr", [{"class", "verse_separator"}], []}, [curr | acc] -> + [Map.put(curr, "count", 1) | acc] + + # n case after verse break + {"div", [{"class", class}], _} = c_tree, [%{"count" => _} | _] = acc -> + [%{class => c_tree |> Floki.text()} | acc] + + # n case before verse break + {"div", [{"class", class}], _} = c_tree, [curr | acc] when is_map(curr) -> + [Map.put(curr, class, c_tree |> Floki.text()) | acc] + + # init + {"div", [{"class", class}], _} = c_tree, [] -> + [%{class => c_tree |> Floki.text()}] + + others, acc -> + IO.inspect(others) + acc + end) + + # formatting & tying loose ends + clean_verses = + [Map.put(curr, "count", count + 1) | verses] + |> Enum.reverse() + + %{acc | verses: clean_verses} + + _, acc -> + acc + end) +``` + +```elixir +contents = Poison.encode!(output) +# File.write!("chalisa_scraped.json", contents) +filename = "chalisa_scraped.json" +url = "./Projects/vyasa/scripts/#{filename}" +File.write!(url, contents) +IO.puts(url) +``` + +```elixir +Floki.traverse_and_update(html, fn + {"div", _, _} = node -> {"div", [], ["Modified Div"]} + node -> node +end) + +text = find_element(:class, "verse_sanskrit") |> inner_text() +transliteration = find_element(:class, "verse_trans") |> inner_text() +en_translation = find_element(:class, "verse_meaning") |> inner_text() + +map = %{ + verse_number: count, + text: text, + transliteration: transliteration, + en_translation: en_translation +} +``` + + + +## Gita Events + +```elixir +gita = Vyasa.Written.get_source_by_title("Gita") +verses = Vyasa.Written.get_verses_in_chapter(1, gita.id) +verse_lookup = Enum.into(for(%{id: id, no: verse_no} <- verses, do: {verse_no, id}), %{}) + +c1_path = Path.expand("./1.mp3", "media/gita") + +{:ok, + %Vyasa.Parser.MP3{ + duration: tot_d, + path: p + }} = Vyasa.Parser.MP3.parse(c1_path) + +{:ok, voice} = + Vyasa.Medium.create_voice(%{lang: "sa", duration: tot_d, file_path: c1_path, source_id: gita.id}) + +# Vyasa.Medium.get_voice!("4c73fb6d-4163-4b64-90d0-5d49680c1ee4") +# |> Vyasa.Medium.delete_voice() +``` + +```elixir +""" +start :- 00:00 +Shloka 1:- 00:33 +Shloka 2 :- 00:49 +Shloka 3:- 01:06 +Shloka 4:- 01:19 +Shloka 5:- 01:32 +Shloka 6:- 01:46 +Shloka 7:- 02:00 +Shloka 8:- 02:15 +Shloka 9:- 02:28 +Shloka 10:- 02:42 +Shloka 11:- 02:56 +Shloka 12:- 03:09 +Shloka 13:- 03:22 +Shloka 14:- 03:36 +Shloka 15:- 03:49 +Shloka 16:- 04:02 +Shloka 17:- 04:14 +Shloka 18:- 04:27 +Shloka 19:- 04:40 +Shloka 20:- 04:54 +Shloka 21:- 05:07 +Shloka 22:- 05:23 +Shloka 23:- 05:36 +Shloka 24:- 05:50 +Shloka 25:- 06:05 +Shloka 26:- 06:18 +Shloka 27:- 06:32 +Shloka 28:- 06:46 +Shloka 29:- 07:01 +Shloka 30:- 07:13 +Shloka 31:- 07:26 +Shloka 32 :- 07:38 +Shloka 33:- 07:52 +Shloka 34 :- 08:05 +Shloka 35 :- 08:18 +Shloka 36 :- 08:31 +Shloka 37:- 08:44 +Shloka 38 :- 08:57 +Shloka 39:- 09:09 +Shloka 40:- 09:22 +Shloka 41:- 09:35 +Shloka 42:- 09:48 +Shloka 43:- 10:02 +Shloka 44:- 10:16 +Shloka 45:- 10:29 +Shloka 46:- 10:40 +Shloka 47:- 10:53 +end:- 11:08 +""" +|> String.split("\n") +|> Enum.map(fn x -> + x + |> String.split(":-") + |> Enum.map(&String.trim/1) + |> Enum.reduce([], fn + <<"Shloka"::utf8, sep::utf8, verse_no::binary>>, acc -> + [verse_lookup[String.to_integer(verse_no)] | acc] + + bin, acc -> + [bin | acc] + end) +end) +|> IO.inspect(limit: :infinity) +|> Enum.reduce( + [], + fn + [time, "start"], acc -> + [%Vyasa.Medium.Event{origin: 0, phase: "start", voice_id: voice.id} | acc] + + [time, "end"], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{origin: d, duration: tot_d - d, phase: "end", voice_id: voice.id} + | [%{prev | duration: d - o} | acc] + ] + + [time, id], [%{origin: o} = prev | acc] -> + [min, sec] = time |> String.split(":") |> Enum.map(&String.to_integer/1) + d = (min * 60 + sec) * 1000 + + [ + %Vyasa.Medium.Event{origin: d, verse_id: id, voice_id: voice.id} + | [%{prev | duration: d - o} | acc] + ] + + _, acc -> + acc + end +) +|> Enum.map(&Vyasa.Medium.create_event(&1)) +``` diff --git a/fly.toml b/fly.toml index cefcd759..50d69fdd 100644 --- a/fly.toml +++ b/fly.toml @@ -26,5 +26,5 @@ swap_size_mb = 512 processes = ["app"] [http_service.concurrency] type = "connections" - hard_limit = 1000 - soft_limit = 1000 + hard_limit = 1001 + soft_limit = 888 diff --git a/lib/utils/string.ex b/lib/utils/string.ex new file mode 100644 index 00000000..c3213e9c --- /dev/null +++ b/lib/utils/string.ex @@ -0,0 +1,11 @@ +defmodule Utils.String do + @moduledoc """ + Contains functions useful for string operations, that need not be + web or server-specific. + """ + @doc """ + Inflexor logic that humanises snake_case string then converts to title case. + """ + def to_title_case(value) when is_binary(value), + do: Recase.to_title(value) +end diff --git a/lib/vyasa/adapters/og_adapter.ex b/lib/vyasa/adapters/og_adapter.ex new file mode 100644 index 00000000..03c42802 --- /dev/null +++ b/lib/vyasa/adapters/og_adapter.ex @@ -0,0 +1,60 @@ +defmodule Vyasa.Adapters.OgAdapter do + @moduledoc """ + Contains logic pertaining to the OpenGraph API, particularly serving as the adapter b/w + our liveview and our filesystem that contains necessary og assets. + """ + + alias Vyasa.Corpus.Gita + + @doc """ + Retrieves the actual content from the gita that is alluded to by an opengraph file name. + """ + def get_content(:gita, filename) do + case Regex.scan(~r/\d+/, filename) |> List.flatten() do + [chapter_num, verse_num] -> # TODO: this could use better guards. e.g. gita-1-000.png will break it + %{text: text} = Gita.verse(chapter_num, verse_num) + %{"src"=> :gita , "text"=> text} + _ -> {:error, "Malformed / unsupported filename #{filename}"} + end + end + + + @doc """ + Returns a complete url that can be used by any entity to find this file. + This function aims to abstract away the actual location (i.e. local tmp dir or s3[future]) + """ + def get_og_file_url(filename) do + System.tmp_dir() |> Path.join(filename) + end + + @doc """ + Returns a string representing the filename for a particular verse from a particular chapter of + the gita. Currently just supports gita. + """ + def encode_filename(src, [chapter_num, verse_num]) when src == :gita do + gita_uuid = "gita" # TODO: consider better unique ids based on what we want to support for our corpus. + gita_uuid <> "-" <> Integer.to_string(chapter_num) <> "-" <> Integer.to_string(verse_num) <> ".png" + end + + + @doc """ + Returns a map of information that can be gleaned from the filename. + """ + def decode_filename(src, filename) when src == :gita do + [chapter_num, verse_num] = Regex.scan(~r/\d+/, filename) |> List.flatten() + %{chapter_num => chapter_num, verse_num => verse_num} + end + + @supported_src_ids ["gita"] + @doc """ + Resolves src id from filename. Currently merely converts it to an existing atom. + """ + def resolve_src_id(filename) do + src_id = List.first(String.split(filename, "-")) + case Enum.member?(@supported_src_ids, src_id) do + true -> {:ok, String.to_existing_atom(src_id)} + _ -> {:error, "Unsupported source"} + end + end + +end diff --git a/lib/vyasa/corpus/engine/fallback.ex b/lib/vyasa/corpus/engine/fallback.ex new file mode 100644 index 00000000..a926c218 --- /dev/null +++ b/lib/vyasa/corpus/engine/fallback.ex @@ -0,0 +1,46 @@ +defmodule Vyasa.Corpus.Engine.Fallback do + @url "https://archive.org/wayback/available?url=" + + def run(path) do + #storage opts + @url + |> fetch_url(path) + |> IO.inspect() + |> fetch_tree() + end + + def fetch_url(url, path \\ "") do + case Req.get(url <> path, conn_opts()) do + {:ok, %{body: %{"archived_snapshots" => + %{"closest" => + %{"url" => url}}}}} -> + {:ok, url} + {:ok, %{body: %{"archived_snapshots" => %{}}}} -> + IO.inspect("Not Found", label: :fallback_err) + {:err, :not_found} + {:error, reason} -> + IO.inspect(reason, label: :fallback_err) + {:err, :fallback_failed} + end + end + + def fetch_tree({:ok, url}) do + url + |> to_https() + |> Req.get!(conn_opts()) + |> Map.get(:body) + end + + def fetch_tree(err), do: err + + defp to_https(url) do + url + |> URI.parse() + |> Map.put(:port, nil) + |> Map.put(:scheme, "https") + |> URI.to_string() + end + + defp conn_opts(), do: [connect_options: [transport_opts: [cacerts: :public_key.cacerts_get()]]] + +end diff --git a/lib/vyasa/corpus/engine/shlokam.ex b/lib/vyasa/corpus/engine/shlokam.ex new file mode 100644 index 00000000..7c461d97 --- /dev/null +++ b/lib/vyasa/corpus/engine/shlokam.ex @@ -0,0 +1,115 @@ +defmodule Vyasa.Corpus.Engine.Shlokam do + @url "https://shlokam.org/" + alias Vyasa.Corpus.Engine.Fallback + + def run(path, opts \\ []) do + #storage opts + @url + |> fetch_tree(path) + |> scrape() + |> store(path, Keyword.get(opts, :o, nil)) + end + + def fetch_tree(url, path \\ "") do + case Req.get!(url <> path, connect_options: [transport_opts: [cacerts: :public_key.cacerts_get()]]) do + %{body: body} -> + {:ok, body + |> Floki.parse_document!() + |> Floki.find(".uncode_text_column")} + %{status: 301, headers: header} -> + header + |> Keyword.get(:location) + |> fetch_tree() + + error -> + IO.inspect(error, label: :primary_site_err) + Fallback.run(url <> path) + end + end + + defp scrape({:ok, tree}) do + tree + |> Enum.reduce(%{title: nil, description: nil, verses: []}, fn + {"div", _, [{"h3", [], ["Description"]} | para]}, acc -> + # IO.inspect(rem, label: "div") + desc = + para + |> Floki.text() + + %{acc | description: desc} + + {"div", _, [{"h3", _, _} = h3_tree]}, acc -> + title = + h3_tree + |> Floki.text() + + %{acc | title: title} + + {"div", _, [{"div", [{"class", "verse_sanskrit"}], _verse} | _] = verse_tree}, acc -> + [curr | [%{"count" => count} | _] = verses] = + Enum.reduce(verse_tree, [], fn + # n case verse break + {"hr", [{"class", "verse_separator"}], []}, [curr | [%{"count" => c} | _] = acc] -> + [Map.put(curr, "count", c + 1) | acc] + + # init verse break + {"hr", [{"class", "verse_separator"}], []}, [curr | acc] -> + [Map.put(curr, "count", 1) | acc] + + # n case after verse break + {"div", [{"class", class}], _} = c_tree, [%{"count" => _} | _] = acc -> + [%{class => c_tree |> Floki.text()} | acc] + + # n case before verse break + {"div", [{"class", class}], _} = c_tree, [curr | acc] when is_map(curr)-> + [Map.put(curr, class, c_tree |> Floki.text()) | acc] + + # init + {"div", [{"class", class}], _} = c_tree, [] -> + [%{class => c_tree |> Floki.text()}] + + others, acc -> + IO.inspect(others) + acc + end) + + #formatting & tying loose ends + clean_verses = [Map.put(curr, "count", count + 1)| verses] + |> Enum.reverse() + + %{acc | verses: clean_verses} + + _, acc -> + acc + end) + end + + defp scrape(err), do: err + + def store(_text, _tree, "db") do + # TODO parsing logic into text indexer structs and db insert ops + end + + def store(tree, text, nil) do + # TODO parsing logic into text indexer structs and db insert ops + json = Jason.encode!(tree) + Application.app_dir(:vyasa, "priv") + |> Path.join("/static/corpus/shlokam.org/#{text}.json") + |> tap(&File.touch(&1)) + |> tap(&File.write!(&1, json)) + end + + def store(tree, text, file_path) do + # TODO parsing logic into text indexer structs and db insert ops + json = Jason.encode!(tree) + file_path + |> Path.join("/shlokam.org") + |> tap(&File.mkdir(&1)) + |> Path.join("/#{text}.json") + |> tap(&File.touch(&1)) + |> tap(&File.write!(&1, json)) + end + + + + end diff --git a/lib/vyasa/corpus/gita.ex b/lib/vyasa/corpus/gita.ex index 2770c250..f375d448 100644 --- a/lib/vyasa/corpus/gita.ex +++ b/lib/vyasa/corpus/gita.ex @@ -50,9 +50,21 @@ defmodule Vyasa.Corpus.Gita do @verses[String.to_atom(to_string(chapter_no))] |> Enum.map(&struct!(Gita.Verse, &1)) end + def verses(chapter_no) do @verses[String.to_atom(chapter_no)] |> Enum.map(&struct!(Gita.Verse, &1)) end + def verse(chapter_no, verse_no) when is_binary(verse_no) and is_binary(chapter_no) do + @verses[String.to_atom(chapter_no)] + |> Enum.find(fn %{:verse_number => verse_num} -> Integer.to_string(verse_num) === verse_no end) + + end + + def verse(_,_) do + %Vyasa.Corpus.Gita.Verse{} + + end + end diff --git a/lib/vyasa/corpus/migrator/dump.ex b/lib/vyasa/corpus/migrator/dump.ex new file mode 100644 index 00000000..fe225fb7 --- /dev/null +++ b/lib/vyasa/corpus/migrator/dump.ex @@ -0,0 +1,76 @@ +defmodule Vyasa.Corpus.Migrator.Dump do + alias Vyasa.Repo + + def table(mod) do + Code.ensure_loaded?(mod) + assoc = mod.__schema__(:associations) + mod + |> Repo.all() + |> Repo.preload(assoc) + |> Enum.map(fn r -> + r + |> hydrate_voices() + end) + |> Enum.map(&process_struct/1) + |> Jason.encode!() + end + + def save(mod) do + Path.expand("#{mod}/#{System.os_time}.json", "data") + |> tap(&File.mkdir_p!(Path.dirname(&1))) + |> File.open!([:write]) + |> IO.binwrite(table(mod)) + end + + # if voices being dumped need to have a media dump + def hydrate_voices(%{voices: [_v | _] = voices} = record) do + voices + |> Repo.preload(:video) + |> Vyasa.Medium.Store.hydrate() + |> Enum.map(&Vyasa.Medium.Store.download(&1)) + %{record | voices: voices} + end + + def hydrate_voices(r), do: r + + defp process_struct(%{__struct__: struct} = s) do + associations = struct.__schema__(:associations) + s + |> Map.from_struct() + |> Enum.map(&process_field(associations, &1)) + |> Enum.reject(fn {_k,v} -> is_nil(v) end) + |> Enum.into(%{}) + + end + + defp process_field(associations, {k, v}) when is_list(v) and is_struct(hd(v)) do + if k in associations do + {k, Enum.map(v, &process_struct/1)} + else + {k, v} + end + end + + defp process_field(_associations, {k, %Ecto.Association.NotLoaded{}}) do + {k, nil} + end + + defp process_field(_associations, {:__meta__, _}) do + {:reject, nil} + end + + defp process_field(_associations, {k, %DateTime{} = d}) do + {k, d} + end + + defp process_field(associations, {k, v}) when is_struct(v) do + if k in associations do + {k, process_struct(v)} + else + {k, Map.from_struct(v)} + end + end + + defp process_field(_associations, {k, v}), do: {k, v} + +end diff --git a/lib/vyasa/corpus/migrator/restore.ex b/lib/vyasa/corpus/migrator/restore.ex new file mode 100644 index 00000000..739b1317 --- /dev/null +++ b/lib/vyasa/corpus/migrator/restore.ex @@ -0,0 +1,6 @@ +defmodule Vyasa.Corpus.Migrator.Restore do + def read(path) do + File.read!(path) + |> Jason.decode!() + end +end diff --git a/lib/vyasa/medium.ex b/lib/vyasa/medium.ex new file mode 100644 index 00000000..d89a54e4 --- /dev/null +++ b/lib/vyasa/medium.ex @@ -0,0 +1,226 @@ +defmodule Vyasa.Medium do + + import Ecto.Query, warn: false + alias Vyasa.Medium.{Video, Voice, Event} + alias Vyasa.Medium + alias Vyasa.Repo + + + @doc """ + Gets a single voice. + + Raises `Ecto.NoResultsError` if the Voice does not exist. + + ## Examples + + iex> get_voice!(123) + %Voice{} + + iex> get_voice!(456) + ** (Ecto.NoResultsError) + + """ + def get_voice!(id) do + Repo.get!(Voice, id) + |> Repo.preload([:events]) + end + + def get_voice(source_id, chapter_no, lang) do + from(v in Voice, + where: v.source_id == ^source_id and v.lang == ^lang and v.chapter_no == ^chapter_no, + preload: [:events, :video]) + |> Repo.one() + end + + def get_voices!(%Voice{source_id: src_id, chapter_no: c_no, lang: l}) do + from(v in Voice, + where: v.source_id == ^src_id and v.chapter_no == ^c_no and v.lang == ^l, + preload: [:events]) + |> Repo.all() + end + + @doc """ + Returns a resolved path to the video, bsed on its type attribute. + + Currently mainly used for youtube videos, possibly more in the future. + """ + def resolve_video_url(%Video{ + type: type, + ext_uri: ext_uri, + } = _video) do + + cond do + type == "youtube" -> "https://www.youtube.com/watch?v=#{ext_uri}" + true -> ext_uri + end + + end + + + @doc """ + Creates a voice. + + ## Examples + + iex> create_voice(%{field: value}) + {:ok, %Voice{}} + + iex> create_voice(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_voice(attrs \\ %{}) do + %Voice{} + |> Voice.gen_changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a voice. + + ## Examples + + iex> update_voice(voice, %{field: new_value}) + {:ok, %Voice{}} + + iex> update_voice(voice, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_voice(%Voice{} = voice, attrs) do + voice + |> Voice.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a voice. + + ## Examples + + iex> delete_voice(voice) + {:ok, %Voice{}} + + iex> delete_voice(voice) + {:error, %Ecto.Changeset{}} + + """ + def delete_voice(%Voice{} = voice) do + Repo.delete(voice) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking voice changes. + + ## Examples + iex> change_voice(voice) + %Ecto.Changeset{data: %Voice{}} + """ + def change_voice(%Voice{} = voice, attrs \\ %{}) do + Voice.changeset(voice, attrs) + end + + @doc """ + Gets a single event. + + Raises `Ecto.NoResultsError` if the Event does not exist. + + ## Examples + + iex> get_event!(123) + %Event{} + + iex> get_event!(456) + ** (Ecto.NoResultsError) + + """ + def get_event!(id), do: Repo.get!(Event, id) + + def get_event_by_order!(%Event{origin: origin, voice_id: v_id}, order) do + #TODO merge Sangh Filters to fix -1 order case for origin backwards operators + (from e in Event, + preload: [:voice, :verse], + where: e.origin >= ^origin and e.voice_id == ^v_id, + order_by: e.origin, + offset: ^order, + limit: 1) + |> Repo.one!() + end + + @doc """ + Creates a event. + + ## Examples + + iex> create_event(%{field: value}) + {:ok, %Event{}} + + iex> create_event(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + + def create_event(attrs \\ %{}) + def create_event(%Event{} = event) do + event + |> Repo.insert() + end + def create_event(attrs) do + %Event{} + |> Event.changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a event. + + ## Examples + + iex> update_event(event, %{field: new_value}) + {:ok, %Event{}} + + iex> update_event(event, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_event(%Event{} = event, attrs) do + event + |> Event.changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a event. + + ## Examples + + iex> delete_event(event) + {:ok, %Event{}} + + iex> delete_event(event) + {:error, %Ecto.Changeset{}} + + """ + def delete_event(%Event{} = event) do + Repo.delete(event) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking event changes. + + ## Examples + iex> change_event(event) + %Ecto.Changeset{data: %Event{}} + """ + def change_event(%Event{} = event, attrs \\ %{}) do + Event.changeset(event, attrs) + end + + def load_events(%Voice{} = voice) do + voice + |> Medium.get_voices!() + |> List.first() + |> Medium.Store.hydrate() + end + +end diff --git a/lib/vyasa/medium/event.ex b/lib/vyasa/medium/event.ex new file mode 100644 index 00000000..dbd35628 --- /dev/null +++ b/lib/vyasa/medium/event.ex @@ -0,0 +1,39 @@ +defmodule Vyasa.Medium.Event do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Written.{Verse, Source} + alias Vyasa.Medium.Voice + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "events" do + field :origin, :integer + field :duration, :integer + field :phase, :string + + embeds_many :fragments, EventFrag do + field :offset, :integer + field :duration, :integer + field :quote, :string + field :status, :string + end + + belongs_to :verse, Verse, foreign_key: :verse_id, type: :binary_id + belongs_to :voice, Voice, foreign_key: :voice_id, type: :binary_id + belongs_to :source, Source, foreign_key: :source_id, type: :binary_id + end + + @doc false + def changeset(event, attrs) do + event + |> cast(attrs, [:origin, :duration, :phase, :verse_id, :voice_id, :source_id]) + |> cast_embed(:fragments, with: &frag_changeset/2) + |> validate_required([:origin, :duration, :fragments, :source_id]) + |> validate_inclusion(:phase, ["start", "end"]) + end + + def frag_changeset(frag, attrs) do + frag + |> cast(attrs, [:offset, :duration,:quote]) + end +end diff --git a/lib/vyasa/medium/ext/s3client.ex b/lib/vyasa/medium/ext/s3client.ex new file mode 100644 index 00000000..77975fb1 --- /dev/null +++ b/lib/vyasa/medium/ext/s3client.ex @@ -0,0 +1,22 @@ +defmodule Vyasa.Medium.Ext.S3Client do + @behaviour ExAws.Request.HttpClient + + require Logger + + def request(method, url, body, headers, http_opts) do + case http_opts do + [] -> :noop + opts -> Logger.debug(inspect({:http_opts, opts})) + end + + with {:ok, resp} <- + Finch.build(method, url, headers, body) + |> Finch.request(Vyasa.Finch) do + IO + {:ok, %{status_code: resp.status, body: resp.body, headers: resp.headers}} + else + {:error, reason} -> + {:error, %{reason: reason}} + end + end +end diff --git a/lib/vyasa/medium/playback.ex b/lib/vyasa/medium/playback.ex new file mode 100644 index 00000000..8e97c3ef --- /dev/null +++ b/lib/vyasa/medium/playback.ex @@ -0,0 +1,24 @@ + defmodule Vyasa.Medium.Playback do + @moduledoc """ + The Playback struct is a medium-agnostic way of representing the playback of a generic "media". + It shall be a reference struct which audio/video players shall use to sync up with each other. + """ + alias Vyasa.Medium.{Playback} + + defstruct [:medium, playing?: false, played_at: nil, paused_at: nil, elapsed: 0, current_time: 0] + + def new(%{} = attrs) do + %Vyasa.Medium.Playback{ + playing?: attrs.playing?, + played_at: nil, # timestamps + paused_at: nil, # timestamps + elapsed: 0, # seconds TODO: convert to ms to standardise w HTML players? + } + end + + def init_playback() do + Playback.new(%{ + playing?: false + }) + end +end diff --git a/lib/vyasa/medium/store.ex b/lib/vyasa/medium/store.ex new file mode 100644 index 00000000..509e291d --- /dev/null +++ b/lib/vyasa/medium/store.ex @@ -0,0 +1,111 @@ +defmodule Vyasa.Medium.Store do + @moduledoc """ + S3 Object Storage Service Communicator using HTTP POST sigv4 + https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html + """ + + alias Vyasa.Medium + + @bucket "vyasa" + + def path(st) when is_struct(st) do + #input and output paths + {local_path(st), path_constructor(st)} + end + + def get(st) when is_struct(st) do + signer(:get, path_constructor(st)) + end + + def get(path) do + signer(:get, path) + end + + def get!(st) when is_struct(st) do + signer!(:get, path_constructor(st)) + end + + def get!(path) do + signer!(:get, path) + end + + def put(struct) do + signer(:put, path_constructor(struct)) + end + + def put!(struct) do + signer!(:put, path_constructor(struct)) + end + + def hydrate([%Medium.Voice{} | _] = voices) do + Enum.map(voices, &(%{&1 | file_path: get!(&1)})) + end + + def hydrate(%Medium.Voice{} = voice) do + %{voice | file_path: get!(voice)} + end + + def hydrate(rt), do: rt + + def download(%Medium.Voice{file_path: url} = v) do + bin = Finch.build(:get, url) + |> Finch.request!(Vyasa.Finch) + |> Map.get(:body) + + Path.expand(path_constructor(v), "media") + |> tap(&File.mkdir_p!(Path.dirname(&1))) + |> File.write!(bin) + end + + + def s3_config do + %{ + region: System.fetch_env!("AWS_DEFAULT_REGION"), + bucket: @bucket, + access_key_id: System.fetch_env!("AWS_ACCESS_KEY_ID"), + secret_access_key: System.fetch_env!("AWS_SECRET_ACCESS_KEY") + } + end + + defp signer!(action, path) do + {:ok, url} = signer(action, path) + url + end + + defp signer(:headandget, path) do + ExAws.S3.head_object("orbistertius", path) + |> ExAws.request!() + ## with 200 + signer(:get, path) + ## else (pass signer link of fallback image function or nil) + end + + + defp signer(action, path) do + ExAws.Config.new(:s3, s3_config()) |> + ExAws.S3.presigned_url(action, @bucket, path, + [expires_in: 88888, virtual_host: false, query_params: [{"ContentType", "application/octet-stream"}]]) + end + + defp local_path(%Medium.Voice{file_path: local_path}) do + local_path + end + + defp path_constructor(%Medium.Voice{__meta__: %{source: type}, id: id}) do + "#{type}/#{id}.mp3" #default to mp3 ext for now + end + + defp path_constructor(%Medium.Voice{__meta__: %{source: type}, source: %{title: st}, meta: %{artists: [ artist | _]}}) do + "#{type}#{unless is_nil(st), + do: "/#{st}"}#{unless is_nil(artist), + do: "/#{artist}"}" + end + + + # defp path_suffix(full, prefix) do + # base = byte_size(prefix) + # <<_::binary-size(base), rest::binary>> = full + # rest + # end + +end diff --git a/lib/vyasa/medium/track.ex b/lib/vyasa/medium/track.ex new file mode 100644 index 00000000..5b55a727 --- /dev/null +++ b/lib/vyasa/medium/track.ex @@ -0,0 +1,28 @@ +defmodule Vyasa.Medium.Track do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Medium.Voice + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "tracks" do + field :title, :string + has_many :voices, Voice + + timestamps(type: :utc_datetime) + end + + @doc false + def gen_changeset(track, attrs) do + track + |> cast(attrs, [:id, :title]) + |> cast_assoc(:verses) + |> validate_required([:title]) + end + + def mutate_changeset(track, attrs) do + track + |> cast(attrs, [:id, :title]) + |> cast_assoc(:verses) + end +end diff --git a/lib/vyasa/medium/video.ex b/lib/vyasa/medium/video.ex new file mode 100644 index 00000000..5f80c1c4 --- /dev/null +++ b/lib/vyasa/medium/video.ex @@ -0,0 +1,29 @@ +defmodule Vyasa.Medium.Video do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Medium.Voice + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "videos" do + field :type, :string + field :ext_uri, :string + + belongs_to :voice, Voice, references: :id, foreign_key: :voice_id, type: :binary_id + + timestamps(type: :utc_datetime) + end + + @doc false + def changeset(video, attrs) do + video + |> cast(attrs, [:type, :ext_uri]) + |> validate_required([:title]) + end + + def gen_changeset(video, attrs, %Voice{id: voice_id}) do + %{video | voice_id: voice_id} + |> cast(attrs, [:type, :ext_uri]) + |> validate_required([:type, :ext_uri]) + end +end diff --git a/lib/vyasa/medium/voice.ex b/lib/vyasa/medium/voice.ex new file mode 100644 index 00000000..7fa8a46b --- /dev/null +++ b/lib/vyasa/medium/voice.ex @@ -0,0 +1,61 @@ +defmodule Vyasa.Medium.Voice do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Written.{Source, Chapter} + alias Vyasa.Medium.{Event, Video, Track} + + @primary_key {:id, Ecto.UUID, autogenerate: false} + schema "voices" do + field :lang, :string + field :title, :string + field :duration, :integer + field :file_path, :string, virtual: true + + embeds_one :meta, VoiceMetadata do + field(:artist, {:array, :string}) + end + + has_one :video, Video, references: :id, foreign_key: :voice_id + has_many :events, Event, references: :id, foreign_key: :voice_id, preload_order: [asc: :origin] + + belongs_to :track, Track, references: :id, foreign_key: :track_id + belongs_to :chapter, Chapter, type: :integer, references: :no, foreign_key: :chapter_no + belongs_to :source, Source, references: :id, foreign_key: :source_id, type: :binary_id + + timestamps(type: :utc_datetime) + end + + @doc false + + def gen_changeset(voice, attrs) do + %{voice | id: Ecto.UUID.generate()} + |> cast(attrs, [:id, :title, :duration, :lang, :file_path, :chapter_no, :source_id]) + |> cast_embed(:meta, with: &meta_changeset/2) + |> file_upload() + end + + def changeset(voice, attrs) do + voice + |> cast(attrs, [:id, :title, :duration, :lang, :file_path, :chapter_no, :source_id]) + |> cast_embed(:meta, with: &meta_changeset/2) + |> cast_assoc(:video) + |> cast_assoc(:events) + end + + def meta_changeset(voice, attrs) do + voice + |> cast(attrs, [:artist]) + end + + def file_upload(%Ecto.Changeset{changes: %{file_path: _} = changes} = ec) do + ext_path = apply_changes(ec) + |> Vyasa.Medium.Writer.run() + |> then(&elem(&1, 1).key) + |> Vyasa.Medium.Store.get!() + + %{ec | changes: %{changes | file_path: ext_path}} + end + + def file_upload(ec), do: ec +end diff --git a/lib/vyasa/medium/writer.ex b/lib/vyasa/medium/writer.ex new file mode 100644 index 00000000..bddbccd5 --- /dev/null +++ b/lib/vyasa/medium/writer.ex @@ -0,0 +1,52 @@ +defmodule Vyasa.Medium.Writer do + @behaviour Phoenix.LiveView.UploadWriter + + alias Vyasa.Medium.Store + + @impl true + def init(struct) do + {local_path, ext_path} = Store.path(struct) + with {:ok, file} <- File.open(local_path, [:binary, :write]), + %{bucket: bucket} = config <- Store.s3_config(), + s3_op <- ExAws.S3.initiate_multipart_upload(bucket, ext_path) do + {:ok, %{file: file, path: local_path, key: ext_path, chunk: 1, s3_op: s3_op, s3_config: ExAws.Config.new(:s3, config)}} + end + end + + def run(struct) do + {local_path, ext_path} = Store.path(struct) + with fs <- ExAws.S3.Upload.stream_file(local_path), + %{bucket: bucket} = cfg <- Store.s3_config(), + req <- ExAws.S3.upload(fs, bucket, ext_path), + {:ok, %{status_code: 200, body: body}} <- ExAws.request(req, config: cfg) do + {:ok, body} + else + {:err, err} -> {:err, err} + end + end + + @impl true + def meta(state) do + %{local_path: state.path, key: state.key} + end + + @impl true + def write_chunk(data, state) do + case IO.binwrite(state.file, data) do + :ok -> + part = ExAws.S3.Upload.upload_chunk!({data, state.chunk}, state.s3_op, state.s3_config) + {:ok, %{state | chunk: state.chunk+1, parts: [part | state.parts]}} + {:error, reason} -> {:error, reason, state} + end + end + + @impl true + def close(state, _reason) do + case {File.close(state.file), ExAws.S3.Upload.complete(state.parts, state.s3_op, state.s3_config)} do + {:ok, {:ok, _}} -> + {:ok, state} + {{:error, reason}, _} -> {:error, reason} + {_,{:error, reason}} -> {:error, reason} + end + end +end diff --git a/lib/vyasa/parser/env.ex b/lib/vyasa/parser/env.ex new file mode 100644 index 00000000..90923f52 --- /dev/null +++ b/lib/vyasa/parser/env.ex @@ -0,0 +1,323 @@ +defmodule Vyasa.Parser.Env do + @moduledoc """ + Simple parser for .env files. + + Supports simple variable–value pairs with upper and lower cased variables. Values are trimmed of extra whitespace. + + Blank lines and lines starting with `#` are ignored. Additionally inline comments can be added after values with a + `#`, i.e. `FOO=bar # comment`. + + Single quote or double quote value to prevent trimming of whitespace and allow usage of `#` in value, i.e. `FOO=' bar # not comment ' # comment`. + + Single quoted values don't do any unescaping. Double quoted values will unescape the following: + + * `\\n` - Linefeed + * `\\r` - Carriage return + * `\\t` - Tab + * `\\f` - Form feed + * `\\b` - Backspace + * `\\"` and `\\'` - Quotes + * `\\\\` - Backslash + * `\\uFFFF` - Unicode escape (4 hex characters to denote the codepoint) + * A backslash at the end of the line in a multiline value will remove the linefeed. + + Values can span multiple lines when single or double quoted: + + ```sh + MULTILINE="This is a + multiline value." + ``` + + This will result in the following: + + ```elixir + System.fetch_env!("MULTILINE") == "This is a\\nmultiline value." + ``` + + A line can start with `export ` for easier interoperation with regular shell scripts. These lines are treated the + same as any others. + + ## Serving suggestion + + If you load lots of environment variables in `config/runtime.exs`, you can easily configure them for development by + having an `.env` file in your development environment and using the parser at the start of the file: + + ```elixir + import Config + + if Config.config_env() == :dev do + Vyasa.Parser.Env.load_file(".env") + end + + # Now variables from `.env` are loaded into system env + config :your_project, + database_url: System.fetch_env!("DB_URL") + """ + + @linefeed_re ~r/\r?\n/ + @line_re ~r/^(?:\s*export)?\s*[a-z_][a-z_0-9]*\s*=/i + @dquoted_val_re ~r/^"([^"\\]*(?:\\.[^"\\]*)*)"\s*(?:#.*)?$/ + @squoted_val_re ~r/^\s*'(.*)'\s*(?:#.*)?$/ + @dquoted_multiline_end ~r/^([^"\\]*(?:\\.[^"\\]*)*)"\s*(?:#.*)?$/ + @squoted_multiline_end ~r/^(.*)'\s*(?:#.*)?$/ + @hex_re ~r/^[0-9a-f]+$/i + + @quote_chars ~w(" ') + + @typedoc "Pair of variable name, variable value." + @type value_pair :: {String.t(), String.t()} + + defmodule ParseError do + @moduledoc "Error raised when a line cannot be parsed." + defexception [:message] + end + + defmodule Continuation do + @typedoc """ + A multiline value continuation. When a function returns this, it means that a multiline value + was started and more needs to be parsed to get the rest of the value. + """ + @type t :: %__MODULE__{ + name: String.t(), + value: String.t(), + start_quote: String.t() + } + @enforce_keys [:name, :value, :start_quote] + defstruct [:name, :value, :start_quote] + end + + @doc """ + Parse given file and load the variables to the environment. + + If a line cannot be parsed or the file cannot be read, an error is raised and no values are loaded to the + environment. + """ + @spec load_file(String.t()) :: :ok + def load_file(file) do + file + |> File.read!() + |> load_data() + end + + @doc """ + Parse given data and load the variables to the environment. + + If a line cannot be parsed, an error is raised and no values are loaded to the environment. + """ + @spec load_data(String.t()) :: :ok + def load_data(data) do + data + |> parse_data() + |> Enum.each(fn {var, val} -> System.put_env(var, val) end) + end + + @doc """ + Parse given file and return a list of variable–value tuples. + + If a line cannot be parsed or the file cannot be read, an error is raised. + """ + @spec parse_file(String.t()) :: [value_pair()] + def parse_file(file) do + file + |> File.read!() + |> parse_data() + end + + @doc """ + Parse given data and return a list of variable–value tuples. + + If a line cannot be parsed, an error is raised. + """ + @spec parse_data(String.t()) :: [value_pair()] + def parse_data(data) do + {value_pairs, continuation} = + data + |> String.split(@linefeed_re) + |> Enum.reduce({[], nil}, fn + line, {ret, nil} -> + trimmed = String.trim(line) + + if not is_comment?(trimmed) and not is_blank?(trimmed) do + reduce_line(ret, line, nil) + else + {ret, nil} + end + + line, {ret, continuation} -> + reduce_line(ret, line, continuation) + end) + + if not is_nil(continuation) do + raise ParseError, + "Could not find end for quote #{continuation.start_quote} in variable #{continuation.name}" + end + + Enum.reverse(value_pairs) + end + + @doc """ + Parse given single line and return a variable–value tuple, or a continuation value if the line + started or continued a multiline value. + + If line cannot be parsed, an error is raised. + + The second argument needs to be `nil` or a continuation value returned from parsing the previous + line. + """ + @spec parse_line(String.t(), Continuation.t() | nil) :: value_pair() | Continuation.t() + def parse_line(line, state) + + def parse_line(line, nil) do + if not Regex.match?(@line_re, line) do + raise ParseError, "Malformed line cannot be parsed: #{line}" + else + [var, val] = String.split(line, "=", parts: 2) + var = var |> String.trim() |> String.replace_leading("export ", "") + trimmed = String.trim(val) + + with {:dquoted, nil} <- {:dquoted, Regex.run(@dquoted_val_re, trimmed)}, + {:squoted, nil} <- {:squoted, Regex.run(@squoted_val_re, trimmed)}, + trimmed_leading = String.trim_leading(val), + {:quoted_start, false} <- + {:quoted_start, String.starts_with?(trimmed_leading, @quote_chars)} do + # Value is plain value + {var, trimmed |> remove_comment() |> String.trim()} + else + {:dquoted, [_, inner_val]} -> + {var, stripslashes(inner_val)} + + {:squoted, [_, inner_val]} -> + {var, inner_val} + + {:quoted_start, _} -> + parse_multiline_start(var, val) + end + end + end + + def parse_line(line, %Continuation{} = continuation) do + trimmed = String.trim_trailing(line) + + end_match = + if continuation.start_quote == "\"" do + Regex.run(@dquoted_multiline_end, trimmed) + else + Regex.run(@squoted_multiline_end, trimmed) + end + + with [_, line_content] <- end_match do + ret = maybe_stripslashes(continuation, line_content) + {continuation.name, continuation.value <> ret} + else + _ -> + next_line = maybe_stripslashes(continuation, line) + next_line = maybe_linefeed(continuation, next_line) + + %Continuation{ + continuation + | value: continuation.value <> next_line + } + end + end + + @spec parse_multiline_start(String.t(), String.t()) :: Continuation.t() + defp parse_multiline_start(name, input) do + {start_quote, rest} = input |> String.trim_leading() |> String.split_at(1) + + continuation = %Continuation{ + name: name, + value: "", + start_quote: start_quote + } + + value = maybe_stripslashes(continuation, rest) + value = maybe_linefeed(continuation, value) + + %Continuation{continuation | value: value} + end + + @spec reduce_line([value_pair()], String.t(), Continuation.t() | nil) :: + {[value_pair()], Continuation.t() | nil} + defp reduce_line(ret, line, continuation) do + case parse_line(line, continuation) do + %Continuation{} = new_continuation -> + {ret, new_continuation} + + result -> + {[result | ret], nil} + end + end + + @spec remove_comment(String.t()) :: String.t() + defp remove_comment(val) do + case String.split(val, "#", parts: 2) do + [true_val, _comment] -> true_val + [true_val] -> true_val + end + end + + @spec is_comment?(String.t()) :: boolean() + defp is_comment?(line) + defp is_comment?("#" <> _rest), do: true + defp is_comment?(_line), do: false + + @spec is_blank?(String.t()) :: boolean() + defp is_blank?(line) + defp is_blank?(""), do: true + defp is_blank?(_line), do: false + + @spec stripslashes(String.t(), :slash | :no_slash, String.t()) :: String.t() + defp stripslashes(input, mode \\ :no_slash, acc \\ "") + + defp stripslashes("\\" <> rest, :no_slash, acc) do + stripslashes(rest, :slash, acc) + end + + defp stripslashes("", :no_slash, acc), do: acc + + defp stripslashes(input, :no_slash, acc) do + case String.split(input, "\\", parts: 2) do + [all] -> acc <> all + [head, tail] -> stripslashes(tail, :slash, acc <> head) + end + end + + defp stripslashes("n" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\n") + defp stripslashes("r" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\r") + defp stripslashes("t" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\t") + defp stripslashes("f" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\f") + defp stripslashes("b" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\b") + defp stripslashes("\"" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\"") + defp stripslashes("'" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "'") + defp stripslashes("\\" <> rest, :slash, acc), do: stripslashes(rest, :no_slash, acc <> "\\") + + defp stripslashes(<<"u", hex::binary-size(4), rest::binary>>, :slash, acc) do + with true <- Regex.match?(@hex_re, hex), + {int, _rest} <- Integer.parse(hex, 16) do + stripslashes(rest, :no_slash, acc <> <>) + else + _ -> stripslashes(rest, :no_slash, acc <> "\\u" <> hex) + end + end + + defp stripslashes(input, :slash, acc), do: stripslashes(input, :no_slash, acc <> "\\") + + @spec maybe_stripslashes(Continuation.t(), String.t()) :: String.t() + defp maybe_stripslashes(continuation, input) + + defp maybe_stripslashes(%Continuation{start_quote: "\""}, input), do: stripslashes(input) + defp maybe_stripslashes(_, input), do: input + + @spec maybe_linefeed(Continuation.t(), String.t()) :: String.t() + defp maybe_linefeed(continuation, input) + + defp maybe_linefeed(%Continuation{start_quote: "\""}, input) do + if String.ends_with?(input, "\\") do + String.slice(input, 0..-2) + else + input <> "\n" + end + end + + defp maybe_linefeed(_, input), do: input <> "\n" +end diff --git a/lib/vyasa/parser/mp3.ex b/lib/vyasa/parser/mp3.ex new file mode 100644 index 00000000..ece61245 --- /dev/null +++ b/lib/vyasa/parser/mp3.ex @@ -0,0 +1,398 @@ +defmodule Vyasa.Parser.MP3 do + @moduledoc """ + Decodes MP3s and parses out information. + + MP3 decoding and duration calculation credit to: + https://shadowfacts.net/2021/mp3-duration/ + """ + import Bitwise + + defstruct duration: 0, size: 0, path: nil, title: nil, artist: nil, tags: nil + + @declared_frame_ids ~w(AENC APIC ASPI COMM COMR ENCR EQU2 ETCO GEOB GRID LINK MCDI MLLT OWNE PRIV PCNT POPM POSS RBUF RVA2 RVRB SEEK SIGN SYLT SYTC TALB TBPM TCOM TCON TCOP TDEN TDLY TDOR TDRC TDRL TDTG TENC TEXT TFLT TIPL TIT1 TIT2 TIT3 TKEY TLAN TLEN TMCL TMED TMOO TOAL TOFN TOLY TOPE TOWN TPE1 TPE2 TPE3 TPE4 TPOS TPRO TPUB TRCK TRSN TRSO TSOA TSOP TSOT TSRC TSSE TSST TXXX UFID USER USLT WCOM WCOP WOAF WOAR WOAS WORS WPAY WPUB WXXX) + + @v1_l1_bitrates {:invalid, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, + :invalid} + @v1_l2_bitrates {:invalid, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, + :invalid} + @v1_l3_bitrates {:invalid, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, + :invalid} + @v2_l1_bitrates {:invalid, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, + :invalid} + @v2_l2_l3_bitrates {:invalid, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, + :invalid} + + def to_mmss(duration) when is_integer(duration) do + hours = div(duration, 60 * 60) + minutes = div(duration - hours * 60 * 60, 60) + seconds = rem(duration - hours * 60 * 60 - minutes * 60, 60) + + [minutes, seconds] + |> Enum.map(fn count -> String.pad_leading("#{count}", 2, ["0"]) end) + |> Enum.join(":") + end + + def parse(path) do + stat = File.stat!(path) + {tag_info, rest} = parse_tag(File.read!(path)) + duration = parse_frame(rest, 0, 0, 0) + + case duration do + duration when is_float(duration) and duration > 0 -> + title = Enum.at(tag_info["TIT2"] || [], 0) + artist = Enum.at(tag_info["TPE1"] || [], 0) + seconds = round(duration * 1000) + + {:ok, + %__MODULE__{ + duration: seconds, + size: stat.size, + path: path, + tags: tag_info, + title: title, + artist: artist + }} + + _other -> + {:error, :bad_file} + end + rescue + _ -> {:error, :bad_file} + end + + defp parse_tag(<< + "ID3", + major_version::integer, + _revision::integer, + _unsynchronized::size(1), + extended_header::size(1), + _experimental::size(1), + _footer::size(1), + 0::size(4), + tag_size_synchsafe::binary-size(4), + rest::binary + >>) do + tag_size = decode_synchsafe_integer(tag_size_synchsafe) + + {rest, ext_header_size} = + if extended_header == 1 do + skip_extended_header(major_version, rest) + else + {rest, 0} + end + + parse_frames(major_version, rest, tag_size - ext_header_size, []) + end + + defp parse_tag(<< + _first::integer, + _second::integer, + _third::integer, + rest::binary + >>) do + # has no ID3 + {%{}, rest} + end + + defp parse_tag(_), do: {%{}, ""} + + defp decode_synchsafe_integer(<>), do: bin + + defp decode_synchsafe_integer(binary) do + binary + |> :binary.bin_to_list() + |> Enum.reverse() + |> Enum.with_index() + |> Enum.reduce(0, fn {el, index}, acc -> acc ||| el <<< (index * 7) end) + end + + defp skip_extended_header(3, << + ext_header_size::size(32), + _flags::size(16), + _padding_size::size(32), + rest::binary + >>) do + remaining_ext_header_size = ext_header_size - 6 + <<_::binary-size(remaining_ext_header_size), rest::binary>> = rest + {rest, ext_header_size} + end + + defp skip_extended_header(4, << + ext_header_size_synchsafe::size(32), + 1::size(8), + _flags::size(8), + rest::binary + >>) do + ext_header_size = decode_synchsafe_integer(ext_header_size_synchsafe) + remaining_ext_header_size = ext_header_size - 6 + <<_::binary-size(remaining_ext_header_size), rest::binary>> = rest + {rest, ext_header_size} + end + + defp parse_frames(_, data, tag_length_remaining, frames) + when tag_length_remaining <= 0 do + {Map.new(frames), data} + end + + defp parse_frames( + major_version, + << + frame_id::binary-size(4), + frame_size_maybe_synchsafe::binary-size(4), + 0::size(1), + _tag_alter_preservation::size(1), + _file_alter_preservation::size(1), + _read_only::size(1), + 0::size(4), + _grouping_identity::size(1), + 0::size(2), + _compression::size(1), + _encryption::size(1), + _unsynchronized::size(1), + _has_data_length_indicator::size(1), + _unused::size(1), + rest::binary + >>, + tag_length_remaining, + frames + ) do + frame_size = + case major_version do + 4 -> + decode_synchsafe_integer(frame_size_maybe_synchsafe) + + 3 -> + <> = frame_size_maybe_synchsafe + size + end + + total_frame_size = frame_size + 10 + next_tag_length_remaining = tag_length_remaining - total_frame_size + + result = decode_frame(frame_id, frame_size, rest) + + case result do + {nil, rest, :halt} -> + {Map.new(frames), rest} + + {nil, rest, :cont} -> + parse_frames(major_version, rest, next_tag_length_remaining, frames) + + {new_frame, rest} -> + parse_frames(major_version, rest, next_tag_length_remaining, [new_frame | frames]) + end + end + + defp parse_frames(_, data, _, frames) do + {Map.new(frames), data} + end + + defp decode_frame("TXXX", frame_size, <>) do + {description, desc_size, rest} = decode_string(text_encoding, frame_size - 1, rest) + {value, _, rest} = decode_string(text_encoding, frame_size - 1 - desc_size, rest) + {{"TXXX", {description, value}}, rest} + end + + defp decode_frame( + "COMM", + frame_size, + <> + ) do + {short_desc, desc_size, rest} = decode_string(text_encoding, frame_size - 4, rest) + {value, _, rest} = decode_string(text_encoding, frame_size - 4 - desc_size, rest) + {{"COMM", {language, short_desc, value}}, rest} + end + + defp decode_frame("APIC", frame_size, <>) do + {mime_type, mime_len, rest} = decode_string(0, frame_size - 1, rest) + + <> = rest + + {description, desc_len, rest} = + decode_string(text_encoding, frame_size - 1 - mime_len - 1, rest) + + image_data_size = frame_size - 1 - mime_len - 1 - desc_len + {image_data, rest} = :erlang.split_binary(rest, image_data_size) + + {{"APIC", {mime_type, picture_type, description, image_data}}, rest} + end + + defp decode_frame(id, frame_size, rest) do + cond do + Regex.match?(~r/^T[0-9A-Z]+$/, id) -> + decode_text_frame(id, frame_size, rest) + + id in @declared_frame_ids -> + <<_frame_data::binary-size(frame_size), rest::binary>> = rest + {nil, rest, :cont} + + true -> + {nil, rest, :halt} + end + end + + defp decode_text_frame(id, frame_size, <>) do + {strs, rest} = decode_string_sequence(text_encoding, frame_size - 1, rest) + {{id, strs}, rest} + end + + defp decode_string_sequence(encoding, max_byte_size, data, acc \\ []) + + defp decode_string_sequence(_, max_byte_size, data, acc) when max_byte_size <= 0 do + {Enum.reverse(acc), data} + end + + defp decode_string_sequence(encoding, max_byte_size, data, acc) do + {str, str_size, rest} = decode_string(encoding, max_byte_size, data) + decode_string_sequence(encoding, max_byte_size - str_size, rest, [str | acc]) + end + + defp convert_string(encoding, str) when encoding in [0, 3] do + str + end + + defp convert_string(1, data) do + {encoding, bom_length} = :unicode.bom_to_encoding(data) + {_, string_data} = String.split_at(data, bom_length) + :unicode.characters_to_binary(string_data, encoding) + end + + defp convert_string(2, data) do + :unicode.characters_to_binary(data, {:utf16, :big}) + end + + defp decode_string(encoding, max_byte_size, data) when encoding in [1, 2] do + {str, rest} = get_double_null_terminated(data, max_byte_size) + + {convert_string(encoding, str), byte_size(str) + 2, rest} + end + + defp decode_string(encoding, max_byte_size, data) when encoding in [0, 3] do + case :binary.split(data, <<0>>) do + [str, rest] when byte_size(str) + 1 <= max_byte_size -> + {str, byte_size(str) + 1, rest} + + _ -> + {str, rest} = :erlang.split_binary(data, max_byte_size) + {str, max_byte_size, rest} + end + end + + defp get_double_null_terminated(data, max_byte_size, acc \\ []) + + defp get_double_null_terminated(rest, 0, acc) do + {acc |> Enum.reverse() |> :binary.list_to_bin(), rest} + end + + defp get_double_null_terminated(<<0, 0, rest::binary>>, _, acc) do + {acc |> Enum.reverse() |> :binary.list_to_bin(), rest} + end + + defp get_double_null_terminated(<>, max_byte_size, acc) do + next_max_byte_size = max_byte_size - 2 + get_double_null_terminated(rest, next_max_byte_size, [b, a | acc]) + end + + defp parse_frame( + << + 0xFF::size(8), + 0b111::size(3), + version_bits::size(2), + layer_bits::size(2), + _protected::size(1), + bitrate_index::size(4), + sampling_rate_index::size(2), + padding::size(1), + _private::size(1), + _channel_mode_index::size(2), + _mode_extension::size(2), + _copyright::size(1), + _original::size(1), + _emphasis::size(2), + _rest::binary + >> = data, + acc, + frame_count, + offset + ) do + with version when version != :invalid <- lookup_version(version_bits), + layer when layer != :invalid <- lookup_layer(layer_bits), + sampling_rate when sampling_rate != :invalid <- + lookup_sampling_rate(version, sampling_rate_index), + bitrate when bitrate != :invalid <- lookup_bitrate(version, layer, bitrate_index) do + samples = lookup_samples_per_frame(version, layer) + frame_size = get_frame_size(samples, layer, bitrate, sampling_rate, padding) + frame_duration = samples / sampling_rate + <<_skipped::binary-size(frame_size), rest::binary>> = data + parse_frame(rest, acc + frame_duration, frame_count + 1, offset + frame_size) + else + _ -> + <<_::size(8), rest::binary>> = data + parse_frame(rest, acc, frame_count, offset + 1) + end + end + + defp parse_frame(<<_::size(8), rest::binary>>, acc, frame_count, offset) do + parse_frame(rest, acc, frame_count, offset + 1) + end + + defp parse_frame(<<>>, acc, _frame_count, _offset) do + acc + end + + defp lookup_version(0b00), do: :version25 + defp lookup_version(0b01), do: :invalid + defp lookup_version(0b10), do: :version2 + defp lookup_version(0b11), do: :version1 + + defp lookup_layer(0b00), do: :invalid + defp lookup_layer(0b01), do: :layer3 + defp lookup_layer(0b10), do: :layer2 + defp lookup_layer(0b11), do: :layer1 + + defp lookup_sampling_rate(_version, 0b11), do: :invalid + defp lookup_sampling_rate(:version1, 0b00), do: 44100 + defp lookup_sampling_rate(:version1, 0b01), do: 48000 + defp lookup_sampling_rate(:version1, 0b10), do: 32000 + defp lookup_sampling_rate(:version2, 0b00), do: 22050 + defp lookup_sampling_rate(:version2, 0b01), do: 24000 + defp lookup_sampling_rate(:version2, 0b10), do: 16000 + defp lookup_sampling_rate(:version25, 0b00), do: 11025 + defp lookup_sampling_rate(:version25, 0b01), do: 12000 + defp lookup_sampling_rate(:version25, 0b10), do: 8000 + + defp lookup_bitrate(_version, _layer, 0), do: :invalid + defp lookup_bitrate(_version, _layer, 0xF), do: :invalid + defp lookup_bitrate(:version1, :layer1, index), do: elem(@v1_l1_bitrates, index) + defp lookup_bitrate(:version1, :layer2, index), do: elem(@v1_l2_bitrates, index) + defp lookup_bitrate(:version1, :layer3, index), do: elem(@v1_l3_bitrates, index) + + defp lookup_bitrate(v, :layer1, index) when v in [:version2, :version25], + do: elem(@v2_l1_bitrates, index) + + defp lookup_bitrate(v, l, index) when v in [:version2, :version25] and l in [:layer2, :layer3], + do: elem(@v2_l2_l3_bitrates, index) + + defp lookup_samples_per_frame(:version1, :layer1), do: 384 + defp lookup_samples_per_frame(:version1, :layer2), do: 1152 + defp lookup_samples_per_frame(:version1, :layer3), do: 1152 + defp lookup_samples_per_frame(v, :layer1) when v in [:version2, :version25], do: 384 + defp lookup_samples_per_frame(v, :layer2) when v in [:version2, :version25], do: 1152 + defp lookup_samples_per_frame(v, :layer3) when v in [:version2, :version25], do: 576 + + defp get_frame_size(samples, layer, kbps, sampling_rate, padding) do + sample_duration = 1 / sampling_rate + frame_duration = samples * sample_duration + bytes_per_second = kbps * 1000 / 8 + size = floor(frame_duration * bytes_per_second) + + if padding == 1 do + size + lookup_slot_size(layer) + else + size + end + end + + defp lookup_slot_size(:layer1), do: 4 + defp lookup_slot_size(l) when l in [:layer2, :layer3], do: 1 +end diff --git a/lib/vyasa/pubsub.ex b/lib/vyasa/pubsub.ex new file mode 100644 index 00000000..b795c373 --- /dev/null +++ b/lib/vyasa/pubsub.ex @@ -0,0 +1,48 @@ +defmodule Vyasa.PubSub do + @moduledoc """ + Publish Subscriber Pattern + """ + alias Phoenix.PubSub + + def subscribe(topic, opts \\ []) do + PubSub.subscribe(Vyasa.PubSub, topic, opts) + end + + def unsubscribe(topic) do + PubSub.unsubscribe(Vyasa.PubSub, topic) + end + + def publish({:ok, message}, event, topics) when is_list(topics) do + topics + |> Enum.map(fn topic -> publish(message, event, topic) end) + {:ok, message} + end + + def publish({:ok, message}, event, topic) do + PubSub.broadcast(Vyasa.PubSub, topic, {__MODULE__, event, message}) + {:ok, message} + end + + def publish(message, event, topics) when is_list(topics) do + topics |> Enum.map(fn topic -> publish(message, event, topic) end) + message + end + + def publish(%Vyasa.Medium.Voice{} = voice, event, sess_id) do + PubSub.broadcast(__MODULE__, "media:session:#{sess_id}", {__MODULE__, event, voice}) + voice + end + + def publish(message, event, topic) when not is_nil(topic) do + PubSub.broadcast(Vyasa.PubSub, topic, {__MODULE__, event, message}) + message + end + + def publish(message, _event, _topic) do + message + end + + def publish({:error, reason}, _event) do + {:error, reason} + end +end diff --git a/lib/vyasa/written.ex b/lib/vyasa/written.ex index 154a54f7..7f4007d0 100644 --- a/lib/vyasa/written.ex +++ b/lib/vyasa/written.ex @@ -6,7 +6,24 @@ defmodule Vyasa.Written do import Ecto.Query, warn: false alias Vyasa.Repo - alias Vyasa.Written.Text + alias Vyasa.Written.{Text, Source, Verse, Chapter, Translation} + + @doc """ + Guards for any uuidV4 + + ## Examples + + iex> is_uuid?("hanuman") + false + + """ + defguard is_uuid?(value) + when is_bitstring(value) and + byte_size(value) == 36 and + binary_part(value, 8, 1) == "-" and + binary_part(value, 13, 1) == "-" and + binary_part(value, 18, 1) == "-" and + binary_part(value, 23, 1) == "-" @doc """ Returns the list of texts. @@ -21,6 +38,50 @@ defmodule Vyasa.Written do Repo.all(Text) end + @doc """ + Returns the list of sources. + + ## Examples + + iex> list_sources() + [%Source{}, ...] + + """ + def list_sources do + Repo.all(Source) + |> Repo.preload([:chapters, :verses]) + end + + @doc """ + Returns the list of verses. + + ## Examples + + iex> list_verses() + [%Verse{}, ...] + + """ + def list_verses do + Repo.all(Verse) + |> Repo.preload([:chapter]) + end + + @doc """ + Returns the list of chapters. + + ## Examples + + iex> list_chapters() + [%Chapter{}, ...] + + """ + def list_chapters do + Repo.all(Chapter) + |> Repo.preload([:verses]) + end + + + @doc """ Gets a single text. @@ -37,6 +98,73 @@ defmodule Vyasa.Written do """ def get_text!(id), do: Repo.get!(Text, id) + @doc """ + Gets a single source by id. + + Raises `Ecto.NoResultsError` if the Text does not exist. + + ## Examples + + iex> get_source!() + %Source{} + + iex> get_text!() + ** (Ecto.NoResultsError) + + """ + def get_source!(id), do: Repo.get!(Source, id) + |> Repo.preload([:chapters, :verses]) + + def get_source_by_title(title) do + query = from src in Source, + where: src.title == ^title, + preload: [verses: [:translations], chapters: [:translations]] + + Repo.one(query) + end + + def get_chapters_by_src(src_title) do + (from c in Chapter, + inner_join: src in assoc(c, :source), + where: src.title == ^src_title, + inner_join: t in assoc(c, :translations), + on: t.source_id == src.id) + |> select_merge([c, src, t], %{ + c | translations: [t], source: src + }) + |> Repo.all() + end + + def get_chapter(no, source_title) do + (from c in Chapter, where: c.no == ^no, + inner_join: src in assoc(c, :source), + where: src.title == ^source_title) + |> Repo.one() + end + + def get_chapter(no, source_title, lang) do + %Source{id: id} = _src = get_source_by_title(source_title) + + target_lang = (from ts in Translation, + where: ts.lang == ^lang and ts.source_id == ^id) + + (from c in Chapter, + where: c.no == ^no and c.source_id == ^id, + preload: [verses: ^(from v in Verse, where: v.source_id == ^id, order_by: v.no, + preload: [translations: ^target_lang]), + translations: ^target_lang] + ) + |> Repo.one() + end + + def get_verses_in_chapter(no, source_id) do + query_verse = from v in Verse, + where: v.chapter_no == ^no and v.source_id == ^source_id, + preload: [:chapter] + + Repo.all(query_verse) + end + @doc """ Creates a text. @@ -93,12 +221,73 @@ defmodule Vyasa.Written do Returns an `%Ecto.Changeset{}` for tracking text changes. ## Examples - iex> change_text(text) %Ecto.Changeset{data: %Text{}} - """ def change_text(%Text{} = text, attrs \\ %{}) do Text.changeset(text, attrs) end -end + + @doc """ + Creates a source. + + ## Examples + + iex> create_source(%{field: value}) + {:ok, %Source{}} + + iex> create_source(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_source(attrs \\ %{}) do + %Source{} + |> Source.gen_changeset(attrs) + |> Repo.insert() + end + + @doc """ + Updates a source. + + ## Examples + + iex> update_source(source, %{field: new_value}) + {:ok, %Source{}} + + iex> update_source(source, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_source(%Source{} = source, attrs) do + source + |> Source.mutate_changeset(attrs) + |> Repo.update() + end + + @doc """ + Deletes a source. + + ## Examples + + iex> delete_source(source) + {:ok, %Source{}} + + iex> delete_source(source) + {:error, %Ecto.Changeset{}} + + """ + def delete_source(%Source{} = source) do + Repo.delete(source) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking source changes. + + ## Examples + iex> change_source(source) + %Ecto.Changeset{data: %Source{}} + """ + def change_source(%Source{} = source, attrs \\ %{}) do + Source.mutate_changeset(source, attrs) + end + end diff --git a/lib/vyasa/written/chapter.ex b/lib/vyasa/written/chapter.ex new file mode 100644 index 00000000..68b78437 --- /dev/null +++ b/lib/vyasa/written/chapter.ex @@ -0,0 +1,30 @@ +defmodule Vyasa.Written.Chapter do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Written.{Source, Verse, Translation, Chapter} + alias Vyasa.Medium.{Voice} + + @primary_key false + schema "chapters" do + field :no, :integer, primary_key: :true + field :key, :string + field :body, :string + field :title, :string + + belongs_to :chapter, Chapter, references: :no, foreign_key: :parent_no + belongs_to :source, Source, references: :id, foreign_key: :source_id, type: :binary_id, primary_key: :true + has_many :verses, Verse, references: :no, foreign_key: :chapter_no + has_many :translations, Translation, references: :no, foreign_key: :chapter_no + has_many :voices, Voice, references: :no, foreign_key: :chapter_no + end + + @doc false + def changeset(text, attrs) do + text + |> cast(attrs, [:body, :no, :title, :parent_no]) + |> cast_assoc(:verses) + |> cast_assoc(:translations) + |> cast_assoc(:voices) + end +end diff --git a/lib/vyasa/written/source.ex b/lib/vyasa/written/source.ex new file mode 100644 index 00000000..90d413eb --- /dev/null +++ b/lib/vyasa/written/source.ex @@ -0,0 +1,36 @@ +defmodule Vyasa.Written.Source do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Written.{Chapter, Verse, Translation} + alias Vyasa.Medium.{Event, Voice} + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "sources" do + field :title, :string + has_many :verses, Verse + has_many :translations, Translation + has_many :chapters, Chapter + has_many :voices, Voice + has_many :events, Event + + timestamps(type: :utc_datetime) + end + + @doc false + def gen_changeset(source, attrs) do + source + |> cast(attrs, [:id, :title]) + |> cast_assoc(:chapters) + |> cast_assoc(:verses) + |> validate_required([:title]) + end + + def mutate_changeset(source, attrs) do + source + |> cast(attrs, [:id, :title]) + |> cast_assoc(:chapters) + |> cast_assoc(:verses) + |> validate_required([:id, :title]) + end +end diff --git a/lib/vyasa/written/translation.ex b/lib/vyasa/written/translation.ex new file mode 100644 index 00000000..a2bfe6c9 --- /dev/null +++ b/lib/vyasa/written/translation.ex @@ -0,0 +1,94 @@ +defmodule Vyasa.Written.Translation do + use Ecto.Schema + import Ecto.Changeset + alias Vyasa.Written.{Verse, Chapter, Source} + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "translations" do + field :lang, :string + # target table + field :type, :string + #polymorphic shape of target + embeds_one :target, Target, on_replace: :delete do + # for chapter + field(:title, :string) + field(:translit_title, :string) + # for chapter/verse + field(:body, :string) + field(:body_meant, :string) + field(:body_translit, :string) + # for verse lexical fragments + field(:body_translit_meant, :string) + # media + end + + + belongs_to :verse, Verse, references: :id, type: Ecto.UUID + belongs_to :chapter, Chapter, references: :no, foreign_key: :chapter_no, type: :integer + belongs_to :source, Source, references: :id, type: Ecto.UUID + end + + # TODO: [low-priority]. + # Once the schema aspects are more or less standardised, there's value in creating a default + # changeset / changeset that gets fired by the parent entity such that we can pass in a single + # map and that will do the db seeding, as opposed to the 3-step seeding approach that is being + # done now. + + + @doc false + def changeset(translation, %{"type" => type} = attrs) do + # %{translation | type: type, verse_id: verse_id, source_id: s_id, chap_no: } # <== DON'T DO THIS. this will create extra associations to chap, but in this fn we only want verse-assocs + translation + |> cast(attrs, [:lang, :type, :verse_id, :chapter_no, :source_id]) + |> typed_target_switch(type) + |> validate_required([:lang]) + end + + def gen_changeset(translation, attrs, %Verse{id: verse_id, __meta__: %{source: type}, source_id: s_id}) do + # %{translation | type: type, verse_id: verse_id, source_id: s_id, chap_no: } # <== DON'T DO THIS. this will create extra associations to chap, but in this fn we only want verse-assocs + %{translation | type: type, verse_id: verse_id, source_id: s_id} + |> cast(attrs, [:lang]) + |> typed_target_switch(type) + |> validate_required([:lang]) + end + + def gen_changeset(translation, attrs, %Chapter{no: c_no, __meta__: %{source: type}, source_id: s_id}) do + %{translation | type: type, chapter_no: c_no, source_id: s_id} + |> cast(attrs, [:lang]) + |> typed_target_switch(type) + |> validate_required([:lang]) + |> validate_inclusion(:lang, ["en", "or", "sa", "hi", "mr", "ta", "ml", "ka"]) + |> foreign_key_constraint(:s_id) + end + + + def gen_changeset(translation, attrs, _parent) do + translation + |> cast(attrs, [:lang, :body]) + |> validate_inclusion(:type, ["verses", "chapters"]) + end + + def typed_target_switch(changeset, type) when type in ["chapters", "verses"] do + #changeset |> validate_inclusion(:type, ["chapters", "verses"]) + target_changeset = case type do + "chapters" -> + &chapter_changeset(&1, &2) + "verses" -> + &verse_changeset(&1, &2) + end + + cast_embed(changeset, :target, with: target_changeset) + end + + def typed_target_switch(changeset, _attrs), do: validate_required(changeset, [:type]) + + def chapter_changeset(structure, attrs) do + structure + |> cast(attrs, [:title, :translit_title, :body, :body_translit]) + end + + def verse_changeset(structure, attrs) do + structure + |> cast(attrs, [:body, :body_meant ,:body_translit, :body_translit_meant]) + end +end diff --git a/lib/vyasa/written/verse.ex b/lib/vyasa/written/verse.ex new file mode 100644 index 00000000..364eed45 --- /dev/null +++ b/lib/vyasa/written/verse.ex @@ -0,0 +1,24 @@ +defmodule Vyasa.Written.Verse do + use Ecto.Schema + import Ecto.Changeset + + alias Vyasa.Written.{Source, Chapter, Translation} + + @primary_key {:id, Ecto.UUID, autogenerate: true} + schema "verses" do + field :no, :integer + field :body, :string + + belongs_to :source, Source, type: Ecto.UUID + belongs_to :chapter, Chapter, type: :integer, references: :no, foreign_key: :chapter_no + has_many :translations, Translation + end + + @doc false + def changeset(text, attrs) do + text + |> cast(attrs, [:id, :body, :no, :source_id, :chapter_no]) + |> cast_assoc(:translations) + |> validate_required([:no, :body]) + end +end diff --git a/lib/vyasa_cli.ex b/lib/vyasa_cli.ex new file mode 100644 index 00000000..e5666e72 --- /dev/null +++ b/lib/vyasa_cli.ex @@ -0,0 +1,40 @@ +defmodule VyasaCLI do + def main(args \\ []) do + IO.inspect(args) + args + |> parse_args() + |> response() + |> IO.puts() + end + + + defp parse_args([command | ["--" <> _] = args]) do + {opts, _, _} = + args + |> OptionParser.parse(switches: [storage: :string]) + {command, opts} + end + + defp parse_args([command | [arg | _] = args]) do + {opts, _, _} = + args + |> OptionParser.parse(switches: [o: :string, path: :string]) + + {command, arg, opts} + end + defp response({"fetch", "shlokam.org/" <> path, opts}) do + Vyasa.Corpus.Engine.Shlokam.run(path, opts) + end + + defp response({"fetch", _, _}) do + "Unsupported domain + Try one of the following: + shlokam.org/ + " + end + + defp response(_) do + "Command doesnt belong to us " + end + +end diff --git a/lib/vyasa_web.ex b/lib/vyasa_web.ex index e8c53dd5..4bb4bdcb 100644 --- a/lib/vyasa_web.ex +++ b/lib/vyasa_web.ex @@ -27,6 +27,9 @@ defmodule VyasaWeb do import Plug.Conn import Phoenix.Controller import Phoenix.LiveView.Router + + # Import Admin Routes + import LiveAdmin.Router end end @@ -49,6 +52,23 @@ defmodule VyasaWeb do end end + def live_view(opts) do + quote do + @opts Keyword.merge( + [ + layout: {VyasaWeb.Layouts, :app}, + container: {:div, class: "relative h-screen flex overflow-hidden bg-white"} + ], + unquote(opts) + ) + + use Phoenix.LiveView, @opts + + unquote(html_helpers()) + + end + end + def live_view do quote do use Phoenix.LiveView, @@ -58,6 +78,8 @@ defmodule VyasaWeb do end end + + def live_component do quote do use Phoenix.LiveComponent @@ -86,7 +108,8 @@ defmodule VyasaWeb do # Core UI components and translation import VyasaWeb.CoreComponents import VyasaWeb.Gettext - + #String Formating for Display + import Utils.String, only: [to_title_case: 1] # Shortcut for generating JS commands alias Phoenix.LiveView.JS @@ -104,10 +127,16 @@ defmodule VyasaWeb do end end + @doc """ When used, dispatch to the appropriate controller/view/etc. """ + defmacro __using__({which, opts}) when is_atom(which) do + apply(__MODULE__, which, [opts]) + end + defmacro __using__(which) when is_atom(which) do apply(__MODULE__, which, []) end -end + + end diff --git a/lib/vyasa_web/admin.ex b/lib/vyasa_web/admin.ex new file mode 100644 index 00000000..5941f69a --- /dev/null +++ b/lib/vyasa_web/admin.ex @@ -0,0 +1,79 @@ +defmodule VyasaWeb.Admin.Written.Verse do + use LiveAdmin.Resource, schema: Vyasa.Written.Verse +end + +defmodule VyasaWeb.Admin.Medium.Event do + use LiveAdmin.Resource, schema: Vyasa.Medium.Event, + immutable_fields: [:source_id], + actions: [:silence, :next, :prev], + render_with: :render_field + + + + def render_field(record, field, session) do + VyasaWeb.Admin.Renderer.render_field(record, field, session) + end + + + def silence(%{voice: _v} = e, _sess) do + e = %{e | voice: nil} + {:ok, e} + end + + def next(%{voice: _v} = e, _sess) do + {:ok, Vyasa.Medium.get_event_by_order!(e, 1)} + end + + def prev(%{voice: _v} = e, _sess) do + {:ok, Vyasa.Medium.get_event_by_order!(e, -1)} + end +end + + +defmodule VyasaWeb.Admin.Renderer do + use Phoenix.Component + + def render_field(%{origin: o, voice: %Vyasa.Medium.Voice{} = v} = assigns, :phase, _session) do + assigns = %{assigns | origin: floor(o/1000), voice: Vyasa.Medium.Store.hydrate(v)} + ~H""" + <%= @phase %> + + """ + end + + def render_field(%{verse: %Vyasa.Written.Verse{} = v} = assigns, :verse_id, _session) do + assigns = %{assigns | verse: v |> Vyasa.Repo.preload(:translations)} + ~H""" +
+ <%= @verse.body %> +
+
+ <%= List.first(@verse.translations).target.body_translit %> +
+ """ + end + + + def render_field(record, field, _session) do + IO.inspect(field) + record + |> Map.fetch!(field) + |> case do + bool when is_boolean(bool) -> + if bool, do: "Yes", else: "No" + date = %Date{} -> + Calendar.strftime(date, "%a, %B %d %Y") + bin when is_binary(bin) -> bin + _ -> + record + |> Map.fetch!(field) + |> case do + val when is_binary(val) -> val + val -> inspect(val, pretty: true) + end + end + end + +end diff --git a/lib/vyasa_web/components/audio_player.ex b/lib/vyasa_web/components/audio_player.ex new file mode 100644 index 00000000..69e053cd --- /dev/null +++ b/lib/vyasa_web/components/audio_player.ex @@ -0,0 +1,38 @@ +defmodule VyasaWeb.AudioPlayer do + use VyasaWeb, :live_component + + def mount(_, _, socket) do + socket + |> assign(player_details: nil) + end + + @impl true + def render(assigns) do + ~H""" +
+ +
+ """ + end + + @impl true + def update(%{ + event: "media_bridge:update_audio_player" = event, + player_details: player_details, + elapsed: elapsed, + } = _assigns, socket) do + IO.inspect("handle update case in audio_player.ex with event = #{event}", label: "checkpoint") + + { + :ok, socket + |> assign(player_details: player_details) + |> assign(elapsed: elapsed) # TODO: refactor candidate for removal + } + end + + @impl true + def update(assigns, socket) do + IO.inspect(assigns, label: "what") + {:ok, socket |> assign(player_details: nil)} + end + end diff --git a/lib/vyasa_web/components/layouts.ex b/lib/vyasa_web/components/layouts.ex index 9611c444..1dce99eb 100644 --- a/lib/vyasa_web/components/layouts.ex +++ b/lib/vyasa_web/components/layouts.ex @@ -2,4 +2,35 @@ defmodule VyasaWeb.Layouts do use VyasaWeb, :html embed_templates "layouts/*" + + attr(:contents, :map, required: true) + + @doc """ + Function component into which meta tags can be inserted. + """ + def meta_tags(assigns) do + ~H""" + + """ + end + + defp parse_contents(contents) when is_map(contents) do + IO.puts("Contents map for meta contents:") + IO.inspect(contents) + + + contents + |> Enum.map(&define_name/1) + |> List.flatten() + |> Enum.into(%{}) + end + + defp parse_contents(_contents), do: %{} + + defp define_name({k, v}) when is_map(v) do + Enum.map(v, &define_name(&1, k)) + end + + defp define_name(data), do: define_name(data, "og") + defp define_name({k, v}, prefix), do: {"#{prefix}:#{k}", v} end diff --git a/lib/vyasa_web/components/layouts/app.html.heex b/lib/vyasa_web/components/layouts/app.html.heex index 038bc210..a72d90c8 100644 --- a/lib/vyasa_web/components/layouts/app.html.heex +++ b/lib/vyasa_web/components/layouts/app.html.heex @@ -1,4 +1,4 @@ -
+
-
+
<.flash_group flash={@flash} /> <%= @inner_content %> +
+ <%= live_render(@socket, VyasaWeb.MediaLive.MediaBridge, id: "MediaBridge", session: @session, sticky: true) %> +
diff --git a/lib/vyasa_web/components/layouts/root.html.heex b/lib/vyasa_web/components/layouts/root.html.heex index 56744bd3..998340a1 100644 --- a/lib/vyasa_web/components/layouts/root.html.heex +++ b/lib/vyasa_web/components/layouts/root.html.heex @@ -4,14 +4,17 @@ - <.live_title suffix=" · Phoenix Framework"> + <.live_title prefix="Vyasa | "> <%= assigns[:page_title] || "Vyasa" %> + + + <.meta_tags contents={assigns[:meta]} /> - <%= @inner_content %> + <%= @inner_content %> diff --git a/lib/vyasa_web/components/youtube_player.ex b/lib/vyasa_web/components/youtube_player.ex new file mode 100644 index 00000000..47c5429f --- /dev/null +++ b/lib/vyasa_web/components/youtube_player.ex @@ -0,0 +1,73 @@ +defmodule VyasaWeb.YouTubePlayer do + use VyasaWeb, :live_component + + # @impl true + # def update(%{event: "play_audio" = _event} = _params, socket) do + # {:ok, socket} + # end + + @impl true + def update(params, socket) do + IO.inspect(socket, label: "BREAKS HERE") + IO.inspect(params, label: "BREAKS HERE params") + {:ok, socket + |> assign(params) + } + end + + + @impl true + def render(assigns) do + ~H""" +
+
+
+ """ + end + + # @impl true + # def render(assigns) do + # ~H""" + #
+ #
+ #
+ #
+ # <.button id="seek100" phx-hook="TriggerYouTubeFunction" data-event-name="click" data-function-name={"seekTo"} data-target-time-stamp={100}> Button 1: 100s + # <.button id="seek1000" phx-hook="TriggerYouTubeFunction" data-event-name="click" data-function-name={"seekTo"} data-target-time-stamp={1000}> Button 2: 1000s + # <.button + # id="switchVideo" + # phx-hook="TriggerYouTubeFunction" + # data-function-name={"loadVideoById"} + # data-event-name={"click"} + # data-video-id={@video_id} + # data-target-time-stamp={0} + # > + # Load New Video @ Start + # + #
+ # <.button id="statsHover" phx-hook={"TriggerYouTubeFunction"} data-event-name={"mouseover"} data-function-name={"getAllStats"}> Hover to get stats + #
+ + #
+ # """ + # end + + @impl true + def handle_event("reportVideoStatus", payload, socket) do + IO.inspect(payload) + {:noreply, socket} + end + + end diff --git a/lib/vyasa_web/controllers/error_html.ex b/lib/vyasa_web/controllers/error_html.ex index 20d5b2b1..b34bc530 100644 --- a/lib/vyasa_web/controllers/error_html.ex +++ b/lib/vyasa_web/controllers/error_html.ex @@ -8,7 +8,8 @@ defmodule VyasaWeb.ErrorHTML do # * lib/vyasa_web/controllers/error_html/404.html.heex # * lib/vyasa_web/controllers/error_html/500.html.heex # - # embed_templates "error_html/*" + + embed_templates "error_html/*" # The default is to render a plain text page based on # the template name. For example, "404.html" becomes diff --git a/lib/vyasa_web/controllers/error_html/404.html.heex b/lib/vyasa_web/controllers/error_html/404.html.heex new file mode 100644 index 00000000..21ce5381 --- /dev/null +++ b/lib/vyasa_web/controllers/error_html/404.html.heex @@ -0,0 +1,339 @@ + + + + + + + 404 - <%= assigns[:reason] && @reason.message || "Not Found" %> + + + +
+ +
+
+
+
+ Error 404 - Not Found + <%= assigns[:reason] && @reason.message || "Slipped down the wrong rabbithole" %> +
+
+
+
+

+
+
+ +
+
+ + + diff --git a/lib/vyasa_web/controllers/fallback_controller.ex b/lib/vyasa_web/controllers/fallback_controller.ex new file mode 100644 index 00000000..30883c17 --- /dev/null +++ b/lib/vyasa_web/controllers/fallback_controller.ex @@ -0,0 +1,37 @@ +defmodule VyasaWeb.FallbackController do + @moduledoc """ + Translates controller action results into valid `Plug.Conn` responses. + + See `Phoenix.Controller.action_fallback/1` for more details. + """ + use VyasaWeb, :controller + + def call(conn, {:error, :unprocessable_entity}) do + conn + |> put_status(:unprocessable_entity) + |> put_view(VyasaWeb.ErrorHTML) + |> render(:"422") + end + + def call(conn, {:error, :not_found}) do + conn + |> put_status(:not_found) + |> put_view(VyasaWeb.ErrorHTML) + |> render(:"404") + end + + def call(conn, {:error, :unauthorized}) do + conn + |> put_status(:unauthorized) + |> put_view(VyasaWeb.ErrorHTML) + |> render(:"403") + end + + def call(conn, {:error, :null_image}) do + conn + |> put_status(:not_found) + |> put_resp_content_type("image/svg+xml") + # path to default logo svg + |> send_file(200, :code.priv_dir(:vyasa) |> Path.join("/static/images/logo.svg")) + end +end diff --git a/lib/vyasa_web/controllers/og_image_controller.ex b/lib/vyasa_web/controllers/og_image_controller.ex new file mode 100644 index 00000000..c845e6a2 --- /dev/null +++ b/lib/vyasa_web/controllers/og_image_controller.ex @@ -0,0 +1,47 @@ +defmodule VyasaWeb.OgImageController do + use VyasaWeb, :controller + alias VyasaWeb.SourceLive.ImageGenerator + alias Vyasa.Adapters.OgAdapter + + action_fallback VyasaWeb.FallbackController + + def show(conn, %{"filename" => filename}) do + case fetch_image_jit(filename) do + {:ok, target_url } -> + conn + |> put_resp_content_type("image/png") + |> send_file(200, target_url) + + err -> err + end + end + + + def fetch_image_jit(filename) do + target_url = System.tmp_dir() |> Path.join(filename) + if File.exists?(target_url) do + {:ok, target_url} + else + case get_og_content(filename) do + %{"src" => :gita, "text" => text} -> + ImageGenerator.generate_opengraph_image!(filename, text) + {:ok, target_url} + _ -> + {:error, :null_image} + end + end + end + + @doc """ + Fetches the actual content, by parsing the filename. + + For now, this shall only fetch gita-related content. Subsequently, this function may be + updated to support other texts and media formats. + """ + def get_og_content(filename) do + case OgAdapter.resolve_src_id(filename) do + {:ok, :gita} -> OgAdapter.get_content(:gita, filename) + _ -> {:error} + end + end +end diff --git a/lib/vyasa_web/controllers/page_html/home.html.heex b/lib/vyasa_web/controllers/page_html/home.html.heex index a83c618f..f6cfae01 100644 --- a/lib/vyasa_web/controllers/page_html/home.html.heex +++ b/lib/vyasa_web/controllers/page_html/home.html.heex @@ -346,7 +346,7 @@ hr {
<.link - navigate={~p"/gita"} + navigate={~p"/explore"} class="group relative rounded-2xl px-6 py-4 text-sm font-semibold leading-6 text-zinc-900 sm:py-6" > diff --git a/lib/vyasa_web/live/gita_live/index.ex b/lib/vyasa_web/live/gita_live/index.ex deleted file mode 100644 index 832a4149..00000000 --- a/lib/vyasa_web/live/gita_live/index.ex +++ /dev/null @@ -1,38 +0,0 @@ -defmodule VyasaWeb.GitaLive.Index do - use VyasaWeb, :live_view - alias Vyasa.Corpus.Gita - - @impl true - def mount(_params, _session, socket) do - {:ok, stream(socket, :chapters, Gita.chapters())} - end - - @impl true - def render(assigns) do - ~H""" - <.header> - <%= @page_title %> - - - <.table - id="texts" - rows={@streams.chapters} - row_click={fn {_id, text} -> JS.navigate(~p"/gita/#{text}") end} - > - <:col :let={{_id, text}} label="Title"><%= text.name_transliterated %> - <:col :let={{_id, text}} label="Description"><%= text.name_meaning %> - - """ - end - - @impl true - def handle_params(params, _url, socket) do - {:noreply, apply_action(socket, socket.assigns.live_action, params)} - end - - defp apply_action(socket, :index, _params) do - socket - |> assign(:page_title, "Chapters in Gita") - |> assign(:text, nil) - end -end diff --git a/lib/vyasa_web/live/gita_live/show.ex b/lib/vyasa_web/live/gita_live/show.ex deleted file mode 100644 index c33e0145..00000000 --- a/lib/vyasa_web/live/gita_live/show.ex +++ /dev/null @@ -1,34 +0,0 @@ -defmodule VyasaWeb.GitaLive.Show do - use VyasaWeb, :live_view - alias Vyasa.Corpus.Gita - - @impl true - def mount(_params, _session, socket) do - {:ok, socket} - end - - @impl true - def render(assigns) do - ~H""" - <.header> - <%= @chapter.name_transliterated %> - <:subtitle> <%= @chapter.chapter_summary %> - - - <.list :for={{_dom_id, text} <- @streams.verses}> - <:item title={"#{text.chapter_number}.#{text.verse_number}"}>

<%= text.text |> String.split("।।") |> List.first() %>

- <:item><%= text.transliteration %> - <:item><%= text.word_meanings %> - - - <.back navigate={~p"/gita"}>Back to Gita - """ - end - #<.link patch={~p"/gita/#{@chapter.id}"} phx-click={JS.push_focus()}> <.button>Annotate - @impl true - def handle_params(%{"id" => id}, _, socket) do - {:noreply, socket - |> assign(:chapter, Gita.chapters(id)) - |> stream(:verses, Gita.verses(id))} - end -end diff --git a/lib/vyasa_web/live/media_live/media_bridge.ex b/lib/vyasa_web/live/media_live/media_bridge.ex new file mode 100644 index 00000000..83f55943 --- /dev/null +++ b/lib/vyasa_web/live/media_live/media_bridge.ex @@ -0,0 +1,512 @@ +defmodule VyasaWeb.MediaLive.MediaBridge do + @moduledoc """ + Media Bridge intends to decouple the media players (audio/video...) from the context of what is being played. + + It will have the following responsibilities: + 1. stores a general playback state. This shall be agnostic to the players that rely on this playback state for synchronising their own playback states. + 2. It shall contain the common playback buttons because these buttons will be controlling all the supported players simultaneously. In so doing, playback state and actions are kept only in the media_bridge + 3. TODO: handle the sync between A/V players + """ + use VyasaWeb, :live_view + alias Vyasa.Medium + alias Vyasa.Medium.{Voice, Event, Playback} + + @default_player_config %{ + height: "300", + width: "400", + playerVars: %{ # see supported params here: https://developers.google.com/youtube/player_parameters#Parameters + autoplay: 1, + mute: 1, + start: 0, + controls: 0, + enablejsapi: 1, + iv_load_policy: 3, # hide video annotations + playsinline: 1, # ensures it doesn't full-screen on ios + } + } + + @impl true + def mount(_params, _sess, socket) do + encoded_config = Jason.encode!(@default_player_config) + socket = socket + |> assign(playback: nil) + |> assign(voice: nil) + |> assign(video: nil) + |> assign(video_player_config: encoded_config) + |> assign(should_show_vid: false) + |> assign(is_follow_mode: true) + |> sync_session() + + + {:ok, socket, layout: false} + end + + defp sync_session(%{assigns: %{session: %{"id" => id} = sess}} = socket) when is_binary(id) do + Vyasa.PubSub.subscribe("media:session:" <> id) + Vyasa.PubSub.publish(:init, :media_handshake, "written:session:" <> id) + + socket + |> push_event("initSession", sess |> Map.take(["id"])) + end + + defp sync_session(socket) do + socket + end + + defp play_media(socket, %Playback{elapsed: elapsed} = playback) do + IO.puts("play_media triggerred with elapsed = #{elapsed}") + socket + |> assign(playback: update_playback_on_play(playback)) + |> update_audio_player() + end + + # fallback + defp play_media(socket, _playback) do + socket + end + + defp update_playback_on_play(%Playback{elapsed: elapsed} = playback) do + now = DateTime.utc_now() + played_at = cond do + elapsed > 0 -> # resume case + DateTime.add(now, -elapsed, :second) + elapsed == 0 -> # fresh start case + now + true -> + now + end + + %{playback | playing?: true, played_at: played_at} + end + + defp pause_media(socket, %Playback{} = playback) do + socket + |> assign(playback: update_playback_on_pause(playback)) + |> update_audio_player() + # |> pause_audio() + end + + defp update_playback_on_pause( %Playback{ + played_at: played_at + } = playback) do + now = DateTime.utc_now() + # TODO elapse back into ms floor at yt + elapsed = DateTime.diff(now, played_at, :second) + %{playback | playing?: false, paused_at: now, elapsed: elapsed} + end + + + # internal action: updates the playback state on seek + defp update_playback_on_seek(socket, position_ms) do + %{playback: %Playback{ + playing?: playing?, + played_at: played_at, + } = playback, + } = socket.assigns + + + position_s = round(position_ms / 1000) + played_at = cond do + !playing? -> played_at + playing? -> DateTime.add(DateTime.utc_now, -position_s, :second) + end + + socket + |> assign(playback: %{playback | played_at: played_at, elapsed: position_s}) + end + + @impl true + def handle_event("toggle_should_show_vid", _, %{assigns: %{ should_show_vid: flag } = _assigns} = socket) do + {:noreply, socket |> assign(should_show_vid: !flag)} + end + + @impl true + def handle_event("toggle_is_follow_mode", _, %{assigns: %{ is_follow_mode: flag } = _assigns} = socket) do + { + :noreply, + socket + |> assign(is_follow_mode: !flag) + |> push_event("toggleFollowMode", %{}) + } + end + + @impl true + def handle_event("play_pause", _, socket) do + %{ + playback: %Playback { + playing?: playing?, + } = playback, + } = socket.assigns + + {:noreply, + cond do + playing? -> socket |> pause_media(playback) + !playing? -> socket |> play_media(playback) + end + } + end + + + @doc""" + Handles seekTime event originated from the ProgressBar + """ + @impl true + def handle_event("seekTime", %{"seekToMs" => position_ms, "originator" => "ProgressBar" = originator} = _payload, socket) do + IO.puts("[handleEvent] seekToMs #{position_ms} ORIGINATOR = #{originator}") + socket + |> handle_seek(position_ms, originator) + end + + # Fallback for seekTime, if no originator is present, shall be to treat MediaBridge as the originator + # and call handle_seek. + @impl true + def handle_event("seekTime", %{"seekToMs" => position_ms} = _payload, socket) do + IO.puts("[handleEvent] seekToMs #{position_ms}") + socket + |> handle_seek(position_ms, "MediaBridge") + end + + # when originator is the ProgressBar, then shall only consume and carry out internal actions only + # i.e. updating of the playback state kept in MediaBridge liveview. + defp handle_seek(socket, position_ms, "ProgressBar" = _originator) do + { + :noreply, + socket + |> update_playback_on_seek(position_ms) + } + end + + # when the seek is originated by the MediaBridge, then it shall carry out both internal & external actions + # internal: updating of the playback state kept in the MediaBridge liveview + # external: pubbing via the seekTime targetEvent + defp handle_seek(socket, position_ms, "MediaBridge" = originator) do + seek_time_payload = %{ + seekToMs: position_ms, + originator: originator + } + + IO.inspect("handle_seek originator: #{originator}, playback position ms: #{position_ms}", label: "checkpoint") + + { + :noreply, + socket + |> push_event("media_bridge:seekTime", seek_time_payload) + |> update_playback_on_seek(position_ms) + } + end + + + @impl true + @doc """ + On receiving a voice_ack, the written and player contexts are now synced. + A playback struct is created that represents this synced-state and the client-side hook is triggerred + to register the associated events timeline. + """ + def handle_info({_, :voice_ack, %Voice{video: video} = voice}, socket) do + %Voice{ + events: voice_events, + } = loaded_voice = voice |> Medium.load_events() + + { + :noreply, + socket + |> assign(voice: loaded_voice) + |> assign(video: video) + |> assign(playback: Playback.init_playback()) + |> push_event("media_bridge:registerEventsTimeline", %{voice_events: voice_events |> create_events_payload()}) + } + end + + def handle_info({_, :written_handshake, :init}, %{assigns: %{session: %{"id" => id}}} = socket) do + Vyasa.PubSub.publish(:init, :media_handshake, "written:session:" <> id) + {:noreply, socket} + end + + # Handles playback sync relative to a particular verse id. In this case, the playback state is expected + # to get updated to the start of the event corresponding to that particular verse. + @impl true + def handle_info({_, :playback_sync, %{verse_id: verse_id} = _inner_msg} = _msg, socket) do + %{voice: %{ events: events } = _voice} = socket.assigns + + IO.inspect("handle_info::playback_sync", label: "checkpoint") + + %Event{ + origin: target_ms + } = _target_event = events + |> get_target_event(verse_id) + + + socket + |> handle_seek(target_ms, "MediaBridge") + end + + def handle_info(msg, socket) do + IO.inspect(msg, label: "unexpected message received by media bridge") + {:noreply, socket} + end + + +defp create_events_payload([%Event{} | _] = events) do + events|> Enum.map(&(&1 |> Map.take([:origin, :duration, :phase, :fragments, :verse_id]))) +end + +defp get_target_event([%Event{} | _] = events, verse_id) do + events + |> Enum.find(fn e -> e.verse_id === verse_id end) + end + +defp update_audio_player(%{ + assigns: %{ + voice: %Voice{ + title: title, + file_path: file_path, + duration: duration, + } = _voice, + playback: %Playback{ + elapsed: elapsed, + playing?: playing?, + } = _playback + } = _assigns, + } = socket) do + + player_details = %{ + artist: "testArtist", + title: title, + isPlaying: playing?, + elapsed: elapsed, + filePath: file_path, + duration: duration, + } + + send_update( + self(), + VyasaWeb.AudioPlayer, + id: "audio-player", + player_details: player_details, + elapsed: elapsed, + event: "media_bridge:update_audio_player" + ) + + cmd = cond do + playing? -> + "play" + !playing? -> + "pause" + end + + seek_time_payload = %{ + seekToMs: elapsed * 1000, + originator: "MediaBridge" + } + + socket + |> push_event("media_bridge:play_pause", %{ + cmd: cmd, + originator: "MediaBridge", + player_details: player_details, + }) + |> push_event("media_bridge:seekTime", seek_time_payload) + +end + +# defp pause_audio(%{assigns: %{playback: %Playback{ +# elapsed: elapsed +# }= _playback} = _assigns} = socket) do + +# send_update(self(), VyasaWeb.AudioPlayer, +# id: "audio-player", +# event: "pause_audio", +# elapsed: elapsed +# ) + +# socket +# end + + # defp js_play_pause() do + # JS.push("play_pause") # server event + # # |> JS.dispatch("js:play_pause", to: "#audio-player") # client-side event, dispatches to DOM TODO: shift to the new audio player hook instead + # end + + + # TODO: add this when implementing tracks & playlists + defp js_prev() do + end + + # TODO: add this when implementing tracks & playlists + defp js_next() do + end + + attr :id, :string, required: true + attr :min, :integer, default: 0 + attr :max, :integer, default: 100 + attr :value, :integer + def progress_bar(assigns) do + assigns = assign_new(assigns, :value, fn -> assigns[:min] || 0 end) + IO.inspect(assigns, label: "progress hopefully we make some progress") + ~H""" +
+
+
+
+ """ + end + + attr :playback, Playback, required: false + def play_pause_button(assigns) do + ~H""" + + """ + end + + def next_button(assigns) do + ~H""" + + """ + end + + def prev_button(assigns) do + ~H""" + + """ + end + + # def volume_control(assigns) do + # ~H""" + + # """ + + # end + + def video_player(assigns) do + ~H""" +
+
+ <.live_component + module={VyasaWeb.YouTubePlayer} + id={"YouTubePlayer"} + video_id={@video.ext_uri} + player_config={@player_config} + /> +
+
+ """ + end + + def video_toggler(assigns) do + ~H""" +
+ <.icon :if={@should_show_vid} name="hero-video-camera-slash"/> + <.icon :if={!@should_show_vid} name="hero-video-camera"/> +
+ """ + end + + def follow_mode_toggler(assigns) do + ~H""" +
+ <.icon :if={@is_follow_mode} name="hero-rectangle-stack"/> + <.icon :if={!@is_follow_mode} name="hero-queue-list"/> +
+ """ + end + +end diff --git a/lib/vyasa_web/live/media_live/media_bridge.html.heex b/lib/vyasa_web/live/media_live/media_bridge.html.heex new file mode 100644 index 00000000..ef88f170 --- /dev/null +++ b/lib/vyasa_web/live/media_live/media_bridge.html.heex @@ -0,0 +1,94 @@ + + + +
+ +
+ <.live_component module={VyasaWeb.AudioPlayer} id={"audio-player"}/> +
+
+
+
+

+ <%= @voice.title %> +

+

+ <%= if @voice && Map.has_key?(@voice, "artist") do %> + <%= @voice.artist %> + <% else %> + artist + <% end %> +

+
+
+ <.progress_bar + id="player-progress" + max={(@voice && @voice.duration) || 100} + value={@playback && @playback.elapsed || 0} + /> +
+
+
+
+
+
+
+
+ + + + +
+ <.play_pause_button + playback={@playback} + /> +
+ + + + +
+ <.follow_mode_toggler is_follow_mode={@is_follow_mode} /> + <.video_toggler should_show_vid={@should_show_vid}/> +
+
+
+ + + +
+ <.video_player + video={@video} + heartbeat={@playback && @playback.elapsed} + should_show_vid={@should_show_vid} + player_config={@video_player_config} + /> +
+
diff --git a/lib/vyasa_web/live/source_live/chapter/generate_image.ex b/lib/vyasa_web/live/source_live/chapter/generate_image.ex new file mode 100644 index 00000000..144f8ad4 --- /dev/null +++ b/lib/vyasa_web/live/source_live/chapter/generate_image.ex @@ -0,0 +1,95 @@ +defmodule VyasaWeb.SourceLive.ImageGenerator do + @moduledoc """ + Contains logic for creating images, initially for opengraph purposes mainly. + """ + @fallback_text "Gita -- The Song Celestial" + @col_width 20 + alias VyasaWeb.SourceLive.ImageGenerator + alias Vix.Vips.Operation + + @doc """ + Returns a url string that can be used for the open-graph image meta-tag. + Currently stores images locally in a temp directory. + """ + def generate_opengraph_image!(filename, content \\ @fallback_text) do + url = + content + |> generate_svg() + |> write_opengraph_image(filename) + + url + end + + defp write_opengraph_image(svg, filename) do + target_url = System.tmp_dir() |> Path.join(filename) + IO.puts(">> [write_opengraph_image] target url: #{target_url}") + {image, _} = Operation.svgload_buffer!(svg) + + Image.write!(image, target_url) + target_url + end + + def generate_svg(content) do + svg_text_nodes = + content + |> ImageGenerator.wrap_text(@col_width) + |> Enum.with_index() + |> Enum.map(fn + {line, idx} -> get_svg_for_text(line, idx) + end) + |> Enum.join("") + + svg_precursor = """ + + + + + + + + + + """ + + svg_end = """ + + + """ + svg = svg_precursor <> svg_text_nodes <> svg_end + svg + end + + defp get_svg_for_text(text, offset) do + initial_y = 250 + vert_line_space = 90 + y_resolved = Integer.to_string(initial_y + vert_line_space * offset) + + """ + #{text} + """ + end + + @doc """ + Manually wraps a text to width of size @col_width. + """ + def wrap_text(text, col_length \\ @col_width) do + words = String.split(text, " ") + + Enum.reduce(words, [], fn word, acc_lines -> + IO.puts("[word:] #{word}") + curr_line = List.last(acc_lines, "") + new_combined_line = curr_line <> " " <> word + has_space_in_curr_line = String.length(new_combined_line) <= col_length + + if has_space_in_curr_line do + if acc_lines == [] do + [word] + else + List.replace_at(acc_lines, length(acc_lines) - 1, new_combined_line) + end + else + acc_lines ++ [word] + end + end) + end +end diff --git a/lib/vyasa_web/live/source_live/chapter/index.ex b/lib/vyasa_web/live/source_live/chapter/index.ex new file mode 100644 index 00000000..5c59a750 --- /dev/null +++ b/lib/vyasa_web/live/source_live/chapter/index.ex @@ -0,0 +1,153 @@ +defmodule VyasaWeb.SourceLive.Chapter.Index do + use VyasaWeb, :live_view + alias Vyasa.Written + alias Vyasa.Medium + + @default_lang "en" + @default_voice_lang "sa" + + @impl true + def mount(_params, _session, socket) do + {:ok, socket + |> stream_configure(:verses, dom_id: &("verse-#{&1.id}"))} + end + + + @impl true + def handle_params(params, _url, socket) do + IO.puts("chapter/index handle params") + + {:noreply, socket + |> sync_session() + |> apply_action(socket.assigns.live_action, params) + + #|> register_client_state() + } + end + + # defp register_client_state(%{assigns: %{voice_events: voice_events}} = socket) do + # desired_keys = [:origin, :duration, :phase, :fragments, :verse_id] + # events = Enum.map(voice_events, fn e -> Map.take(Map.from_struct(e), desired_keys) end) + + # socket + # |> push_event("registerEventsTimeline", + # %{voice_events: events}) + # end + + defp sync_session(%{assigns: %{session: %{"id" => sess_id}}} = socket) do + # written channel for reading and media channel for writing to media bridge and to player + Vyasa.PubSub.subscribe("written:session:" <> sess_id) + Vyasa.PubSub.publish(:init, :written_handshake, "media:session:" <> sess_id) + socket + end + + defp sync_session(socket), do: socket + + defp apply_action(socket, :index, %{"source_title" => source_title, "chap_no" => chap_no} = _params) do + + + # ==> replace this: + chap = %{verses: verses, translations: [ts | _]} = Written.get_chapter(chap_no, source_title, @default_lang) + + + + socket + |> stream(:verses, verses) + |> assign(:source_title, source_title) + |> assign(:chap, chap) + |> assign(:selected_transl, ts) + |> assign_meta() + end + + @impl true + @doc """ + Handles the action of clicking to seek by emitting the verse_id to the live player + via the pubsub system. + """ + def handle_event("clickVerseToSeek", + %{"verse_id" => verse_id} = _payload, + %{assigns: %{session: %{"id" => sess_id}}} = socket) do + IO.inspect("handle_event::clickVerseToSeek", label: "checkpoint") + Vyasa.PubSub.publish(%{verse_id: verse_id}, :playback_sync, "media:session:" <> sess_id) + {:noreply, socket} + end + + @doc """ + Upon rcv of :media_handshake, which indicates an intention to sync by the player, + returns a message containing %Voice{} info that can be used to generate a playback. + """ + @impl true + def handle_info({_, :media_handshake, :init}, + %{assigns: %{ + session: %{"id" => sess_id}, + chap: %Written.Chapter{no: c_no, source_id: src_id} + }} = socket) do + + chosen_voice = Medium.get_voice(src_id, c_no, @default_voice_lang) + Vyasa.PubSub.publish( + chosen_voice, + :voice_ack, + sess_id + ) + + {:noreply, socket} + end + + def handle_info(msg, socket) do IO.inspect(msg, label: "unexpected message in @chapter") + {:noreply, socket} + end + + defp assign_meta(socket) do + socket + |> assign(:page_title, "#{to_title_case(socket.assigns.source_title)} Chapter #{socket.assigns.chap.no} | #{socket.assigns.chap.title}") + |> assign(:meta, %{ + title: "#{to_title_case(socket.assigns.source_title)} Chapter #{socket.assigns.chap.no} | #{socket.assigns.chap.title}", + description: socket.assigns.chap.body, + type: "website", + image: url(~p"/images/the_vyasa_project_1.png"), + url: url(socket, ~p"/explore/#{socket.assigns.source_title}/#{socket.assigns.chap.no}"), + }) + end + + @doc """ + Renders a clickable verse display. + + ## Examples + <.verse_display> + <:item title="Title" navigate={~p"/myPath"}><%= @post.title %> + + """ + attr :id, :string, required: false + slot :item, required: true do + attr :title, :string + attr :verse_id, :string, required: false + attr :navigate, :any, required: false + end + def verse_display(assigns) do + ~H""" +
+
+
+
+ +
+
+ <%= render_slot(item) %> +
+
+
+
+ """ + end + + end diff --git a/lib/vyasa_web/live/source_live/chapter/index.html.heex b/lib/vyasa_web/live/source_live/chapter/index.html.heex new file mode 100644 index 00000000..805d95f5 --- /dev/null +++ b/lib/vyasa_web/live/source_live/chapter/index.html.heex @@ -0,0 +1,44 @@ +
+ <.header class="p-4 pb-0"> +
+ <%= @selected_transl.target.translit_title %> | <%= @chap.title%> +
+
+ Chapter <%= @chap.no%> - <%= @selected_transl.target.title %> +
+ + <:subtitle> +
+ <%= @selected_transl.target.body %> +
+ + + + <.verse_display id={dom_id} :for={{dom_id, %Written.Verse{} = verse} <- @streams.verses}> + <:item + title={"#{verse.chapter_no}.#{verse.no}"} + verse_id={verse.id} + > +

+ <%= verse.body |> String.split("।।") |> List.first() %> +

+ + <:item title={"Transliteration"}> +

+ <%= hd(verse.translations).target.body_translit %> +

+ + <:item title={"Transliteration Meaning"}> +

+ <%= hd(verse.translations).target.body_translit_meant %> +

+ + <:item title={"Translation"}> +

+ <%= hd(verse.translations).target.body %> +

+ + + + <.back navigate={~p"/explore/#{@source_title}"}>Back to <%= to_title_case(@source_title)%> Chapters +
diff --git a/lib/vyasa_web/live/source_live/chapter/show_verse.ex b/lib/vyasa_web/live/source_live/chapter/show_verse.ex new file mode 100644 index 00000000..79fb0713 --- /dev/null +++ b/lib/vyasa_web/live/source_live/chapter/show_verse.ex @@ -0,0 +1,64 @@ +defmodule VyasaWeb.SourceLive.Chapter.ShowVerse do + use VyasaWeb, :live_view + alias Vyasa.Written + + @impl true + def mount(_params, _session, socket) do + {:ok, socket} + end + + @impl true + def handle_params(%{"source_title" => source_title, "chap_no" => chap_no, "verse_no" => verse_no}, _, socket) do + verse = get_verse_via_url_params(String.to_integer(verse_no), chap_no, source_title) + + en_translation = verse.translations |> Enum.find(fn t -> t.lang == "en" end) + + {:noreply, + socket + |> assign(:source_title, source_title) + |> assign(:chap_no, chap_no) + |> assign(:verse_no, String.to_integer(verse_no)) + |> assign(:verse, verse) + |> assign(:en_translation, en_translation) + # |> assign_meta() + } + # |> assign(:chapter, Written.get_chapter(chap_no, source_id)) + # |> stream(:verses, Gita.verses(chap_no)) + # |> assign(:verse, Gita.verse(chap_no, verse_no)) + # |> assign_meta()} + end + + defp get_verse_via_url_params(verse_no, chap_no, src_title) do + chapter = Written.get_chapter(chap_no, src_title) + chapter.verses + |> Enum.find(fn verse -> verse.no == verse_no end) + |> Vyasa.Repo.preload([:chapter, :source, :translations]) + end + + # defp assign_meta(socket) do + # IO.inspect(socket.assigns.verse) + # %{:chapter_id => chapter, :verse_number => verse, :text => text} = socket.assigns.verse + + # assign(socket, :meta, %{ + # title: "Chapter #{chapter} | Verse #{verse}", + # description: text, + # type: "website", + # image: url(~p"/og/#{get_image_url(socket, chapter, verse)}"), + # url: url(socket, ~p"/gita/#{chapter}/#{verse}") + # }) + # end + + # defp get_image_url(socket, chapter_num, verse_num) do + # filename = OgAdapter.encode_filename(:gita, [chapter_num, verse_num]) + # target_url = OgAdapter.get_og_file_url(filename) + + # if File.exists?(target_url) do + # target_url + # else + # text = socket.assigns.verse.text + # ImageGenerator.generate_opengraph_image!(filename, text) + # end + + # filename + # end +end diff --git a/lib/vyasa_web/live/source_live/chapter/show_verse.html.heex b/lib/vyasa_web/live/source_live/chapter/show_verse.html.heex new file mode 100644 index 00000000..2665e291 --- /dev/null +++ b/lib/vyasa_web/live/source_live/chapter/show_verse.html.heex @@ -0,0 +1,77 @@ + + + +
+ <.header> + <:subtitle> + <%= @verse.chapter_no %>:<%= @verse.no %> + +

+ <%= @verse.body %> +

+ + +

+ <%= @en_translation.target.body_translit %> +

+ +

+ <%= @en_translation.target.body_translit_meant %> +

+ +

+ hi + <%= @en_translation.target.body %> +

+ + +
+
+
+ <.button + id="button-YouTubePlayer" + > + Toggle Player + +
+ It's me, tooltip content... +
+ + <.back navigate={~p"/explore/#{@source_title}/#{@chap_no}"}> + Back to <%= @source_title %> Chapter <%= @verse.chapter_no %> + + <.back navigate={~p"/explore/#{@source_title}"}>Back to <%= @source_title %> Chapters +
+ <.live_component + module={VyasaWeb.YouTubePlayer} + id={"YouTubePlayer"} + /> +
+
diff --git a/lib/vyasa_web/live/source_live/index.ex b/lib/vyasa_web/live/source_live/index.ex new file mode 100644 index 00000000..10c2c737 --- /dev/null +++ b/lib/vyasa_web/live/source_live/index.ex @@ -0,0 +1,31 @@ +defmodule VyasaWeb.SourceLive.Index do + use VyasaWeb, :live_view + alias Vyasa.Written + + @impl true + def mount(_params, _session, socket) do + {:ok, stream(socket, :sources, Written.list_sources())} + end + + + @impl true + def handle_params(params, _url, socket) do + {:noreply, apply_action(socket, socket.assigns.live_action, params)} + end + + defp apply_action(socket, :index, _params) do + socket + |> assign(:page_title, "Sources") + |> assign_meta() + end + + defp assign_meta(socket) do + assign(socket, :meta, %{ + title: "Sources to Explore", + description: "Explore the wealth of indic knowledge, distilled into words.", + type: "website", + image: url(~p"/images/the_vyasa_project_1.png"), + url: url(socket, ~p"/explore/"), + }) + end +end diff --git a/lib/vyasa_web/live/source_live/index.html.heex b/lib/vyasa_web/live/source_live/index.html.heex new file mode 100644 index 00000000..96a1559d --- /dev/null +++ b/lib/vyasa_web/live/source_live/index.html.heex @@ -0,0 +1,20 @@ + <.header> + +
+ <%= @page_title %> +
+ + + <.table + id="sources" + rows={@streams.sources} + row_click={fn {_id, source} -> JS.navigate(~p"/explore/#{source.title}/") end} + > + <:col :let={{_id, source}} label=""> +
+ <%= to_title_case(source.title) %> +
+ + + + Enum.count() < 10} class="block h-96"/> diff --git a/lib/vyasa_web/live/source_live/show.ex b/lib/vyasa_web/live/source_live/show.ex new file mode 100644 index 00000000..7b99e220 --- /dev/null +++ b/lib/vyasa_web/live/source_live/show.ex @@ -0,0 +1,84 @@ +defmodule VyasaWeb.SourceLive.Show do + use VyasaWeb, :live_view + alias Vyasa.Written + alias Vyasa.Written.{Chapter} + + @impl true + def mount(_params, _session, socket) do + socket = stream_configure(socket, :chapters, dom_id: &("Chapter-#{&1.no}")) + {:ok, socket} + end + + @impl true + def handle_params(%{"source_title" => source_title}, _, socket) do + # %Source{ + # id: id, + # # verses: verses, + # chapters: chapters, + # title: title + # } = Written.get_source_by_title(source_title) + + [%Chapter{} |_]= chapters = Written.get_chapters_by_src(source_title) + src = hd(chapters).source + title = src.title + id = src.id + + + { + :noreply, + socket + |> assign(:id, id) + |> assign(:title, title) + |> assign(:page_title, to_title_case(title)) + |> stream(:chapters, chapters |> Enum.sort_by(fn chap -> chap.no end)) + |> assign_meta() + } + + end + + defp assign_meta(socket) do + assign(socket, :meta, %{ + title: socket.assigns.title, + description: "Explore the #{socket.assigns.title}", + type: "website", + image: url(~p"/images/the_vyasa_project_1.png"), + url: url(socket, ~p"/explore/#{socket.assigns.title}") + }) + end + + @doc """ + Renders a clickable verse list. + + ## Examples + <.chapter_list> + <:item title="Title" navigate={~p"/explore/:id/:chapter_id"}> [<%= @chapter.no =>]<%= @chapter.title %> + + """ + slot :item, required: true do + attr :title, :string + attr :navigate, :any, required: false + end + + def chapter_list(assigns) do + ~H""" +
+
+
+
+ <.link + navigate={item[:navigate]} + class="text-sm font-semibold leading-6 text-zinc-900 hover:text-zinc-700" + > + <%= item.title %> + +
+
<%= render_slot(item) %>
+
+
+
+ """ + end +end diff --git a/lib/vyasa_web/live/source_live/show.html.heex b/lib/vyasa_web/live/source_live/show.html.heex new file mode 100644 index 00000000..058fd5a7 --- /dev/null +++ b/lib/vyasa_web/live/source_live/show.html.heex @@ -0,0 +1,33 @@ + +<.header > +
+ <%= to_title_case(@title)%> +
+ + + + +<.table +id="chapters" +rows={@streams.chapters} +row_click={fn {_id, chap} -> JS.navigate(~p"/explore/#{@title}/#{chap.no}") end} +> + <:col :let={{_id, chap}} label="Chapter"> +
+ <%= chap.no %>. <%= hd(chap.translations).target.translit_title %> +
+ + <:col :let={{_id, chap}} label="Description"> +
+ <%= chap.title %> +
+
+ <%= hd(chap.translations).target.title %> +
+ + + + +<.back navigate={~p"/explore/"}>Back to All Sources + + Enum.count() < 10} class="block h-96"/> diff --git a/lib/vyasa_web/live/source_live/show_verse.html.heex b/lib/vyasa_web/live/source_live/show_verse.html.heex new file mode 100644 index 00000000..4beef9ee --- /dev/null +++ b/lib/vyasa_web/live/source_live/show_verse.html.heex @@ -0,0 +1,68 @@ + + +
+ <.header> + <:subtitle><%= @verse.chapter_number %>:<%= @verse.verse_number %> +

<%= @verse.text |> String.split("।।") |> List.first() %>

+ +
+

<%= @verse.transliteration %>

+
+

<%= @verse.word_meanings %>

+
+ <.button + phx-hook="ShareQuoteButton" + id="ShareQuoteButton" + aria-describedby="tooltip" + data-verse={Jason.encode!(@verse)} + data-share-title={"Gita Chapter #{@verse.chapter_number} #{@verse.title}"} + > + Share + + <.button + id="button-YouTubePlayer" + > + Toggle Player + +
+ It's me, tooltip content... +
+ + <.back navigate={~p"/explore/#{@source_title}/@{chap_no}"}> + Back to Gita Chapter <%= @verse.chapter_number %> + + <.back navigate={~p"/explore/#{@source_title}"}>Back to <%= @source_title %> +
+ <.live_component + module={VyasaWeb.YouTubePlayer} + id={"YouTubePlayer"} + /> +
+
diff --git a/lib/vyasa_web/live/text_live/form_component.ex b/lib/vyasa_web/live/text_live/form_component.ex deleted file mode 100644 index 91253bf3..00000000 --- a/lib/vyasa_web/live/text_live/form_component.ex +++ /dev/null @@ -1,90 +0,0 @@ -defmodule VyasaWeb.TextLive.FormComponent do - use VyasaWeb, :live_component - - alias Vyasa.Written - - @impl true - def render(assigns) do - ~H""" -
- <.header> - <%= @title %> - <:subtitle>Use this form to manage text records in your database. - - - <.simple_form - for={@form} - id="text-form" - phx-target={@myself} - phx-change="validate" - phx-submit="save" - > - <.input field={@form[:title]} type="text" label="Title" /> - <:actions> - <.button phx-disable-with="Saving...">Save Text - - -
- """ - end - - @impl true - def update(%{text: text} = assigns, socket) do - changeset = Written.change_text(text) - - {:ok, - socket - |> assign(assigns) - |> assign_form(changeset)} - end - - @impl true - def handle_event("validate", %{"text" => text_params}, socket) do - changeset = - socket.assigns.text - |> Written.change_text(text_params) - |> Map.put(:action, :validate) - - {:noreply, assign_form(socket, changeset)} - end - - def handle_event("save", %{"text" => text_params}, socket) do - save_text(socket, socket.assigns.action, text_params) - end - - defp save_text(socket, :edit, text_params) do - case Written.update_text(socket.assigns.text, text_params) do - {:ok, text} -> - notify_parent({:saved, text}) - - {:noreply, - socket - |> put_flash(:info, "Text updated successfully") - |> push_patch(to: socket.assigns.patch)} - - {:error, %Ecto.Changeset{} = changeset} -> - {:noreply, assign_form(socket, changeset)} - end - end - - defp save_text(socket, :new, text_params) do - case Written.create_text(text_params) do - {:ok, text} -> - notify_parent({:saved, text}) - - {:noreply, - socket - |> put_flash(:info, "Text created successfully") - |> push_patch(to: socket.assigns.patch)} - - {:error, %Ecto.Changeset{} = changeset} -> - {:noreply, assign_form(socket, changeset)} - end - end - - defp assign_form(socket, %Ecto.Changeset{} = changeset) do - assign(socket, :form, to_form(changeset)) - end - - defp notify_parent(msg), do: send(self(), {__MODULE__, msg}) -end diff --git a/lib/vyasa_web/live/text_live/index.ex b/lib/vyasa_web/live/text_live/index.ex deleted file mode 100644 index 59c567e9..00000000 --- a/lib/vyasa_web/live/text_live/index.ex +++ /dev/null @@ -1,47 +0,0 @@ -defmodule VyasaWeb.TextLive.Index do - use VyasaWeb, :live_view - - alias Vyasa.Written - alias Vyasa.Written.Text - - @impl true - def mount(_params, _session, socket) do - {:ok, stream(socket, :texts, Written.list_texts())} - end - - @impl true - def handle_params(params, _url, socket) do - {:noreply, apply_action(socket, socket.assigns.live_action, params)} - end - - defp apply_action(socket, :edit, %{"id" => id}) do - socket - |> assign(:page_title, "Edit Text") - |> assign(:text, Written.get_text!(id)) - end - - defp apply_action(socket, :new, _params) do - socket - |> assign(:page_title, "New Text") - |> assign(:text, %Text{}) - end - - defp apply_action(socket, :index, _params) do - socket - |> assign(:page_title, "Listing Texts") - |> assign(:text, nil) - end - - @impl true - def handle_info({VyasaWeb.TextLive.FormComponent, {:saved, text}}, socket) do - {:noreply, stream_insert(socket, :texts, text)} - end - - @impl true - def handle_event("delete", %{"id" => id}, socket) do - text = Written.get_text!(id) - {:ok, _} = Written.delete_text(text) - - {:noreply, stream_delete(socket, :texts, text)} - end -end diff --git a/lib/vyasa_web/live/text_live/index.html.heex b/lib/vyasa_web/live/text_live/index.html.heex deleted file mode 100644 index 9f46256c..00000000 --- a/lib/vyasa_web/live/text_live/index.html.heex +++ /dev/null @@ -1,41 +0,0 @@ -<.header> - Listing Texts - <:actions> - <.link patch={~p"/texts/new"}> - <.button>New Text - - - - -<.table - id="texts" - rows={@streams.texts} - row_click={fn {_id, text} -> JS.navigate(~p"/texts/#{text}") end} -> - <:col :let={{_id, text}} label="Title"><%= text.title %> - <:action :let={{_id, text}}> -
- <.link navigate={~p"/texts/#{text}"}>Show -
- <.link patch={~p"/texts/#{text}/edit"}>Edit - - <:action :let={{id, text}}> - <.link - phx-click={JS.push("delete", value: %{id: text.id}) |> hide("##{id}")} - data-confirm="Are you sure?" - > - Delete - - - - -<.modal :if={@live_action in [:new, :edit]} id="text-modal" show on_cancel={JS.patch(~p"/texts")}> - <.live_component - module={VyasaWeb.TextLive.FormComponent} - id={@text.id || :new} - title={@page_title} - action={@live_action} - text={@text} - patch={~p"/texts"} - /> - diff --git a/lib/vyasa_web/live/text_live/show.ex b/lib/vyasa_web/live/text_live/show.ex deleted file mode 100644 index b94fe853..00000000 --- a/lib/vyasa_web/live/text_live/show.ex +++ /dev/null @@ -1,21 +0,0 @@ -defmodule VyasaWeb.TextLive.Show do - use VyasaWeb, :live_view - - alias Vyasa.Written - - @impl true - def mount(_params, _session, socket) do - {:ok, socket} - end - - @impl true - def handle_params(%{"id" => id}, _, socket) do - {:noreply, - socket - |> assign(:page_title, page_title(socket.assigns.live_action)) - |> assign(:text, Written.get_text!(id))} - end - - defp page_title(:show), do: "Show Text" - defp page_title(:edit), do: "Edit Text" -end diff --git a/lib/vyasa_web/live/text_live/show.html.heex b/lib/vyasa_web/live/text_live/show.html.heex deleted file mode 100644 index efecb714..00000000 --- a/lib/vyasa_web/live/text_live/show.html.heex +++ /dev/null @@ -1,26 +0,0 @@ -<.header> - Text <%= @text.id %> - <:subtitle>This is a text record from your database. - <:actions> - <.link patch={~p"/texts/#{@text}/show/edit"} phx-click={JS.push_focus()}> - <.button>Edit text - - - - -<.list> - <:item title="Title"><%= @text.title %> - - -<.back navigate={~p"/texts"}>Back to texts - -<.modal :if={@live_action == :edit} id="text-modal" show on_cancel={JS.patch(~p"/texts/#{@text}")}> - <.live_component - module={VyasaWeb.TextLive.FormComponent} - id={@text.id} - title={@page_title} - action={@live_action} - text={@text} - patch={~p"/texts/#{@text}"} - /> - diff --git a/lib/vyasa_web/router.ex b/lib/vyasa_web/router.ex index 34aec15b..12d6eead 100644 --- a/lib/vyasa_web/router.ex +++ b/lib/vyasa_web/router.ex @@ -1,8 +1,10 @@ defmodule VyasaWeb.Router do use VyasaWeb, :router + pipeline :browser do plug :accepts, ["html"] + plug CORSPlug, origin: ["https://www.youtube.com/iframe_api"] plug :fetch_session plug :fetch_live_flash plug :put_root_layout, html: {VyasaWeb.Layouts, :root} @@ -14,20 +16,31 @@ defmodule VyasaWeb.Router do plug :accepts, ["json"] end + + scope "/", VyasaWeb do pipe_through :browser - get "/", PageController, :home - live "/gita/", GitaLive.Index, :index - live "/gita/:id", GitaLive.Show, :show - live "/texts", TextLive.Index, :index - live "/texts/new", TextLive.Index, :new - live "/texts/:id/edit", TextLive.Index, :edit - live "/texts/:id", TextLive.Show, :show - live "/texts/:id/show/edit", TextLive.Show, :edit + get "/og/:filename", OgImageController, :show - end + + get "/", PageController, :home + + live_session :gen_anon_session, + on_mount: [{VyasaWeb.Session, :anon}] do + live "/explore/", SourceLive.Index, :index + live "/explore/:source_title/", SourceLive.Show, :show + live "/explore/:source_title/:chap_no", SourceLive.Chapter.Index, :index + live "/explore/:source_title/:chap_no/:verse_no", SourceLive.Chapter.ShowVerse, :show + end + + live_admin "/admin" do + admin_resource "/verses", VyasaWeb.Admin.Written.Verse + admin_resource "/events", VyasaWeb.Admin.Medium.Event + end + + end # Other scopes may use custom stacks. # scope "/api", VyasaWeb do @@ -46,6 +59,7 @@ defmodule VyasaWeb.Router do scope "/dev" do pipe_through :browser + live_dashboard "/dashboard", metrics: VyasaWeb.Telemetry forward "/mailbox", Plug.Swoosh.MailboxPreview end diff --git a/lib/vyasa_web/session.ex b/lib/vyasa_web/session.ex new file mode 100644 index 00000000..8e3a4908 --- /dev/null +++ b/lib/vyasa_web/session.ex @@ -0,0 +1,25 @@ +defmodule VyasaWeb.Session do + import Phoenix.Component, only: [assign: 2] + import Phoenix.LiveView, only: [get_connect_params: 1] + + @default_locale "en" + @timezone "UTC" + @timezone_offset 0 + + def on_mount(:anon, _params, _sessions, socket) do + # get_connect_params returns nil on the first (static rendering) mount call, and has the added connect params from the js LiveSocket creation on the subsequent (LiveSocket) call + {:cont, + socket + |> assign( + locale: get_connect_params(socket)["locale"] || @default_locale, + tz: %{timezone: get_connect_params(socket)["timezone"] || @timezone, + timezone_offset: get_connect_params(socket)["timezone_offset"] || @timezone_offset}, + session: get_connect_params(socket)["session"] |> mutate_session() + )} + end + + defp mutate_session(%{"id" => id} = sess) when is_binary(id), do: sess + defp mutate_session(%{"active" => true}), do: %{"id" => :crypto.strong_rand_bytes(18) |> :base64.encode()} + defp mutate_session(%{}), do: %{"id" => :crypto.strong_rand_bytes(18) |> :base64.encode()} + defp mutate_session(_), do: %{"active" => false} + end diff --git a/media/chalisa/hanuman_chalisa_gulshan_kumar.mp3 b/media/chalisa/hanuman_chalisa_gulshan_kumar.mp3 new file mode 100644 index 00000000..e450eb1a Binary files /dev/null and b/media/chalisa/hanuman_chalisa_gulshan_kumar.mp3 differ diff --git a/media/gita/1.mp3 b/media/gita/1.mp3 new file mode 100644 index 00000000..510b2817 Binary files /dev/null and b/media/gita/1.mp3 differ diff --git a/mix.exs b/mix.exs index 38f2f9c2..a6553f22 100644 --- a/mix.exs +++ b/mix.exs @@ -7,9 +7,10 @@ defmodule Vyasa.MixProject do version: "0.1.0-alpha.1", elixir: "~> 1.14", elixirc_paths: elixirc_paths(Mix.env()), - elixirc_options: [ + elixirc_options: [ warnings_as_errors: true ], + escript: escript(), start_permanent: Mix.env() == :prod, aliases: aliases(), deps: deps() @@ -26,6 +27,11 @@ defmodule Vyasa.MixProject do ] end + # Defining Scripting Env + defp escript do + [main_module: VyasaCLI] + end + # Specifies which paths to compile per environment. defp elixirc_paths(:test), do: ["lib", "test/support"] defp elixirc_paths(_), do: ["lib"] @@ -42,7 +48,7 @@ defmodule Vyasa.MixProject do {:phoenix_html, "~> 3.3"}, {:phoenix_live_reload, "~> 1.2", only: :dev}, {:phoenix_live_view, "~> 0.20.1"}, - {:floki, ">= 0.30.0", only: :test}, + {:floki, ">= 0.30.0"}, {:phoenix_live_dashboard, "~> 0.8.2"}, {:esbuild, "~> 0.8", runtime: Mix.env() == :dev}, {:tailwind, "~> 0.2.0", runtime: Mix.env() == :dev}, @@ -53,7 +59,16 @@ defmodule Vyasa.MixProject do {:gettext, "~> 0.20"}, {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.1.1"}, - {:plug_cowboy, "~> 2.5"} + {:plug_cowboy, "~> 2.5"}, + {:image, "~> 0.37"}, + {:vix, "~> 0.5"}, + {:kino, "~> 0.12.0"}, + {:cors_plug, "~> 3.0"}, + {:ex_aws, "~> 2.0"}, + {:ex_aws_s3, "~> 2.5"}, + {:live_admin, "~> 0.11.4"}, + {:req, "~> 0.4.0"}, + {:recase, "~> 0.5"} ] end @@ -71,7 +86,11 @@ defmodule Vyasa.MixProject do test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"], "assets.setup": ["tailwind.install --if-missing", "esbuild.install --if-missing"], "assets.build": ["tailwind default", "esbuild default"], - "assets.deploy": ["tailwind default --minify", "esbuild default --minify --loader:.ttf=file", "phx.digest"] + "assets.deploy": [ + "tailwind default --minify", + "esbuild default --minify --loader:.ttf=file", + "phx.digest" + ] ] end end diff --git a/mix.lock b/mix.lock index b9e7fd41..c8cf0782 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,8 @@ %{ "castore": {:hex, :castore, "1.0.4", "ff4d0fb2e6411c0479b1d965a814ea6d00e51eb2f58697446e9c41a97d940b28", [:mix], [], "hexpm", "9418c1b8144e11656f0be99943db4caf04612e3eaecefb5dae9a2a87565584f8"}, + "cc_precompiler": {:hex, :cc_precompiler, "0.1.9", "e8d3364f310da6ce6463c3dd20cf90ae7bbecbf6c5203b98bf9b48035592649b", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "9dcab3d0f3038621f1601f13539e7a9ee99843862e66ad62827b0c42b2f58a54"}, + "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, + "cors_plug": {:hex, :cors_plug, "3.0.3", "7c3ac52b39624bc616db2e937c282f3f623f25f8d550068b6710e58d04a0e330", [:mix], [{:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "3f2d759e8c272ed3835fab2ef11b46bddab8c1ab9528167bd463b6452edf830d"}, "cowboy": {:hex, :cowboy, "2.10.0", "ff9ffeff91dae4ae270dd975642997afe2a1179d94b1887863e43f681a203e26", [:make, :rebar3], [{:cowlib, "2.12.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "3afdccb7183cc6f143cb14d3cf51fa00e53db9ec80cdcd525482f5e99bc41d6b"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.12.1", "a9fa9a625f1d2025fe6b462cb865881329b5caff8f1854d1cbc9f9533f00e1e1", [:make, :rebar3], [], "hexpm", "163b73f6367a7341b33c794c4e88e7dbfe6498ac42dcd69ef44c5bc5507c8db0"}, @@ -8,18 +11,31 @@ "dns_cluster": {:hex, :dns_cluster, "0.1.1", "73b4b2c3ec692f8a64276c43f8c929733a9ab9ac48c34e4c0b3d9d1b5cd69155", [:mix], [], "hexpm", "03a3f6ff16dcbb53e219b99c7af6aab29eb6b88acf80164b4bd76ac18dc890b3"}, "ecto": {:hex, :ecto, "3.10.3", "eb2ae2eecd210b4eb8bece1217b297ad4ff824b4384c0e3fdd28aaf96edd6135", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "44bec74e2364d491d70f7e42cd0d690922659d329f6465e89feb8a34e8cd3433"}, "ecto_sql": {:hex, :ecto_sql, "3.10.2", "6b98b46534b5c2f8b8b5f03f126e75e2a73c64f3c071149d32987a5378b0fdbd", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.10.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 0.17.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "68c018debca57cb9235e3889affdaec7a10616a4e3a80c99fa1d01fdafaa9007"}, + "elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"}, "esbuild": {:hex, :esbuild, "0.8.1", "0cbf919f0eccb136d2eeef0df49c4acf55336de864e63594adcea3814f3edf41", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "25fc876a67c13cb0a776e7b5d7974851556baeda2085296c14ab48555ea7560f"}, + "ex_aws": {:hex, :ex_aws, "2.5.1", "7418917974ea42e9e84b25e88b9f3d21a861d5f953ad453e212f48e593d8d39f", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1b95431f70c446fa1871f0eb9b183043c5a625f75f9948a42d25f43ae2eff12b"}, + "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"}, "expo": {:hex, :expo, "0.4.1", "1c61d18a5df197dfda38861673d392e642649a9cef7694d2f97a587b2cfb319b", [:mix], [], "hexpm", "2ff7ba7a798c8c543c12550fa0e2cbc81b95d4974c65855d8d15ba7b37a1ce47"}, "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, "finch": {:hex, :finch, "0.16.0", "40733f02c89f94a112518071c0a91fe86069560f5dbdb39f9150042f44dcfb1a", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2.6 or ~> 1.0", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f660174c4d519e5fec629016054d60edd822cdfe2b7270836739ac2f97735ec5"}, "floki": {:hex, :floki, "0.35.2", "87f8c75ed8654b9635b311774308b2760b47e9a579dabf2e4d5f1e1d42c39e0b", [:mix], [], "hexpm", "6b05289a8e9eac475f644f09c2e4ba7e19201fd002b89c28c1293e7bd16773d9"}, + "fss": {:hex, :fss, "0.1.1", "9db2344dbbb5d555ce442ac7c2f82dd975b605b50d169314a20f08ed21e08642", [:mix], [], "hexpm", "78ad5955c7919c3764065b21144913df7515d52e228c09427a004afe9c1a16b0"}, "gettext": {:hex, :gettext, "0.23.1", "821e619a240e6000db2fc16a574ef68b3bd7fe0167ccc264a81563cc93e67a31", [:mix], [{:expo, "~> 0.4.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "19d744a36b809d810d610b57c27b934425859d158ebd56561bc41f7eeb8795db"}, + "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~> 6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~> 1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~> 1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.4.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~> 1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hpax": {:hex, :hpax, "0.1.2", "09a75600d9d8bbd064cdd741f21fc06fc1f4cf3d0fcc335e5aa19be1a7235c84", [:mix], [], "hexpm", "2c87843d5a23f5f16748ebe77969880e29809580efdaccd615cd3bed628a8c13"}, + "httpoison": {:hex, :httpoison, "2.2.1", "87b7ed6d95db0389f7df02779644171d7319d319178f6680438167d7b69b1f3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "51364e6d2f429d80e14fe4b5f8e39719cacd03eb3f9a9286e61e216feac2d2df"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "image": {:hex, :image, "0.39.0", "c003ce095ee32c40f194ca1a48ffa6d3e67192e567183e70dfd8b77bb7144119", [:mix], [{:bumblebee, "~> 0.3", [hex: :bumblebee, repo: "hexpm", optional: true]}, {:evision, "~> 0.1.33", [hex: :evision, repo: "hexpm", optional: true]}, {:exla, "~> 0.5", [hex: :exla, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: true]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}, {:nx, "~> 0.5", [hex: :nx, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.14 or ~> 3.2", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:plug, "~> 1.13", [hex: :plug, repo: "hexpm", optional: true]}, {:rustler, "> 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: false]}, {:vix, "~> 0.23", [hex: :vix, repo: "hexpm", optional: false]}], "hexpm", "d83de26e009a59cb8c53d2efecaacd7c9b990897dc3c7095a5b8847e73c8f968"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, + "kino": {:hex, :kino, "0.12.0", "dfebe415f31cf2f54d98600178c08fd017931d9dada6fb59b7716b5431bee4a1", [:mix], [{:fss, "~> 0.1.0", [hex: :fss, repo: "hexpm", optional: false]}, {:nx, "~> 0.1", [hex: :nx, repo: "hexpm", optional: true]}, {:table, "~> 0.1.2", [hex: :table, repo: "hexpm", optional: false]}], "hexpm", "6796a64ae978fc2e50e52cae022ae6a3d28b8e50589af158b8f3904e7f748377"}, + "live_admin": {:hex, :live_admin, "0.11.4", "d4e964ac99d215305d2d9f4af941a334d8e8edd19c53d589ebf3d53b7f079fea", [:mix], [{:ecto, "~> 3.10", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:gettext, "~> 0.22", [hex: :gettext, repo: "hexpm", optional: false]}, {:phoenix_ecto, "~> 4.4", [hex: :phoenix_ecto, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}], "hexpm", "c09ae7669b6b6e85bb03af19436c035aaf01e49f4ef7966d0e0c994c651252c9"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, "mint": {:hex, :mint, "1.5.1", "8db5239e56738552d85af398798c80648db0e90f343c8469f6c6d8898944fb6f", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "4a63e1e76a7c3956abd2c72f370a0d0aecddc3976dea5c27eccbecfa5e7d5b1e"}, "nimble_options": {:hex, :nimble_options, "1.0.2", "92098a74df0072ff37d0c12ace58574d26880e522c22801437151a159392270e", [:mix], [], "hexpm", "fd12a8db2021036ce12a309f26f564ec367373265b53e25403f0ee697380f1b8"}, "nimble_pool": {:hex, :nimble_pool, "1.0.0", "5eb82705d138f4dd4423f69ceb19ac667b3b492ae570c9f5c900bb3d2f50a847", [:mix], [], "hexpm", "80be3b882d2d351882256087078e1b1952a28bf98d0a287be87e4a24a710b67a"}, + "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.7.10", "02189140a61b2ce85bb633a9b6fd02dff705a5f1596869547aeb2b2b95edd729", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "cf784932e010fd736d656d7fead6a584a4498efefe5b8227e9f383bf15bb79d0"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.4.3", "86e9878f833829c3f66da03d75254c155d91d72a201eb56ae83482328dc7ca93", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d36c401206f3011fefd63d04e8ef626ec8791975d9d107f9a0817d426f61ac07"}, "phoenix_html": {:hex, :phoenix_html, "3.3.3", "380b8fb45912b5638d2f1d925a3771b4516b9a78587249cabe394e0a5d579dc9", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "923ebe6fec6e2e3b3e569dfbdc6560de932cd54b000ada0208b5f45024bdd76c"}, @@ -28,16 +44,24 @@ "phoenix_live_view": {:hex, :phoenix_live_view, "0.20.1", "92a37acf07afca67ac98bd326532ba8f44ad7d4bdf3e4361b03f7f02594e5ae9", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "be494fd1215052729298b0e97d5c2ce8e719c00854b82cd8cf15c1cd7fcf6294"}, "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"}, "phoenix_template": {:hex, :phoenix_template, "1.0.3", "32de561eefcefa951aead30a1f94f1b5f0379bc9e340bb5c667f65f1edfa4326", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "16f4b6588a4152f3cc057b9d0c0ba7e82ee23afa65543da535313ad8d25d8e2c"}, + "phoenix_view": {:hex, :phoenix_view, "2.0.3", "4d32c4817fce933693741deeb99ef1392619f942633dde834a5163124813aad3", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}], "hexpm", "cd34049af41be2c627df99cd4eaa71fc52a328c0c3d8e7d4aa28f880c30e7f64"}, "plug": {:hex, :plug, "1.15.1", "b7efd81c1a1286f13efb3f769de343236bd8b7d23b4a9f40d3002fc39ad8f74c", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "459497bd94d041d98d948054ec6c0b76feacd28eec38b219ca04c0de13c79d30"}, "plug_cowboy": {:hex, :plug_cowboy, "2.6.1", "9a3bbfceeb65eff5f39dab529e5cd79137ac36e913c02067dba3963a26efe9b2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "de36e1a21f451a18b790f37765db198075c25875c64834bcc82d90b309eb6613"}, "plug_crypto": {:hex, :plug_crypto, "2.0.0", "77515cc10af06645abbfb5e6ad7a3e9714f805ae118fa1a70205f80d2d70fe73", [:mix], [], "hexpm", "53695bae57cc4e54566d993eb01074e4d894b65a3766f1c43e2c61a1b0f45ea9"}, "postgrex": {:hex, :postgrex, "0.17.3", "c92cda8de2033a7585dae8c61b1d420a1a1322421df84da9a82a6764580c503d", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "946cf46935a4fdca7a81448be76ba3503cff082df42c6ec1ff16a4bdfbfb098d"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, + "recase": {:hex, :recase, "0.7.0", "3f2f719f0886c7a3b7fe469058ec539cb7bbe0023604ae3bce920e186305e5ae", [:mix], [], "hexpm", "36f5756a9f552f4a94b54a695870e32f4e72d5fad9c25e61bc4a3151c08a4e0c"}, + "req": {:hex, :req, "0.4.8", "2b754a3925ddbf4ad78c56f30208ced6aefe111a7ea07fb56c23dccc13eb87ae", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "7146e51d52593bb7f20d00b5308a5d7d17d663d6e85cd071452b613a8277100c"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, + "sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"}, "swoosh": {:hex, :swoosh, "1.14.0", "710e363e114dedb4080b737e0307f5410887ffc9a239f818231e5618b6b84e1b", [:mix], [{:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dccfc986ac99c18345ab3e1a8b934b2d817fd6d59a2494f0af78502184c71025"}, + "table": {:hex, :table, "0.1.2", "87ad1125f5b70c5dea0307aa633194083eb5182ec537efc94e96af08937e14a8", [:mix], [], "hexpm", "7e99bc7efef806315c7e65640724bf165c3061cdc5d854060f74468367065029"}, "tailwind": {:hex, :tailwind, "0.2.2", "9e27288b568ede1d88517e8c61259bc214a12d7eed271e102db4c93fcca9b2cd", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}], "hexpm", "ccfb5025179ea307f7f899d1bb3905cd0ac9f687ed77feebc8f67bdca78565c4"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"}, "telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, + "vix": {:hex, :vix, "0.26.0", "027f10b6969b759318be84bd0bd8c88af877445e4e41cf96a0460392cea5399c", [:make, :mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: false]}, {:cc_precompiler, "~> 0.1.4 or ~> 0.2", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.7.3 or ~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}], "hexpm", "71b0a79ae7f199cacfc8e679b0e4ba25ee47dc02e182c5b9097efb29fbe14efd"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, "websock_adapter": {:hex, :websock_adapter, "0.5.5", "9dfeee8269b27e958a65b3e235b7e447769f66b5b5925385f5a569269164a210", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "4b977ba4a01918acbf77045ff88de7f6972c2a009213c515a445c48f224ffce9"}, } diff --git a/priv/cacerts.pem b/priv/cacerts.pem new file mode 100644 index 00000000..8a59d0da --- /dev/null +++ b/priv/cacerts.pem @@ -0,0 +1,3534 @@ +## +## Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Tue Dec 12 01:57:24 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: 1970dd65858925d68498d2356aea6d03f764422523c5887deca8ce3ba9e1f845 +## + + +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----- + +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----- +MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw +EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN +MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp +c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq +t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C +jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg +vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF +ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR +AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend +jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO +peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR +7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi +GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 +OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov +L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm +5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr +44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf +Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m +Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp +mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk +vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf +KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br +NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj +viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ +-----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----- + +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----- + +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----- +MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM +BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE +AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky +MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz +IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 +IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ +wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa +by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 +zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f +YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 +oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l +EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 +hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 +EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 +jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY +iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt +ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI +WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 +JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx +K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ +Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC +4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo +2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz +lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem +OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 +vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== +-----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----- + +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----- +MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE +BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG +A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv +biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC +R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE +ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB +dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn +dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ +FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+ +5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG +x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX +2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL +OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3 +sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C +GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5 +WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E +FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt +rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+ +nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg +tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW +sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp +pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA +zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq +ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52 +7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I +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----- +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 +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----- +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 +-----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----- + +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----- + +BJCA Global Root CA1 +==================== +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBUMQswCQYDVQQG +EwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJK +Q0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAzMTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkG +A1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQD +DBRCSkNBIEdsb2JhbCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFm +CL3ZxRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZspDyRhyS +sTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O558dnJCNPYwpj9mZ9S1Wn +P3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgRat7GGPZHOiJBhyL8xIkoVNiMpTAK+BcW +yqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRj +eulumijWML3mG90Vr4TqnMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNn +MoH1V6XKV0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/pj+b +OT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZOz2nxbkRs1CTqjSSh +GL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXnjSXWgXSHRtQpdaJCbPdzied9v3pK +H9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMB +AAGjQjBAMB0GA1UdDgQWBBTF7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4G +A1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3KliawLwQ8hOnThJ +dMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u+2D2/VnGKhs/I0qUJDAnyIm8 +60Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuh +TaRjAv04l5U/BXCga99igUOLtFkNSoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW +4AB+dAb/OMRyHdOoP2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmp +GQrI+pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRzznfSxqxx +4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9eVzYH6Eze9mCUAyTF6ps +3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4S +SPfSKcOYKMryMguTjClPPGAyzQWWYezyr/6zcCwupvI= +-----END CERTIFICATE----- + +BJCA Global Root CA2 +==================== +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQswCQYDVQQGEwJD +TjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJVFkxHTAbBgNVBAMMFEJKQ0Eg +R2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgyMVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UE +BhMCQ04xJjAkBgNVBAoMHUJFSUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRC +SkNBIEdsb2JhbCBSb290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jl +SR9BIgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK++kpRuDCK +/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJKsVF/BvDRgh9Obl+rg/xI +1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8 +W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8g +UXOQwKhbYdDFUDn9hf7B43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- + +Sectigo Public Server Authentication Root E46 +============================================= +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQswCQYDVQQGEwJH +QjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBTZXJ2 +ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5 +WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0 +aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUr +gQQAIgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccCWvkEN/U0 +NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+6xnOQ6OjQjBAMB0GA1Ud +DgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAwNnADBkAjAn7qRaqCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RH +lAFWovgzJQxC36oCMB3q4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21U +SAGKcw== +-----END CERTIFICATE----- + +Sectigo Public Server Authentication Root R46 +============================================= +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBfMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1 +OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3 +DQEBAQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDaef0rty2k +1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnzSDBh+oF8HqcIStw+Kxwf +GExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xfiOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMP +FF1bFOdLvt30yNoDN9HWOaEhUTCDsG3XME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vu +ZDCQOc2TZYEhMbUjUDM3IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5Qaz +Yw6A3OASVYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgESJ/A +wSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu+Zd4KKTIRJLpfSYF +plhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt8uaZFURww3y8nDnAtOFr94MlI1fZ +EoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+LHaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW +6aWWrL3DkJiy4Pmi1KZHQ3xtzwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWI +IUkwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQYKlJfp/imTYp +E0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52gDY9hAaLMyZlbcp+nv4fjFg4 +exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZAFv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M +0ejf5lG5Nkc/kLnHvALcWxxPDkjBJYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI +84HxZmduTILA7rpXDhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9m +pFuiTdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5dHn5Hrwd +Vw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65LvKRRFHQV80MNNVIIb/b +E/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmm +J1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAYQqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- + +SSL.com TLS RSA Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQG +EwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBSU0Eg +Um9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloXDTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMC +VVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJv +b3QgQ0EgMjAyMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u +9nTPL3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OYt6/wNr/y +7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0insS657Lb85/bRi3pZ7Qcac +oOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3PnxEX4MN8/HdIGkWCVDi1FW24IBydm5M +R7d1VVm0U3TZlMZBrViKMWYPHqIbKUBOL9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDG +D6C1vBdOSHtRwvzpXGk3R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEW +TO6Af77wdr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS+YCk +8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYSd66UNHsef8JmAOSq +g+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoGAtUjHBPW6dvbxrB6y3snm/vg1UYk +7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2fgTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1Ud +EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsu +N+7jhHonLs0ZNbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsMQtfhWsSWTVTN +j8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvfR4iyrT7gJ4eLSYwfqUdYe5by +iB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJDPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjU +o3KUQyxi4U5cMj29TH0ZR6LDSeeWP4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqo +ENjwuSfr98t67wVylrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7Egkaib +MOlqbLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2wAgDHbICi +vRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3qr5nsLFR+jM4uElZI7xc7 +P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sjiMho6/4UIyYOf8kpIEFR3N+2ivEC+5BB0 +9+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- + +SSL.com TLS ECC Root CA 2022 +============================ +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQswCQYDVQQGEwJV +UzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxTU0wuY29tIFRMUyBFQ0MgUm9v +dCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMx +GDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3Qg +Q0EgMjAyMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWy +JGYmacCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFNSeR7T5v1 +5wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSJjy+j6CugFFR7 +81a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NWuCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGG +MAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w +7deedWo1dlJF4AIxAMeNb0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5 +Zn6g6g== +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA ECC TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4wLAYDVQQDDCVB +dG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQswCQYD +VQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3Mg +VHJ1c3RlZFJvb3QgUm9vdCBDQSBFQ0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYT +AkRFMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6K +DP/XtXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4AjJn8ZQS +b+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2KCXWfeBmmnoJsmo7jjPX +NtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMDaAAwZQIwW5kp85wxtolrbNa9d+F851F+ +uDrNozZffPc8dz7kUK2o59JZDCaOMDtuCCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGY +a3cpetskz2VAv9LcjBHo9H1/IISpQuQo +-----END CERTIFICATE----- + +Atos TrustedRoot Root CA RSA TLS 2021 +===================================== +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBMMS4wLAYDVQQD +DCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIxMQ0wCwYDVQQKDARBdG9zMQsw +CQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0 +b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNV +BAYTAkRFMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BB +l01Z4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYvYe+W/CBG +vevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZkmGbzSoXfduP9LVq6hdK +ZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDsGY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt +0xU6kGpn8bRrZtkh68rZYnxGEFzedUlnnkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVK +PNe0OwANwI8f4UDErmwh3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMY +sluMWuPD0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzygeBY +Br3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8ANSbhqRAvNncTFd+ +rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezBc6eUWsuSZIKmAMFwoW4sKeFYV+xa +fJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lIpw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/ +BAUwAwEB/zAdBgNVHQ4EFgQUdEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0G +CSqGSIb3DQEBDAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPso0UvFJ/1TCpl +Q3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJqM7F78PRreBrAwA0JrRUITWX +AdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuywxfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9G +slA9hGCZcbUztVdF5kJHdWoOsAgMrr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2Vkt +afcxBPTy+av5EzH4AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9q +TFsR0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuYo7Ey7Nmj +1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5dDTedk+SKlOxJTnbPP/l +PqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcEoji2jbDwN/zIIX8/syQbPYtuzE2wFg2W +HYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- + +TrustAsia Global Root CA G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIFpTCCA42gAwIBAgIUZPYOZXdhaqs7tOqFhLuxibhxkw8wDQYJKoZIhvcNAQEMBQAwWjELMAkG +A1UEBhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMM +G1RydXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHMzAeFw0yMTA1MjAwMjEwMTlaFw00NjA1MTkwMjEw +MTlaMFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMu +MSQwIgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzMwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQDAMYJhkuSUGwoqZdC+BqmHO1ES6nBBruL7dOoKjbmzTNyPtxNST1QY4Sxz +lZHFZjtqz6xjbYdT8PfxObegQ2OwxANdV6nnRM7EoYNl9lA+sX4WuDqKAtCWHwDNBSHvBm3dIZwZ +Q0WhxeiAysKtQGIXBsaqvPPW5vxQfmZCHzyLpnl5hkA1nyDvP+uLRx+PjsXUjrYsyUQE49RDdT/V +P68czH5GX6zfZBCK70bwkPAPLfSIC7Epqq+FqklYqL9joDiR5rPmd2jE+SoZhLsO4fWvieylL1Ag +dB4SQXMeJNnKziyhWTXAyB1GJ2Faj/lN03J5Zh6fFZAhLf3ti1ZwA0pJPn9pMRJpxx5cynoTi+jm +9WAPzJMshH/x/Gr8m0ed262IPfN2dTPXS6TIi/n1Q1hPy8gDVI+lhXgEGvNz8teHHUGf59gXzhqc +D0r83ERoVGjiQTz+LISGNzzNPy+i2+f3VANfWdP3kXjHi3dqFuVJhZBFcnAvkV34PmVACxmZySYg +WmjBNb9Pp1Hx2BErW+Canig7CjoKH8GB5S7wprlppYiU5msTf9FkPz2ccEblooV7WIQn3MSAPmea +mseaMQ4w7OYXQJXZRe0Blqq/DPNL0WP3E1jAuPP6Z92bfW1K/zJMtSU7/xxnD4UiWQWRkUF3gdCF +TIcQcf+eQxuulXUtgQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEDk5PIj +7zjKsK5Xf/IhMBY027ySMB0GA1UdDgQWBBRA5OTyI+84yrCuV3/yITAWNNu8kjAOBgNVHQ8BAf8E +BAMCAQYwDQYJKoZIhvcNAQEMBQADggIBACY7UeFNOPMyGLS0XuFlXsSUT9SnYaP4wM8zAQLpw6o1 +D/GUE3d3NZ4tVlFEbuHGLige/9rsR82XRBf34EzC4Xx8MnpmyFq2XFNFV1pF1AWZLy4jVe5jaN/T +G3inEpQGAHUNcoTpLrxaatXeL1nHo+zSh2bbt1S1JKv0Q3jbSwTEb93mPmY+KfJLaHEih6D4sTNj +duMNhXJEIlU/HHzp/LgV6FL6qj6jITk1dImmasI5+njPtqzn59ZW/yOSLlALqbUHM/Q4X6RJpstl +cHboCoWASzY9M/eVVHUl2qzEc4Jl6VL1XP04lQJqaTDFHApXB64ipCz5xUG3uOyfT0gA+QEEVcys ++TIxxHWVBqB/0Y0n3bOppHKH/lmLmnp0Ft0WpWIp6zqW3IunaFnT63eROfjXy9mPX1onAX1daBli +2MjN9LdyR75bl87yraKZk62Uy5P2EgmVtqvXO9A/EcswFi55gORngS1d7XB4tmBZrOFdRWOPyN9y +aFvqHbgB8X7754qz41SgOAngPN5C8sLtLpvzHzW2NtjjgKGLzZlkD8Kqq7HK9W+eQ42EVJmzbsAS +ZthwEPEGNTNDqJwuuhQxzhB/HIbjj9LV+Hfsm6vxL2PZQl/gZ4FkkfGXL/xuJvYz+NO1+MRiqzFR +JQJ6+N1rZdVtTTDIZbpoFGWsJwt0ivKH +-----END CERTIFICATE----- + +TrustAsia Global Root CA G4 +=========================== +-----BEGIN CERTIFICATE----- +MIICVTCCAdygAwIBAgIUTyNkuI6XY57GU4HBdk7LKnQV1tcwCgYIKoZIzj0EAwMwWjELMAkGA1UE +BhMCQ04xJTAjBgNVBAoMHFRydXN0QXNpYSBUZWNobm9sb2dpZXMsIEluYy4xJDAiBgNVBAMMG1Ry +dXN0QXNpYSBHbG9iYWwgUm9vdCBDQSBHNDAeFw0yMTA1MjAwMjEwMjJaFw00NjA1MTkwMjEwMjJa +MFoxCzAJBgNVBAYTAkNOMSUwIwYDVQQKDBxUcnVzdEFzaWEgVGVjaG5vbG9naWVzLCBJbmMuMSQw +IgYDVQQDDBtUcnVzdEFzaWEgR2xvYmFsIFJvb3QgQ0EgRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AATxs8045CVD5d4ZCbuBeaIVXxVjAd7Cq92zphtnS4CDr5nLrBfbK5bKfFJV4hrhPVbwLxYI+hW8 +m7tH5j/uqOFMjPXTNvk4XatwmkcN4oFBButJ+bAp3TPsUKV/eSm4IJijYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHwYDVR0jBBgwFoAUpbtKl86zK3+kMd6Xg1mDpm9xy94wHQYDVR0OBBYEFKW7SpfOsyt/ +pDHel4NZg6ZvccveMA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjBe8usGzEkxn0AA +bbd+NvBNEU/zy4k6LHiRUKNbwMp1JvK/kF0LgoxgKJ/GcJpo5PECMFxYDlZ2z1jD1xCMuo6u47xk +dUfFVZDj/bpV6wfEU6s3qe4hsiFbYI89MvHVI5TWWA== +-----END CERTIFICATE----- + +CommScope Public Trust ECC Root-01 +================================== +-----BEGIN CERTIFICATE----- +MIICHTCCAaOgAwIBAgIUQ3CCd89NXTTxyq4yLzf39H91oJ4wCgYIKoZIzj0EAwMwTjELMAkGA1UE +BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz +dCBFQ0MgUm9vdC0wMTAeFw0yMTA0MjgxNzM1NDNaFw00NjA0MjgxNzM1NDJaME4xCzAJBgNVBAYT +AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg +RUNDIFJvb3QtMDEwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARLNumuV16ocNfQj3Rid8NeeqrltqLx +eP0CflfdkXmcbLlSiFS8LwS+uM32ENEp7LXQoMPwiXAZu1FlxUOcw5tjnSCDPgYLpkJEhRGnSjot +6dZoL0hOUysHP029uax3OVejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBSOB2LAUN3GGQYARnQE9/OufXVNMDAKBggqhkjOPQQDAwNoADBlAjEAnDPfQeMjqEI2 +Jpc1XHvr20v4qotzVRVcrHgpD7oh2MSg2NED3W3ROT3Ek2DS43KyAjB8xX6I01D1HiXo+k515liW +pDVfG2XqYZpwI7UNo5uSUm9poIyNStDuiw7LR47QjRE= +-----END CERTIFICATE----- + +CommScope Public Trust ECC Root-02 +================================== +-----BEGIN CERTIFICATE----- +MIICHDCCAaOgAwIBAgIUKP2ZYEFHpgE6yhR7H+/5aAiDXX0wCgYIKoZIzj0EAwMwTjELMAkGA1UE +BhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBUcnVz +dCBFQ0MgUm9vdC0wMjAeFw0yMTA0MjgxNzQ0NTRaFw00NjA0MjgxNzQ0NTNaME4xCzAJBgNVBAYT +AlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1c3Qg +RUNDIFJvb3QtMDIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR4MIHoYx7l63FRD/cHB8o5mXxO1Q/M +MDALj2aTPs+9xYa9+bG3tD60B8jzljHz7aRP+KNOjSkVWLjVb3/ubCK1sK9IRQq9qEmUv4RDsNuE +SgMjGWdqb8FuvAY5N9GIIvejQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBTmGHX/72DehKT1RsfeSlXjMjZ59TAKBggqhkjOPQQDAwNnADBkAjAmc0l6tqvmSfR9 +Uj/UQQSugEODZXW5hYA4O9Zv5JOGq4/nich/m35rChJVYaoR4HkCMHfoMXGsPHED1oQmHhS48zs7 +3u1Z/GtMMH9ZzkXpc2AVmkzw5l4lIhVtwodZ0LKOag== +-----END CERTIFICATE----- + +CommScope Public Trust RSA Root-01 +================================== +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUPgNJgXUWdDGOTKvVxZAplsU5EN0wDQYJKoZIhvcNAQELBQAwTjELMAkG +A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU +cnVzdCBSU0EgUm9vdC0wMTAeFw0yMTA0MjgxNjQ1NTRaFw00NjA0MjgxNjQ1NTNaME4xCzAJBgNV +BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 +c3QgUlNBIFJvb3QtMDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwSGWjDR1C45Ft +nYSkYZYSwu3D2iM0GXb26v1VWvZVAVMP8syMl0+5UMuzAURWlv2bKOx7dAvnQmtVzslhsuitQDy6 +uUEKBU8bJoWPQ7VAtYXR1HHcg0Hz9kXHgKKEUJdGzqAMxGBWBB0HW0alDrJLpA6lfO741GIDuZNq +ihS4cPgugkY4Iw50x2tBt9Apo52AsH53k2NC+zSDO3OjWiE260f6GBfZumbCk6SP/F2krfxQapWs +vCQz0b2If4b19bJzKo98rwjyGpg/qYFlP8GMicWWMJoKz/TUyDTtnS+8jTiGU+6Xn6myY5QXjQ/c +Zip8UlF1y5mO6D1cv547KI2DAg+pn3LiLCuz3GaXAEDQpFSOm117RTYm1nJD68/A6g3czhLmfTif +BSeolz7pUcZsBSjBAg/pGG3svZwG1KdJ9FQFa2ww8esD1eo9anbCyxooSU1/ZOD6K9pzg4H/kQO9 +lLvkuI6cMmPNn7togbGEW682v3fuHX/3SZtS7NJ3Wn2RnU3COS3kuoL4b/JOHg9O5j9ZpSPcPYeo +KFgo0fEbNttPxP/hjFtyjMcmAyejOQoBqsCyMWCDIqFPEgkBEa801M/XrmLTBQe0MXXgDW1XT2mH ++VepuhX2yFJtocucH+X8eKg1mp9BFM6ltM6UCBwJrVbl2rZJmkrqYxhTnCwuwwIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUN12mmnQywsL5x6YVEFm4 +5P3luG0wDQYJKoZIhvcNAQELBQADggIBAK+nz97/4L1CjU3lIpbfaOp9TSp90K09FlxD533Ahuh6 +NWPxzIHIxgvoLlI1pKZJkGNRrDSsBTtXAOnTYtPZKdVUvhwQkZyybf5Z/Xn36lbQnmhUQo8mUuJM +3y+Xpi/SB5io82BdS5pYV4jvguX6r2yBS5KPQJqTRlnLX3gWsWc+QgvfKNmwrZggvkN80V4aCRck +jXtdlemrwWCrWxhkgPut4AZ9HcpZuPN4KWfGVh2vtrV0KnahP/t1MJ+UXjulYPPLXAziDslg+Mkf +Foom3ecnf+slpoq9uC02EJqxWE2aaE9gVOX2RhOOiKy8IUISrcZKiX2bwdgt6ZYD9KJ0DLwAHb/W +NyVntHKLr4W96ioDj8z7PEQkguIBpQtZtjSNMgsSDesnwv1B10A8ckYpwIzqug/xBpMu95yo9GA+ +o/E4Xo4TwbM6l4c/ksp4qRyv0LAbJh6+cOx69TOY6lz/KwsETkPdY34Op054A5U+1C0wlREQKC6/ +oAI+/15Z0wUOlV9TRe9rh9VIzRamloPh37MG88EU26fsHItdkJANclHnYfkUyq+Dj7+vsQpZXdxc +1+SWrVtgHdqul7I52Qb1dgAT+GhMIbA1xNxVssnBQVocicCMb3SgazNNtQEo/a2tiRc7ppqEvOuM +6sRxJKi6KfkIsidWNTJf6jn7MZrVGczw +-----END CERTIFICATE----- + +CommScope Public Trust RSA Root-02 +================================== +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIUVBa/O345lXGN0aoApYYNK496BU4wDQYJKoZIhvcNAQELBQAwTjELMAkG +A1UEBhMCVVMxEjAQBgNVBAoMCUNvbW1TY29wZTErMCkGA1UEAwwiQ29tbVNjb3BlIFB1YmxpYyBU +cnVzdCBSU0EgUm9vdC0wMjAeFw0yMTA0MjgxNzE2NDNaFw00NjA0MjgxNzE2NDJaME4xCzAJBgNV +BAYTAlVTMRIwEAYDVQQKDAlDb21tU2NvcGUxKzApBgNVBAMMIkNvbW1TY29wZSBQdWJsaWMgVHJ1 +c3QgUlNBIFJvb3QtMDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDh+g77aAASyE3V +rCLENQE7xVTlWXZjpX/rwcRqmL0yjReA61260WI9JSMZNRTpf4mnG2I81lDnNJUDMrG0kyI9p+Kx +7eZ7Ti6Hmw0zdQreqjXnfuU2mKKuJZ6VszKWpCtYHu8//mI0SFHRtI1CrWDaSWqVcN3SAOLMV2MC +e5bdSZdbkk6V0/nLKR8YSvgBKtJjCW4k6YnS5cciTNxzhkcAqg2Ijq6FfUrpuzNPDlJwnZXjfG2W +Wy09X6GDRl224yW4fKcZgBzqZUPckXk2LHR88mcGyYnJ27/aaL8j7dxrrSiDeS/sOKUNNwFnJ5rp +M9kzXzehxfCrPfp4sOcsn/Y+n2Dg70jpkEUeBVF4GiwSLFworA2iI540jwXmojPOEXcT1A6kHkIf +hs1w/tkuFT0du7jyU1fbzMZ0KZwYszZ1OC4PVKH4kh+Jlk+71O6d6Ts2QrUKOyrUZHk2EOH5kQMr +eyBUzQ0ZGshBMjTRsJnhkB4BQDa1t/qp5Xd1pCKBXbCL5CcSD1SIxtuFdOa3wNemKfrb3vOTlycE +VS8KbzfFPROvCgCpLIscgSjX74Yxqa7ybrjKaixUR9gqiC6vwQcQeKwRoi9C8DfF8rhW3Q5iLc4t +Vn5V8qdE9isy9COoR+jUKgF4z2rDN6ieZdIs5fq6M8EGRPbmz6UNp2YINIos8wIDAQABo0IwQDAP +BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUR9DnsSL/nSz12Vdgs7Gx +cJXvYXowDQYJKoZIhvcNAQELBQADggIBAIZpsU0v6Z9PIpNojuQhmaPORVMbc0RTAIFhzTHjCLqB +KCh6krm2qMhDnscTJk3C2OVVnJJdUNjCK9v+5qiXz1I6JMNlZFxHMaNlNRPDk7n3+VGXu6TwYofF +1gbTl4MgqX67tiHCpQ2EAOHyJxCDut0DgdXdaMNmEMjRdrSzbymeAPnCKfWxkxlSaRosTKCL4BWa +MS/TiJVZbuXEs1DIFAhKm4sTg7GkcrI7djNB3NyqpgdvHSQSn8h2vS/ZjvQs7rfSOBAkNlEv41xd +gSGn2rtO/+YHqP65DSdsu3BaVXoT6fEqSWnHX4dXTEN5bTpl6TBcQe7rd6VzEojov32u5cSoHw2O +HG1QAk8mGEPej1WFsQs3BWDJVTkSBKEqz3EWnzZRSb9wO55nnPt7eck5HHisd5FUmrh1CoFSl+Nm +YWvtPjgelmFV4ZFUjO2MJB+ByRCac5krFk5yAD9UG/iNuovnFNa2RU9g7Jauwy8CTl2dlklyALKr +dVwPaFsdZcJfMw8eD/A7hvWwTruc9+olBdytoptLFwG+Qt81IR2tq670v64fG9PiO/yzcnMcmyiQ +iRM9HcEARwmWmjgb3bHPDcK0RPOWlc4yOo80nOAXx17Org3bhzjlP1v9mxnhMUF6cKojawHhRUzN +lM47ni3niAIi9G7oyOzWPPO5std3eqx7 +-----END CERTIFICATE----- diff --git a/priv/repo/migrations/20240121234321_create_tables_for_gita_clone.exs b/priv/repo/migrations/20240121234321_create_tables_for_gita_clone.exs new file mode 100644 index 00000000..4b447e25 --- /dev/null +++ b/priv/repo/migrations/20240121234321_create_tables_for_gita_clone.exs @@ -0,0 +1,47 @@ +defmodule Vyasa.Repo.Migrations.CreateTablesForGitaClone do + use Ecto.Migration + + def change do + + # this is probably just a temporary table for now + create table(:sources, primary_key: false) do + add :id, :uuid, primary_key: true + add :title, :string + + timestamps([:utc_datetime]) + end + + create table(:chapters, primary_key: false) do + add :no, :integer, primary_key: true + add :title, :string + add :body, :text + + add :source_id, references(:sources, column: :id, type: :uuid), primary_key: true + end + + create unique_index(:chapters, [:source_id, :no]) # (src) uniquely identifies a chapter, left chap out because it's optional + + create table(:verses, primary_key: false) do + add :id, :uuid, primary_key: true + add :no, :integer + add :chapter_no, references(:chapters, column: :no, type: :integer, with: [source_id: :source_id]) + add :body, :text + add :source_id, references(:sources, column: :id, type: :uuid), null: false + end + + create unique_index(:verses, [:source_id, :chapter_no, :no]) # (src) uniquely identifies a verse, left chap out because it's optional + + + + create table(:translations, primary_key: false) do + add :id, :uuid, primary_key: true + add :lang, :string + add :type, :string + + add :target, :jsonb + add :chapter_no, references(:chapters, column: :no, type: :integer, with: [source_id: :source_id]) + add :verse_id, references(:verses, column: :id, type: :uuid, on_delete: :nothing) + add :source_id, references(:sources, column: :id, type: :uuid), null: false + end + end +end diff --git a/priv/repo/migrations/20240131122233_gen_media_events.exs b/priv/repo/migrations/20240131122233_gen_media_events.exs new file mode 100644 index 00000000..945af24c --- /dev/null +++ b/priv/repo/migrations/20240131122233_gen_media_events.exs @@ -0,0 +1,51 @@ +defmodule Vyasa.Repo.Migrations.GenMediaEvents do + use Ecto.Migration + + def change do + create table(:tracks, primary_key: false) do + add :id, :uuid, primary_key: true + add :title, :string + end + + create table(:voices, primary_key: false) do + add :id, :uuid, primary_key: true + add :lang, :string + add :title, :string + add :duration, :integer + add :meta, :jsonb + add :track_id, references(:tracks, column: :id, type: :uuid) + add :chapter_no, references(:chapters, column: :no, type: :integer, with: [source_id: :source_id]) + add :source_id, references(:sources, column: :id, type: :uuid) + + timestamps([:utc_datetime]) + end + + create table(:videos, primary_key: false) do + add :id, :uuid, primary_key: true + add :type, :string + add :ext_uri, :string + add :voice_id, references(:voices, column: :id, type: :uuid, on_delete: :nothing) + + timestamps([:utc_datetime]) + end + + create table(:events, primary_key: false) do + add :id, :uuid, primary_key: true + add :origin, :integer + add :duration, :integer + add :phase, :string + + add :verse_id, references(:verses, column: :id, type: :uuid, on_delete: :nothing) + add :voice_id, references(:voices, column: :id, type: :uuid, on_delete: :nothing) + add :fragments, {:array, :map}, null: false, default: [] + add :source_id, references(:sources, column: :id, type: :uuid) + end + + alter table(:chapters) do + add :key, :string + add :parent_no, references(:chapters, column: :no, type: :integer, with: [source_id: :source_id]) + end + + create unique_index(:sources, [:title]) + end +end diff --git a/priv/repo/seeds.exs b/priv/repo/seeds.exs index ad988ca7..01f37bf3 100644 --- a/priv/repo/seeds.exs +++ b/priv/repo/seeds.exs @@ -9,3 +9,12 @@ # # We recommend using the bang functions (`insert!`, `update!` # and so on) as they will fail if something goes wrong. +require Logger +try do + ExAws.S3.put_bucket("vyasa", "ap-southeast-1") + |> ExAws.request!() + IO.inspect("ok good", "bucket creation") +rescue + e -> + Logger.debug(Exception.format(:error, e, __STACKTRACE__)) +end diff --git a/priv/static/corpus/gita/verse.json b/priv/static/corpus/gita/verse.json index 7442434b..898db522 100644 --- a/priv/static/corpus/gita/verse.json +++ b/priv/static/corpus/gita/verse.json @@ -56,7 +56,7 @@ "title": "Verse 5", "verse_number": 5, "verse_order": 5, - "transliteration": "dhṛiṣhṭaketuśhchekitānaḥ kāśhirājaśhcha vīryavān\npurujit kuntibhojaśhcha śhaibyaśhcha nara-puṅgavaḥ\nyudhāmanyuśhcha vikrānta uttamaujāśhcha vīryavān\n", + "transliteration": "dhṛiṣhṭaketuśhchekitānaḥ kāśhirājaśhcha vīryavān\npurujit kuntibhojaśhcha śhaibyaśhcha nara-puṅgavaḥ\n", "word_meanings": "dhṛiṣhṭaketuḥ—Dhrishtaketu; chekitānaḥ—Chekitan; kāśhirājaḥ—Kashiraj; cha—and; vīrya-vān—heroic; purujit—Purujit; kuntibhojaḥ—Kuntibhoj; cha—and; śhaibyaḥ—Shaibya; cha—and; nara-puṅgavaḥ—best of men; yudhāmanyuḥ—Yudhamanyu; cha—and; vikrāntaḥ—courageous; uttamaujāḥ—Uttamauja; cha—and; vīrya-vān—gallant;\n" }, { @@ -68,7 +68,7 @@ "title": "Verse 6", "verse_number": 6, "verse_order": 6, - "transliteration": "saubhadro draupadeyāśhcha sarva eva mahā-rathāḥ\n", + "transliteration": "yudhāmanyuśhcha vikrānta uttamaujāśhcha vīryavān\nsaubhadro draupadeyāśhcha sarva eva mahā-rathāḥ\n", "word_meanings": "saubhadraḥ—the son of Subhadra; draupadeyāḥ—the sons of Draupadi; cha—and; sarve—all; eva—indeed; mahā-rathāḥ—warriors who could single handedly match the strength of ten thousand ordinary warriors\n" }, { @@ -232,24 +232,24 @@ "chapter_number": 1, "externalId": 20, "id": 20, - "text": "अथ व्यवस्थितान् दृष्ट्वा धार्तराष्ट्रान्कपिध्वजः।\n\nप्रवृत्ते शस्त्रसंपाते धनुरुद्यम्य पाण्डवः।।1.20।।\n ", + "text": "अथ व्यवस्थितान् दृष्ट्वा धार्तराष्ट्रान्कपिध्वजः।\n\nप्रवृत्ते शस्त्रसंपाते धनुरुद्यम्य पाण्डवः।।1.20।।\n", "title": "Verse 20", "verse_number": 20, "verse_order": 20, - "transliteration": "atha vyavasthitān dṛiṣhṭvā dhārtarāṣhṭrān kapi-dhwajaḥ\npravṛitte śhastra-sampāte dhanurudyamya pāṇḍavaḥ\nhṛiṣhīkeśhaṁ tadā vākyam idam āha mahī-pate\n", - "word_meanings": "atha—thereupon; vyavasthitān—arrayed; dṛiṣhṭvā—seeing; dhārtarāṣhṭrān—Dhritarashtra’s sons; kapi-dwajaḥ—the Monkey Bannered; pravṛitte—about to commence; śhastra-sampāte—to use the weapons; dhanuḥ—bow; udyamya—taking up; pāṇḍavaḥ—Arjun, the son of Pandu; hṛiṣhīkeśham—to Shree Krishna; tadā—at that time; vākyam—words; idam—these; āha—said; mahī-pate—King\n" + "transliteration": "atha vyavasthitān dṛiṣhṭvā dhārtarāṣhṭrān kapi-dhwajaḥ\npravṛitte śhastra-sampāte dhanurudyamya pāṇḍavaḥ\n", + "word_meanings": "atha—thereupon; vyavasthitān—arrayed; dṛiṣhṭvā—seeing; dhārtarāṣhṭrān—Dhritarashtra’s sons; kapi-dwajaḥ—the Monkey Bannered; pravṛitte—about to commence; śhastra-sampāte—to use the weapons; dhanuḥ—bow; udyamya—taking up; pāṇḍavaḥ—Arjun, the son of Pandu\n" }, { "chapter_id": 1, "chapter_number": 1, "externalId": 21, "id": 21, - "text": "अर्जुन उवाच\n\nहृषीकेशं तदा वाक्यमिदमाह महीपते।\n\nसेनयोरुभयोर्मध्ये रथं स्थापय मेऽच्युत।।1.21।।\n ", + "text": "हृषीकेशं तदा वाक्यमिदमाह महीपते अर्जुन उवाच\n\nसेनयोरुभयोर्मध्ये रथं स्थापय मेऽच्युत।।1.21।।\n ", "title": "Verse 21", "verse_number": 21, "verse_order": 21, - "transliteration": "arjuna uvācha\nsenayor ubhayor madhye rathaṁ sthāpaya me ’chyuta\n", - "word_meanings": "arjunaḥ uvācha—Arjun said; senayoḥ—armies; ubhayoḥ—both; madhye—in the middle; ratham—chariot; sthāpaya—place; me—my; achyuta—Shree Krishna, the infallible One;\n" + "transliteration": "hṛiṣhīkeśhaṁ tadā vākyam idam āha mahī-pate\narjuna uvācha\nsenayor ubhayor madhye rathaṁ sthāpaya me ’chyuta\n", + "word_meanings": "hṛiṣhīkeśham—to Shree Krishna; tadā—at that time; vākyam—words; idam—these; āha—said; mahī-pate—Kingarjunaḥ uvācha—Arjun said; senayoḥ—armies; ubhayoḥ—both; madhye—in the middle; ratham—chariot; sthāpaya—place; me—my; achyuta—Shree Krishna, the infallible One;\n" }, { "chapter_id": 1, @@ -304,12 +304,12 @@ "chapter_number": 1, "externalId": 26, "id": 26, - "text": "तत्रापश्यत्स्थितान्पार्थः पितृ़नथ पितामहान्।\n\nआचार्यान्मातुलान्भ्रातृ़न्पुत्रान्पौत्रान्सखींस्तथा।।1.26।।\n ", + "text": "तत्रापश्य त्स्थितान् पार्थः पितृ़नथ पितामहान्।\n\nआचार्यान् मातुलान् भ्रातृ़न् पुत्रान् पौत्रान् सखींस् तथा।।1.26।।\n ", "title": "Verse 26", "verse_number": 26, "verse_order": 26, - "transliteration": "tatrāpaśhyat sthitān pārthaḥ pitṝīn atha pitāmahān\nāchāryān mātulān bhrātṝīn putrān pautrān sakhīṁs tathā\nśhvaśhurān suhṛidaśh chaiva senayor ubhayor api\n", - "word_meanings": "tatra—there; apaśhyat—saw; sthitān—stationed; pārthaḥ—Arjun; pitṝīn—fathers; atha—thereafter; pitāmahān—grandfathers; āchāryān—teachers; mātulān—maternal uncles; bhrātṝīn—brothers; putrān—sons; pautrān—grandsons; sakhīn—friends; tathā—also; śhvaśhurān—fathers-in-law; suhṛidaḥ—well-wishers; cha—and; eva—indeed; senayoḥ—armies; ubhayoḥ—in both armies; api—also\n" + "transliteration": "tatrāpaśhyat sthitān pārthaḥ pitṝīn atha pitāmahān\nāchāryān mātulān bhrātṝīn putrān pautrān sakhīṁs tathā\n", + "word_meanings": "tatra—there; apaśhyat—saw; sthitān—stationed; pārthaḥ—Arjun; pitṝīn—fathers; atha—thereafter; pitāmahān—grandfathers; āchāryān—teachers; mātulān—maternal uncles; bhrātṝīn—brothers; putrān—sons; pautrān—grandsons; sakhīn—friends; tathā—likewise\n" }, { "chapter_id": 1, @@ -320,20 +320,20 @@ "title": "Verse 27", "verse_number": 27, "verse_order": 27, - "transliteration": "tān samīkṣhya sa kaunteyaḥ sarvān bandhūn avasthitān\nkṛipayā parayāviṣhṭo viṣhīdann idam abravīt\n", - "word_meanings": "tān—these; samīkṣhya—on seeing; saḥ—they; kaunteyaḥ—Arjun, the son of Kunti; sarvān—all; bandhūn—relatives; avasthitān—present; kṛipayā—by compassion; parayā—great; āviṣhṭaḥ—overwhelmed; viṣhīdan—deep sorrow; idam—this; abravīt—spoke\n" + "transliteration": "śhvaśhurān suhṛidaśh chaiva senayor ubhayor api\ntān samīkṣhya sa kaunteyaḥ sarvān bandhūn avasthitān\n", + "word_meanings": "śhvaśhurān—fathers-in-law; suhṛidaḥ—well-wishers; cha—and; eva—indeed; senayoḥ—armies; ubhayoḥ—in both armies; api—also; tān—these; samīkṣhya—on seeing; saḥ—they; kaunteyaḥ—Arjun, the son of Kunti; sarvān—all; bandhūn—relatives; avasthitān—present\n" }, { "chapter_id": 1, "chapter_number": 1, "externalId": 28, "id": 28, - "text": "अर्जुन उवाच\n\nकृपया परयाऽऽविष्टो विषीदन्निदमब्रवीत्।\n\nदृष्ट्वेमं स्वजनं कृष्ण युयुत्सुं समुपस्थितम्।।1.28।।\n ", + "text": "कृपया परयाऽऽविष्टो विषीदन्न् इदम् अब्रवीत्।\n\nअर्जुन उवाच\n\nदृष्ट्वेमं स्वजनं कृष्ण युयुत्सुं समुपस्थितम्।।1.28।।\n ", "title": "Verse 28", "verse_number": 28, "verse_order": 28, - "transliteration": "arjuna uvācha\ndṛiṣhṭvemaṁ sva-janaṁ kṛiṣhṇa yuyutsuṁ samupasthitam\n", - "word_meanings": "arjunaḥ uvācha—Arjun said; dṛiṣhṭvā—on seeing; imam—these; sva-janam—kinsmen; kṛiṣhṇa—Krishna; yuyutsum—eager to fight; samupasthitam—present; \n" + "transliteration": "kṛipayā parayāviṣhṭo viṣhīdann idam abravīt\narjuna uvācha\ndṛiṣhṭvemaṁ sva-janaṁ kṛiṣhṇa yuyutsuṁ samupasthitam\n", + "word_meanings": "kṛipayā—by compassion; parayā—great; āviṣhṭaḥ—overwhelmed; viṣhīdan—deep sorrow; idam—this; abravīt—spoke; arjunaḥ uvācha—Arjun said; dṛiṣhṭvā—on seeing; imam—these; sva-janam—kinsmen; kṛiṣhṇa—Krishna; yuyutsum—eager to fight; samupasthitam—present; \n" }, { "chapter_id": 1, diff --git a/priv/static/corpus/shlokam.org/hanumanchalisa.json b/priv/static/corpus/shlokam.org/hanumanchalisa.json new file mode 100644 index 00000000..98648286 --- /dev/null +++ b/priv/static/corpus/shlokam.org/hanumanchalisa.json @@ -0,0 +1 @@ +{"description":"Hanuman Chalisa is authored by 16th-century poet Tulsidas in the Awadhi language. It has 40 verses and every verse has 4 lines.","title":"Hanuman Chalisa","verses":[{"count":1,"verse_meaning":"Having polished the mirror of my heart with the dust of my Guru’s lotus feet, I recite the divine fame of the greatest king of Raghukul dynasty, which bestows us with the fruit of all the four efforts.","verse_sanskrit":"श्रीगुरु चरन सरोज रज निज मनु मुकुरु सुधारि ।\n\nबरनउँ रघुबर बिमल जसु जो दायकु फल चारि ॥","verse_trans":"śrīguru carana saroja raja nija manu mukuru sudhāri .\n\nbaranaüm̐ raghubara bimala jasu jo dāyaku phala cāri .."},{"count":2,"verse_meaning":"Knowing that this mind of mine has less intelligence, I remember the ‘Son of Wind’ who, granting me strength, wisdom and all kinds of knowledge, removes all my suffering and shortcomings.","verse_sanskrit":"बुद्धिहीन तनु जानिके सुमिरौं पवन-कुमार ।\n\nबल बुधि बिद्या देहु मोहिं हरहु कलेस बिकार ॥","verse_trans":"buddhihīna tanu jānike sumirauṃ pavana-kumāra .\n\nbala budhi bidyā dehu mohiṃ harahu kalesa bikāra .."},{"count":3,"verse_meaning":"Victory to Lord Hanuman, the ocean of wisdom and virtue. Victory to the Lord who is supreme among the monkeys, illuminator of the three worlds.","verse_sanskrit":"॥चौपाई॥\n\nजय हनुमान ज्ञान गुन सागर ।\n\nजय कपीस तिहुँ लोक उजागर ॥१॥","verse_trans":"jaya hanumāna jñāna guna sāgara .\n\njaya kapīsa tihum̐ loka ujāgara ..1.."},{"count":4,"verse_meaning":"you are Lord Rama’s emissary,‌ the abode of matchless power, Mother Anjani’s son and also popular as the ‘Son of the Wind’.","verse_sanskrit":"राम दूत अतुलित बल धामा ।\n\nअञ्जनि-पुत्र पवनसुत नामा ॥२॥","verse_trans":"rāma dūta atulita bala dhāmā .\n\nañjani-putra pavanasuta nāmā ..2.."},{"count":5,"verse_meaning":"Great hero, you are as mighty as a thunderbolt. you remove evil intellect and are the companion of those having good ones.","verse_sanskrit":"महाबीर बिक्रम बजरङ्गी ।\n\nकुमति निवार सुमति के सङ्गी ॥३॥","verse_trans":"mahābīra bikrama bajaraṅgī .\n\nkumati nivāra sumati ke saṅgī ..3.."},{"count":6,"verse_meaning":"your skin is golden in color and you are adorned with beautiful clothes. you have adorning earrings in your ears and your hair is curly and thick.","verse_sanskrit":"कञ्चन बरन बिराज सुबेसा ।\n\nकानन कुण्डल कुञ्चित केसा ॥४॥","verse_trans":"kañcana barana birāja subesā .\n\nkānana kuṇḍala kuñcita kesā ..4.."},{"count":7,"verse_meaning":"In your hands, shine a mace and a flag of righteousness. A sacred thread adorns your right shoulder.","verse_sanskrit":"हाथ बज्र औ ध्वजा बिराजै ।\n\nकाँधे मूँज जनेउ साजै ॥५॥","verse_trans":"hātha bajra au dhvajā birājai .\n\nkām̐dhe mūm̐ja janeu sājai ..5.."},{"count":8,"verse_meaning":"You are the embodiment of Lord Shiva and vanar-raj Kesari’s son. There is no limit or end to your glory, your magnificence. The whole universe worships you.","verse_sanskrit":"सङ्कर सुवन केसरीनन्दन ।\n\nतेज प्रताप महा जग बन्दन ॥६॥","verse_trans":"saṅkara suvana kesarīnandana .\n\nteja pratāpa mahā jaga bandana ..6.."},{"count":9,"verse_meaning":"You are the wisest of the wise, virtuous and (morally) clever. You are always eager to do Lord Rama’s works.","verse_sanskrit":"बिद्यावान गुनी अति चातुर ।\n\nराम काज करिबे को आतुर ॥७॥","verse_trans":"bidyāvāna gunī ati cātura .\n\nrāma kāja karibe ko ātura ..7.."},{"count":10,"verse_meaning":"You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart.","verse_sanskrit":"प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥","verse_trans":"prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8.."},{"count":11,"verse_meaning":"Taking the subtle form, you appeared in front of Mother Sita. And, taking the formidable form, you burnt the Lanka (Ravana’s kingdom).","verse_sanskrit":"सूक्ष्म रूप धरि सियहिं दिखावा ।\n\nबिकट रूप धरि लङ्क जरावा ॥९॥","verse_trans":"sūkṣma rūpa dhari siyahiṃ dikhāvā .\n\nbikaṭa rūpa dhari laṅka jarāvā ..9.."},{"count":12,"verse_meaning":"Taking the massive form (like that of Bheema), you slaughtered the demons. This is how, you completed Lord Rama’s tasks, successfully.","verse_sanskrit":"भीम रूप धरि असुर सँहारे ।\n\nरामचन्द्र के काज सँवारे ॥१०॥","verse_trans":"bhīma rūpa dhari asura sam̐hāre .\n\nrāmacandra ke kāja sam̐vāre ..10.."},{"count":13,"verse_meaning":"Bringing the magic-herb (sanjivani), you revived Lord Laxmana.","verse_sanskrit":"लाय सञ्जीवन लखन जियाये ।\n\nश्रीरघुबीर हरषि उर लाये ॥११॥","verse_trans":"lāya sañjīvana lakhana jiyāye .\n\nśrīraghubīra haraṣi ura lāye ..11.."},{"count":14,"verse_meaning":"Raghupati, Lord Rama praised you greatly and overflowing in gratitude, said that you are a dear brother to him just as Bharat is.","verse_sanskrit":"रघुपति कीह्नी बहुत बड़ाई ।\n\nतुम मम प्रिय भरतहि सम भाई ॥१२॥","verse_trans":"raghupati kīhnī bahuta bar̤āī .\n\ntuma mama priya bharatahi sama bhāī ..12.."},{"count":15,"verse_meaning":"Saying this, Lord Rama drew you to himself and embraced you. Sages like Sanaka, Gods like Brahma and sages like Narada and even the thousand-mouthed serpent sing your fame!","verse_sanskrit":"सहस बदन तुह्मारो जस गावैं ।\n\nअस कहि श्रीपति कण्ठ लगावैं ॥१३॥","verse_trans":"sahasa badana tuhmāro jasa gāvaiṃ .\n\nasa kahi śrīpati kaṇṭha lagāvaiṃ ..13.."},{"count":16,"verse_meaning":"Sanak, Sanandan and the other Rishis and great saints; Brahma – the god, Narada, Saraswati – the Mother Divine and the King of serpents sing your glory.","verse_sanskrit":"सनकादिक ब्रह्मादि मुनीसा ।\n\nनारद सारद सहित अहीसा ॥१४॥","verse_trans":"sanakādika brahmādi munīsā .\n\nnārada sārada sahita ahīsā ..14.."},{"count":17,"verse_meaning":"Yama, Kubera and the guardians of the four quarters; poets and scholars – none can express your glory.","verse_sanskrit":"जम कुबेर दिगपाल जहाँ ते ।\n\nकबि कोबिद कहि सके कहाँ ते ॥१५॥","verse_trans":"jama kubera digapāla jahām̐ te .\n\nkabi kobida kahi sake kahām̐ te ..15.."},{"count":18,"verse_meaning":"You helped Sugriva by introducing him to Lord Rama and regaining his crown. Therefore, you gave him the Kingship (the dignity of being called a king).","verse_sanskrit":"तुम उपकार सुग्रीवहिं कीह्ना ।\n\nराम मिलाय राज पद दीह्ना ॥१६॥","verse_trans":"tuma upakāra sugrīvahiṃ kīhnā .\n\nrāma milāya rāja pada dīhnā ..16.."},{"count":19,"verse_meaning":"Likewise, complying with your preachings, even Vibhishana became the King of Lanka.","verse_sanskrit":"तुह्मरो मन्त्र बिभीषन माना ।\n\nलङ्केस्वर भए सब जग जाना ॥१७॥","verse_trans":"tuhmaro mantra bibhīṣana mānā .\n\nlaṅkesvara bhae saba jaga jānā ..17.."},{"count":20,"verse_meaning":"You swallowed the sun, located thousands of miles away, mistaking it to be a sweet, red fruit!","verse_sanskrit":"जुग सहस्र जोजन पर भानु ।\n\nलील्यो ताहि मधुर फल जानू ॥१८॥","verse_trans":"juga sahasra jojana para bhānu .\n\nlīlyo tāhi madhura phala jānū ..18.."},{"count":21,"verse_meaning":"Keeping the ring in your mouth, which was given to you by Lord Rama, you crossed over the ocean, to no astonishment, whatsoever.","verse_sanskrit":"प्रभु मुद्रिका मेलि मुख माहीं ।\n\nजलधि लाँघि गये अचरज नाहीं ॥१९॥","verse_trans":"prabhu mudrikā meli mukha māhīṃ .\n\njaladhi lām̐ghi gaye acaraja nāhīṃ ..19.."},{"count":22,"verse_meaning":"All difficult tasks of this world become easy, with your grace.","verse_sanskrit":"दुर्गम काज जगत के जेते ।\n\nसुगम अनुग्रह तुह्मरे तेते ॥२०॥","verse_trans":"durgama kāja jagata ke jete .\n\nsugama anugraha tuhmare tete ..20.."},{"count":23,"verse_meaning":"You are the guardian at Lord Rama’s door. Nobody can move forward without your permission which means that Lord Rama’s darshans (to get the sight of) are possible only with your blessings.","verse_sanskrit":"राम दुआरे तुम रखवारे ।\n\nहोत न आज्ञा बिनु पैसारे ॥२१॥","verse_trans":"rāma duāre tuma rakhavāre .\n\nhota na ājñā binu paisāre ..21.."},{"count":24,"verse_meaning":"Those who take refuge in you, find all the comforts and happiness. When we have a protector like you, we do not need to get scared of anybody or anything.","verse_sanskrit":"सब सुख लहै तुह्मारी सरना ।\n\nतुम रच्छक काहू को डर ना ॥२२॥","verse_trans":"saba sukha lahai tuhmārī saranā .\n\ntuma racchaka kāhū ko ḍara nā ..22.."},{"count":25,"verse_meaning":"You alone can withstand your magnificence. All the three worlds start trembling at one roar of yours.","verse_sanskrit":"आपन तेज सह्मारो आपै ।\n\nतीनों लोक हाँक तें काँपै ॥२३॥","verse_trans":"āpana teja sahmāro āpai .\n\ntīnoṃ loka hām̐ka teṃ kām̐pai ..23.."},{"count":26,"verse_meaning":"O Mahaveer! No ghosts or evil spirits come near the ones who remember your name. Therefore, just remembering your name does everything!","verse_sanskrit":"भूत पिसाच निकट नहिं आवै ।\n\nमहाबीर जब नाम सुनावै ॥२४॥","verse_trans":"bhūta pisāca nikaṭa nahiṃ āvai .\n\nmahābīra jaba nāma sunāvai ..24.."},{"count":27,"verse_meaning":"O Hanuman! All diseases and all kinds of pain get eradicated when one recites or chants your name. Therefore, chanting your name regularly is considered to be very significant.","verse_sanskrit":"नासै रोग हरै सब पीरा ।\n\nजपत निरन्तर हनुमत बीरा ॥२५॥","verse_trans":"nāsai roga harai saba pīrā .\n\njapata nirantara hanumata bīrā ..25.."},{"count":28,"verse_meaning":"Whoever meditates upon or worships you with thought, word, and deed, gets freedom from all kinds of crisis and affliction.","verse_sanskrit":"सङ्कट तें हनुमान छुड़ावै ।\n\nमन क्रम बचन ध्यान जो लावै ॥२६॥","verse_trans":"saṅkaṭa teṃ hanumāna chur̤āvai .\n\nmana krama bacana dhyāna jo lāvai ..26.."},{"count":29,"verse_meaning":"Lord Rama is the greatest ascetic amongst all the kings. But, it’s only you who carried out all the tasks of Lord Sri Rama.","verse_sanskrit":"सब पर राम तपस्वी राजा ।\n\nतिन के काज सकल तुम साजा ॥२७॥","verse_trans":"saba para rāma tapasvī rājā .\n\ntina ke kāja sakala tuma sājā ..27.."},{"count":30,"verse_meaning":"One who comes to you with any longing or a sincere desire obtains the abundance of the manifested fruit, which remains undying throughout life.","verse_sanskrit":"और मनोरथ जो कोई लावै ।\n\nसोई अमित जीवन फल पावै ॥२८॥","verse_trans":"aura manoratha jo koī lāvai .\n\nsoī amita jīvana phala pāvai ..28.."},{"count":31,"verse_meaning":"Your splendor fills all the four ages. And, your glory is renowned throughout the world.","verse_sanskrit":"चारों जुग परताप तुह्मारा ।\n\nहै परसिद्ध जगत उजियारा ॥२९॥","verse_trans":"cāroṃ juga paratāpa tuhmārā .\n\nhai parasiddha jagata ujiyārā ..29.."},{"count":32,"verse_meaning":"You are the guardian of saints and sages; the destroyer of demons and adored by Lord Rama.","verse_sanskrit":"साधु सन्त के तुम रखवारे ।\n\nअसुर निकन्दन राम दुलारे ॥३०॥","verse_trans":"sādhu santa ke tuma rakhavāre .\n\nasura nikandana rāma dulāre ..30.."},{"count":33,"verse_meaning":"You have been blessed by Mother Janaki to give boon further, to the deserving ones, wherein you can grant the siddhis (eight different powers) and the nidhis (nine different kinds of wealth).","verse_sanskrit":"अष्टसिद्धि नौ निधि के दाता ।\n\nअस बर दीन जानकी माता ॥३१॥","verse_trans":"aṣṭasiddhi nau nidhi ke dātā .\n\nasa bara dīna jānakī mātā ..31.."},{"count":34,"verse_meaning":"You have the essence of Ram bhakti, may you always remain the humble and devoted servant of Raghupati.","verse_sanskrit":"राम रसायन तुह्मरे पासा ।\n\nसदा रहो रघुपति के दासा ॥३२॥","verse_trans":"rāma rasāyana tuhmare pāsā .\n\nsadā raho raghupati ke dāsā ..32.."},{"count":35,"verse_meaning":"When one sings your praise, your name, he gets to meet Lord Rama and finds relief from the sorrows of many lifetimes.","verse_sanskrit":"तुह्मरे भजन राम को पावै ।\n\nजनम जनम के दुख बिसरावै ॥३३॥","verse_trans":"tuhmare bhajana rāma ko pāvai .\n\njanama janama ke dukha bisarāvai ..33.."},{"count":36,"verse_meaning":"By your grace, one will go to the immortal abode of Lord Rama after death and remain devoted to him.","verse_sanskrit":"अन्त काल रघुबर पुर जाई ।\n\nजहाँ जन्म हरिभक्त कहाई ॥३४॥","verse_trans":"anta kāla raghubara pura jāī .\n\njahām̐ janma haribhakta kahāī ..34.."},{"count":37,"verse_meaning":"It is not needed to serve any other deity or god. Service to Lord Hanuman gives all the comforts.","verse_sanskrit":"और देवता चित्त न धरई ।\n\nहनुमत सेइ सर्ब सुख करई ॥३५॥","verse_trans":"aura devatā citta na dharaī .\n\nhanumata sei sarba sukha karaī ..35.."},{"count":38,"verse_meaning":"All troubles cease for the one who remembers the powerful lord, Lord Hanuman and all his pains also come to an end.","verse_sanskrit":"सङ्कट कटै मिटै सब पीरा ।\n\nजो सुमिरै हनुमत बलबीरा ॥३६॥","verse_trans":"saṅkaṭa kaṭai miṭai saba pīrā .\n\njo sumirai hanumata balabīrā ..36.."},{"count":39,"verse_meaning":"O Lord Hanuman! Praises and glory to you O mighty lord, please bestow your grace as our supreme guru.","verse_sanskrit":"जय जय जय हनुमान गोसाईं ।\n\nकृपा करहु गुरुदेव की नाईं ॥३७॥","verse_trans":"jaya jaya jaya hanumāna gosāīṃ .\n\nkṛpā karahu gurudeva kī nāīṃ ..37.."},{"count":40,"verse_meaning":"One who recites this Chalisa a hundred times is released from all bondages and will attain great bliss.","verse_sanskrit":"जो सत बार पाठ कर कोई ।\n\nछूटहि बन्दि महा सुख होई ॥३८॥","verse_trans":"jo sata bāra pāṭha kara koī .\n\nchūṭahi bandi mahā sukha hoī ..38.."},{"count":41,"verse_meaning":"One who reads and recites this Hanuman Chalisa, all his works get accomplished. Lord Shiva, himself, is the witness to it.","verse_sanskrit":"जो यह पढ़ै हनुमान चालीसा ।\n\nहोय सिद्धि साखी गौरीसा ॥३९॥","verse_trans":"jo yaha par̤hai hanumāna cālīsā .\n\nhoya siddhi sākhī gaurīsā ..39.."},{"count":42,"verse_meaning":"O Lord Hanuman, may I always remain a servant, a devotee to Lord Sri Ram, says Tulsidas. And, may you always reside in my heart.","verse_sanskrit":"तुलसीदास सदा हरि चेरा ।\n\nकीजै नाथ हृदय महँ डेरा ॥४०॥","verse_trans":"tulasīdāsa sadā hari cerā .\n\nkījai nātha hṛdaya maham̐ ḍerā ..40.."},{"count":43,"verse_meaning":"O the Son of Wind, you are the destroyer of all sorrows. you are the embodiment of fortune and prosperity.\n\nWith Lord Rama, Laxmana and Mother Sita, dwell in my heart, always.","verse_sanskrit":"॥दोहा॥\n\nपवनतनय सङ्कट हरन मङ्गल मूरति रूप ।\n\nराम लखन सीता सहित हृदय बसहु सुर भूप ॥","verse_trans":"pavanatanaya saṅkaṭa harana maṅgala mūrati rūpa .\n\nrāma lakhana sītā sahita hṛdaya basahu sura bhūpa .."}]} \ No newline at end of file diff --git a/priv/static/images/the_vyasa_project_1.png b/priv/static/images/the_vyasa_project_1.png new file mode 100644 index 00000000..41f60d06 Binary files /dev/null and b/priv/static/images/the_vyasa_project_1.png differ diff --git a/scripts/chalisa.json b/scripts/chalisa.json new file mode 100644 index 00000000..fd924409 --- /dev/null +++ b/scripts/chalisa.json @@ -0,0 +1,3652 @@ +{ + "wireMagic": "pb3", + "pens": [ { + + } ], + "wsWinStyles": [ { + + }, { + "mhModeHint": 2, + "juJustifCode": 0, + "sdScrollDir": 3 + } ], + "wpWinPositions": [ { + + }, { + "apPoint": 6, + "ahHorPos": 20, + "avVerPos": 100, + "rcRows": 2, + "ccCols": 40 + } ], + "events": [ { + "tStartMs": 0, + "dDurationMs": 583419, + "id": 1, + "wpWinPosId": 1, + "wsWinStyleId": 1 + }, { + "tStartMs": 0, + "dDurationMs": 8690, + "wWinId": 1, + "segs": [ { + "utf8": "को", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 1360, + "dDurationMs": 7330, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 1370, + "dDurationMs": 11370, + "wWinId": 1, + "segs": [ { + "utf8": "अच्छी", + "acAsrConf": 229 + }, { + "utf8": " तरह", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " गुरु", + "tOffsetMs": 1960, + "acAsrConf": 229 + }, { + "utf8": " चरण", + "tOffsetMs": 2470, + "acAsrConf": 229 + }, { + "utf8": " सरोज", + "tOffsetMs": 3870, + "acAsrConf": 229 + }, { + "utf8": " रज", + "tOffsetMs": 4870, + "acAsrConf": 229 + }, { + "utf8": " निज", + "tOffsetMs": 5380, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 8680, + "dDurationMs": 4060, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 8690, + "dDurationMs": 4050, + "wWinId": 1, + "segs": [ { + "utf8": "मनु", + "acAsrConf": 181 + }, { + "utf8": " मुकुरु", + "tOffsetMs": 1020, + "acAsrConf": 225 + }, { + "utf8": " सुधारि", + "tOffsetMs": 2020, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 13930, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 13940, + "dDurationMs": 8230, + "wWinId": 1, + "segs": [ { + "utf8": "बरनउं", + "acAsrConf": 146 + }, { + "utf8": " रघुबर", + "tOffsetMs": 1000, + "acAsrConf": 158 + }, { + "utf8": " विमल", + "tOffsetMs": 1869, + "acAsrConf": 68 + }, { + "utf8": " जसु", + "tOffsetMs": 2550, + "acAsrConf": 185 + } ] + }, { + "tStartMs": 18160, + "dDurationMs": 4010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 18170, + "dDurationMs": 4000, + "wWinId": 1, + "segs": [ { + "utf8": "जो", + "acAsrConf": 229 + }, { + "utf8": " लायक", + "tOffsetMs": 1000, + "acAsrConf": 125 + } ] + }, { + "tStartMs": 22390, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 22400, + "dDurationMs": 5590, + "wWinId": 1, + "segs": [ { + "utf8": "झाल", + "acAsrConf": 67 + }, { + "utf8": " बीम", + "tOffsetMs": 1000, + "acAsrConf": 142 + } ] + }, { + "tStartMs": 25150, + "dDurationMs": 2840, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 25160, + "dDurationMs": 5039, + "wWinId": 1, + "segs": [ { + "utf8": "बुद्धिहीन", + "acAsrConf": 228 + }, { + "utf8": " तनु", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " जानिके", + "tOffsetMs": 1180, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 27980, + "dDurationMs": 2219, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 27990, + "dDurationMs": 6140, + "wWinId": 1, + "segs": [ { + "utf8": "[हंसी]" + } ] + }, { + "tStartMs": 30189, + "dDurationMs": 3941, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 30199, + "dDurationMs": 3931, + "wWinId": 1, + "segs": [ { + "utf8": "सुमिरौं", + "acAsrConf": 229 + }, { + "utf8": " पवन-कुमार", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 34450, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 34460, + "dDurationMs": 7380, + "wWinId": 1, + "segs": [ { + "utf8": "बल", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 36819, + "dDurationMs": 5021, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 36829, + "dDurationMs": 7890, + "wWinId": 1, + "segs": [ { + "utf8": "धुंध", + "acAsrConf": 151 + }, { + "utf8": " गार्द", + "tOffsetMs": 1410, + "acAsrConf": 187 + }, { + "utf8": " देश", + "tOffsetMs": 2460, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 41830, + "dDurationMs": 2889, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 41840, + "dDurationMs": 5070, + "wWinId": 1, + "segs": [ { + "utf8": "मोहनियां", + "acAsrConf": 229 + }, { + "utf8": " अ", + "tOffsetMs": 1020, + "acAsrConf": 191 + } ] + }, { + "tStartMs": 44709, + "dDurationMs": 2201, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 44719, + "dDurationMs": 4801, + "wWinId": 1, + "segs": [ { + "utf8": "करे", + "acAsrConf": 190 + } ] + }, { + "tStartMs": 46900, + "dDurationMs": 2620, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 46910, + "dDurationMs": 7829, + "wWinId": 1, + "segs": [ { + "utf8": "बिकता", + "acAsrConf": 229 + }, { + "utf8": " बार", + "tOffsetMs": 1440, + "acAsrConf": 186 + } ] + }, { + "tStartMs": 49510, + "dDurationMs": 5229, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 49520, + "dDurationMs": 5219, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 55930, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 55940, + "dDurationMs": 11609, + "wWinId": 1, + "segs": [ { + "utf8": "जय", + "acAsrConf": 229 + }, { + "utf8": " हनुमान", + "tOffsetMs": 1290, + "acAsrConf": 188 + }, { + "utf8": " ज्ञान", + "tOffsetMs": 2290, + "acAsrConf": 229 + }, { + "utf8": " गुण", + "tOffsetMs": 2820, + "acAsrConf": 229 + }, { + "utf8": " सागर", + "tOffsetMs": 3820, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 61000, + "dDurationMs": 6549, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 61010, + "dDurationMs": 8490, + "wWinId": 1, + "segs": [ { + "utf8": "जय", + "acAsrConf": 229 + }, { + "utf8": " कपीस", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " तिहुं", + "tOffsetMs": 1299, + "acAsrConf": 229 + }, { + "utf8": " लोक", + "tOffsetMs": 2229, + "acAsrConf": 229 + }, { + "utf8": " तुझ", + "tOffsetMs": 3450, + "acAsrConf": 66 + }, { + "utf8": " कर", + "tOffsetMs": 4450, + "acAsrConf": 39 + } ] + }, { + "tStartMs": 67539, + "dDurationMs": 1961, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 67549, + "dDurationMs": 7621, + "wWinId": 1, + "segs": [ { + "utf8": "रामदूत", + "acAsrConf": 187 + }, { + "utf8": " अतुलित", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 69490, + "dDurationMs": 5680, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 69500, + "dDurationMs": 7830, + "wWinId": 1, + "segs": [ { + "utf8": "बल", + "acAsrConf": 229 + }, { + "utf8": " धामा", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " अंजनि-पुत्र", + "tOffsetMs": 1950, + "acAsrConf": 189 + }, { + "utf8": " पवनसुत", + "tOffsetMs": 3030, + "acAsrConf": 187 + } ] + }, { + "tStartMs": 75160, + "dDurationMs": 2170, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 75170, + "dDurationMs": 6160, + "wWinId": 1, + "segs": [ { + "utf8": "नामा", + "acAsrConf": 86 + } ] + }, { + "tStartMs": 77320, + "dDurationMs": 4010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 77330, + "dDurationMs": 4000, + "wWinId": 1, + "segs": [ { + "utf8": "मां", + "acAsrConf": 168 + }, { + "utf8": " ने", + "tOffsetMs": 1000, + "acAsrConf": 35 + } ] + }, { + "tStartMs": 81780, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 81790, + "dDurationMs": 4660, + "wWinId": 1, + "segs": [ { + "utf8": "श्रुति", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 83600, + "dDurationMs": 2850, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 83610, + "dDurationMs": 3960, + "wWinId": 1, + "segs": [ { + "utf8": "महाबीर", + "acAsrConf": 229 + }, { + "utf8": " बिक्रम", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " बजरंगी", + "tOffsetMs": 1720, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 86440, + "dDurationMs": 1130, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 86450, + "dDurationMs": 6400, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 87560, + "dDurationMs": 5290, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 87570, + "dDurationMs": 10170, + "wWinId": 1, + "segs": [ { + "utf8": "कुमति", + "acAsrConf": 229 + }, { + "utf8": " निवार", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " सुमति", + "tOffsetMs": 2130, + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 3130, + "acAsrConf": 229 + }, { + "utf8": " संगी", + "tOffsetMs": 3970, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 92840, + "dDurationMs": 4900, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 92850, + "dDurationMs": 9120, + "wWinId": 1, + "segs": [ { + "utf8": "कंचन", + "acAsrConf": 229 + }, { + "utf8": " बरन", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " बिराज", + "tOffsetMs": 2190, + "acAsrConf": 229 + }, { + "utf8": " सुबेसा", + "tOffsetMs": 3240, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 97730, + "dDurationMs": 4240, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 97740, + "dDurationMs": 10320, + "wWinId": 1, + "segs": [ { + "utf8": "कानन", + "acAsrConf": 229 + }, { + "utf8": " कुंडल", + "tOffsetMs": 1440, + "acAsrConf": 229 + }, { + "utf8": " कुंचित", + "tOffsetMs": 2670, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 101960, + "dDurationMs": 6100, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 101970, + "dDurationMs": 10380, + "wWinId": 1, + "segs": [ { + "utf8": "के", + "acAsrConf": 190 + }, { + "utf8": " आई", + "tOffsetMs": 1380, + "acAsrConf": 156 + }, { + "utf8": " हाथ", + "tOffsetMs": 2380, + "acAsrConf": 229 + }, { + "utf8": " बज्र", + "tOffsetMs": 2970, + "acAsrConf": 229 + }, { + "utf8": " औ", + "tOffsetMs": 3970, + "acAsrConf": 229 + }, { + "utf8": " ध्वजा", + "tOffsetMs": 4750, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 108050, + "dDurationMs": 4300, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 108060, + "dDurationMs": 6960, + "wWinId": 1, + "segs": [ { + "utf8": "विराजे", + "acAsrConf": 229 + }, { + "utf8": " कांधे", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " मूंज", + "tOffsetMs": 1620, + "acAsrConf": 229 + }, { + "utf8": " जनेऊ", + "tOffsetMs": 2620, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 112340, + "dDurationMs": 2680, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 112350, + "dDurationMs": 9270, + "wWinId": 1, + "segs": [ { + "utf8": "साजै", + "acAsrConf": 229 + }, { + "utf8": " संकर", + "tOffsetMs": 1110, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 115010, + "dDurationMs": 6610, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 115020, + "dDurationMs": 10290, + "wWinId": 1, + "segs": [ { + "utf8": "सुवन", + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1230, + "acAsrConf": 229 + }, { + "utf8": " तिरछी", + "tOffsetMs": 2230, + "acAsrConf": 229 + }, { + "utf8": " टू", + "tOffsetMs": 3070, + "acAsrConf": 213 + }, { + "utf8": " नंदन", + "tOffsetMs": 3790, + "acAsrConf": 229 + }, { + "utf8": " तेज", + "tOffsetMs": 4710, + "acAsrConf": 229 + }, { + "utf8": " प्रताप", + "tOffsetMs": 5710, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 121610, + "dDurationMs": 3700, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 121620, + "dDurationMs": 6739, + "wWinId": 1, + "segs": [ { + "utf8": "महा", + "acAsrConf": 229 + }, { + "utf8": " जग", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " बंदन", + "tOffsetMs": 1690, + "acAsrConf": 229 + }, { + "utf8": " विद्यावान", + "tOffsetMs": 2380, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 125300, + "dDurationMs": 3059, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 125310, + "dDurationMs": 3049, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 131840, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 131850, + "dDurationMs": 10120, + "wWinId": 1, + "segs": [ { + "utf8": "गुनी", + "acAsrConf": 229 + }, { + "utf8": " अति", + "tOffsetMs": 1110, + "acAsrConf": 229 + }, { + "utf8": " चातुर", + "tOffsetMs": 2110, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 135200, + "dDurationMs": 6770, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 135210, + "dDurationMs": 14570, + "wWinId": 1, + "segs": [ { + "utf8": "राम", + "acAsrConf": 229 + }, { + "utf8": " काज", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " करिबे", + "tOffsetMs": 1810, + "acAsrConf": 229 + }, { + "utf8": " को", + "tOffsetMs": 3060, + "acAsrConf": 229 + }, { + "utf8": " आतुर", + "tOffsetMs": 4320, + "acAsrConf": 229 + }, { + "utf8": " प्रभु", + "tOffsetMs": 5320, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 141960, + "dDurationMs": 7820, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 141970, + "dDurationMs": 9660, + "wWinId": 1, + "segs": [ { + "utf8": "पिंपरी", + "acAsrConf": 190 + }, { + "utf8": " सुनिबे", + "tOffsetMs": 1110, + "acAsrConf": 184 + }, { + "utf8": " को", + "tOffsetMs": 2110, + "acAsrConf": 229 + }, { + "utf8": " रसिया", + "tOffsetMs": 2560, + "acAsrConf": 229 + }, { + "utf8": " राम", + "tOffsetMs": 3660, + "acAsrConf": 229 + }, { + "utf8": " लखन", + "tOffsetMs": 4660, + "acAsrConf": 229 + }, { + "utf8": " सीता", + "tOffsetMs": 5620, + "acAsrConf": 229 + }, { + "utf8": " मन", + "tOffsetMs": 6810, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 149770, + "dDurationMs": 1860, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 149780, + "dDurationMs": 3740, + "wWinId": 1, + "segs": [ { + "utf8": "बसिया", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 151620, + "dDurationMs": 1900, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 151630, + "dDurationMs": 5010, + "wWinId": 1, + "segs": [ { + "utf8": "सूक्ष्म", + "acAsrConf": 229 + }, { + "utf8": " रूप", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 153510, + "dDurationMs": 3130, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 153520, + "dDurationMs": 4890, + "wWinId": 1, + "segs": [ { + "utf8": "धरि", + "acAsrConf": 229 + }, { + "utf8": " सियहि", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " दिखावा", + "tOffsetMs": 1330, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 156630, + "dDurationMs": 1780, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 156640, + "dDurationMs": 9280, + "wWinId": 1, + "segs": [ { + "utf8": "बिकट", + "acAsrConf": 228 + } ] + }, { + "tStartMs": 158400, + "dDurationMs": 7520, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 158410, + "dDurationMs": 9960, + "wWinId": 1, + "segs": [ { + "utf8": "दुग्गर", + "acAsrConf": 226 + }, { + "utf8": " लंक", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " जरावा", + "tOffsetMs": 2340, + "acAsrConf": 229 + }, { + "utf8": " भीम", + "tOffsetMs": 3340, + "acAsrConf": 229 + }, { + "utf8": " रूप", + "tOffsetMs": 4240, + "acAsrConf": 229 + }, { + "utf8": " धरि", + "tOffsetMs": 4930, + "acAsrConf": 229 + }, { + "utf8": " असुर", + "tOffsetMs": 6060, + "acAsrConf": 229 + }, { + "utf8": " अच्छा", + "tOffsetMs": 7060, + "acAsrConf": 125 + } ] + }, { + "tStartMs": 165910, + "dDurationMs": 2460, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 165920, + "dDurationMs": 6560, + "wWinId": 1, + "segs": [ { + "utf8": "हां", + "acAsrConf": 125 + }, { + "utf8": " रे", + "tOffsetMs": 750, + "acAsrConf": 148 + } ] + }, { + "tStartMs": 168360, + "dDurationMs": 4120, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 168370, + "dDurationMs": 7110, + "wWinId": 1, + "segs": [ { + "utf8": "रामचंद्र", + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " काज", + "tOffsetMs": 1480, + "acAsrConf": 229 + }, { + "utf8": " संवारे", + "tOffsetMs": 1990, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 172470, + "dDurationMs": 3010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 172480, + "dDurationMs": 3000, + "wWinId": 1, + "segs": [ { + "utf8": "लाय", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 175990, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 176000, + "dDurationMs": 3920, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 178290, + "dDurationMs": 1630, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 178300, + "dDurationMs": 4200, + "wWinId": 1, + "segs": [ { + "utf8": "सजीवन", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 179910, + "dDurationMs": 2590, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 179920, + "dDurationMs": 4230, + "wWinId": 1, + "segs": [ { + "utf8": "लखन", + "acAsrConf": 229 + }, { + "utf8": " जियाये", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 182490, + "dDurationMs": 1660, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 182500, + "dDurationMs": 3360, + "wWinId": 1, + "segs": [ { + "utf8": "श्रीरघुबीर", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 184140, + "dDurationMs": 1720, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 184150, + "dDurationMs": 3330, + "wWinId": 1, + "segs": [ { + "utf8": "हरषि", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 185850, + "dDurationMs": 1630, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 185860, + "dDurationMs": 3300, + "wWinId": 1, + "segs": [ { + "utf8": "उर", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 187470, + "dDurationMs": 1690, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 187480, + "dDurationMs": 3420, + "wWinId": 1, + "segs": [ { + "utf8": "लाये", + "acAsrConf": 229 + }, { + "utf8": " रघुपति", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 189150, + "dDurationMs": 1750, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 189160, + "dDurationMs": 3900, + "wWinId": 1, + "segs": [ { + "utf8": "कीन्ही", + "acAsrConf": 130 + } ] + }, { + "tStartMs": 190890, + "dDurationMs": 2170, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 190900, + "dDurationMs": 7710, + "wWinId": 1, + "segs": [ { + "utf8": "बहुत", + "acAsrConf": 169 + }, { + "utf8": " बड़ाई", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 193050, + "dDurationMs": 5560, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 193060, + "dDurationMs": 12620, + "wWinId": 1, + "segs": [ { + "utf8": "तुम", + "acAsrConf": 153 + }, { + "utf8": " मम", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " प्रिय", + "tOffsetMs": 1810, + "acAsrConf": 229 + }, { + "utf8": " भरतहि", + "tOffsetMs": 2320, + "acAsrConf": 229 + }, { + "utf8": " सम", + "tOffsetMs": 3150, + "acAsrConf": 229 + }, { + "utf8": " भाई", + "tOffsetMs": 4150, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 198600, + "dDurationMs": 7080, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 198610, + "dDurationMs": 10150, + "wWinId": 1, + "segs": [ { + "utf8": "सहस", + "acAsrConf": 229 + }, { + "utf8": " बदन", + "tOffsetMs": 1140, + "acAsrConf": 229 + }, { + "utf8": " तुम्हरो", + "tOffsetMs": 2140, + "acAsrConf": 229 + }, { + "utf8": " तो", + "tOffsetMs": 3200, + "acAsrConf": 229 + }, { + "utf8": " जज", + "tOffsetMs": 3530, + "acAsrConf": 54 + }, { + "utf8": " का", + "tOffsetMs": 4129, + "acAsrConf": 145 + }, { + "utf8": " या", + "tOffsetMs": 4640, + "acAsrConf": 227 + }, { + "utf8": " वेब", + "tOffsetMs": 5270, + "acAsrConf": 203 + }, { + "utf8": " अस", + "tOffsetMs": 6170, + "acAsrConf": 229 + }, { + "utf8": " कहि", + "tOffsetMs": 6440, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 205670, + "dDurationMs": 3090, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 205680, + "dDurationMs": 4760, + "wWinId": 1, + "segs": [ { + "utf8": "श्रीपति", + "acAsrConf": 229 + }, { + "utf8": " कंठ", + "tOffsetMs": 809, + "acAsrConf": 229 + }, { + "utf8": " लगावैं", + "tOffsetMs": 1590, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 208750, + "dDurationMs": 1690, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 208760, + "dDurationMs": 3510, + "wWinId": 1, + "segs": [ { + "utf8": "सनकादिक", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 210430, + "dDurationMs": 1840, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 210440, + "dDurationMs": 3930, + "wWinId": 1, + "segs": [ { + "utf8": "ब्रह्मादि", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 212260, + "dDurationMs": 2110, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 212270, + "dDurationMs": 7890, + "wWinId": 1, + "segs": [ { + "utf8": "मुनीसा", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 214360, + "dDurationMs": 5800, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 214370, + "dDurationMs": 8490, + "wWinId": 1, + "segs": [ { + "utf8": "नारद", + "acAsrConf": 229 + }, { + "utf8": " सारद", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " सहित", + "tOffsetMs": 2280, + "acAsrConf": 229 + }, { + "utf8": " तरह", + "tOffsetMs": 3449, + "acAsrConf": 225 + }, { + "utf8": " की", + "tOffsetMs": 4449, + "acAsrConf": 168 + } ] + }, { + "tStartMs": 220150, + "dDurationMs": 2710, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 220160, + "dDurationMs": 4980, + "wWinId": 1, + "segs": [ { + "utf8": "डिफ़ाल्ट", + "acAsrConf": 227 + } ] + }, { + "tStartMs": 222850, + "dDurationMs": 2290, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 222860, + "dDurationMs": 9910, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 225130, + "dDurationMs": 7640, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 225140, + "dDurationMs": 15340, + "wWinId": 1, + "segs": [ { + "utf8": "जॉब", + "acAsrConf": 229 + }, { + "utf8": " मे", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " झांक", + "tOffsetMs": 1750, + "acAsrConf": 23 + }, { + "utf8": " पाल", + "tOffsetMs": 2819, + "acAsrConf": 160 + }, { + "utf8": " जहां", + "tOffsetMs": 4200, + "acAsrConf": 212 + }, { + "utf8": " ते", + "tOffsetMs": 5200, + "acAsrConf": 229 + }, { + "utf8": " कबि", + "tOffsetMs": 5679, + "acAsrConf": 158 + }, { + "utf8": " कोबिद", + "tOffsetMs": 6550, + "acAsrConf": 229 + }, { + "utf8": " कहि", + "tOffsetMs": 6670, + "acAsrConf": 153 + } ] + }, { + "tStartMs": 232760, + "dDurationMs": 7720, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 232770, + "dDurationMs": 14420, + "wWinId": 1, + "segs": [ { + "utf8": "सके", + "acAsrConf": 140 + }, { + "utf8": " का", + "tOffsetMs": 920, + "acAsrConf": 145 + }, { + "utf8": " या", + "tOffsetMs": 1920, + "acAsrConf": 135 + }, { + "utf8": " तेल", + "tOffsetMs": 2850, + "acAsrConf": 229 + }, { + "utf8": " कुएं", + "tOffsetMs": 3890, + "acAsrConf": 229 + }, { + "utf8": " कार", + "tOffsetMs": 4890, + "acAsrConf": 99 + }, { + "utf8": " सुशील", + "tOffsetMs": 5780, + "acAsrConf": 190 + }, { + "utf8": " जीवन", + "tOffsetMs": 6780, + "acAsrConf": 229 + }, { + "utf8": " की", + "tOffsetMs": 6900, + "acAsrConf": 218 + } ] + }, { + "tStartMs": 240470, + "dDurationMs": 6720, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 240480, + "dDurationMs": 8330, + "wWinId": 1, + "segs": [ { + "utf8": "मीटिंग", + "acAsrConf": 126 + }, { + "utf8": " हाथ", + "tOffsetMs": 690, + "acAsrConf": 164 + }, { + "utf8": " राम", + "tOffsetMs": 1289, + "acAsrConf": 179 + }, { + "utf8": " मिलाय", + "tOffsetMs": 2119, + "acAsrConf": 210 + }, { + "utf8": " राज", + "tOffsetMs": 3119, + "acAsrConf": 229 + }, { + "utf8": " पद", + "tOffsetMs": 3320, + "acAsrConf": 212 + }, { + "utf8": " प्रति", + "tOffsetMs": 4320, + "acAsrConf": 130 + } ] + }, { + "tStartMs": 247180, + "dDurationMs": 1630, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 247190, + "dDurationMs": 5340, + "wWinId": 1, + "segs": [ { + "utf8": "तुम्हरो", + "acAsrConf": 158 + }, { + "utf8": " मंत्र", + "tOffsetMs": 1000, + "acAsrConf": 147 + } ] + }, { + "tStartMs": 248800, + "dDurationMs": 3730, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 248810, + "dDurationMs": 9959, + "wWinId": 1, + "segs": [ { + "utf8": "विधि", + "acAsrConf": 72 + }, { + "utf8": " क्षण", + "tOffsetMs": 1000, + "acAsrConf": 125 + }, { + "utf8": " माना", + "tOffsetMs": 2069, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 252520, + "dDurationMs": 6249, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 252530, + "dDurationMs": 10210, + "wWinId": 1, + "segs": [ { + "utf8": "लंकेस्वर", + "acAsrConf": 229 + }, { + "utf8": " है", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " अ", + "tOffsetMs": 1840, + "acAsrConf": 204 + }, { + "utf8": " व्यूज", + "tOffsetMs": 2380, + "acAsrConf": 208 + }, { + "utf8": " अ", + "tOffsetMs": 3010, + "acAsrConf": 210 + }, { + "utf8": " अ", + "tOffsetMs": 3160, + "acAsrConf": 190 + }, { + "utf8": " जुग", + "tOffsetMs": 3609, + "acAsrConf": 161 + }, { + "utf8": " जुग", + "tOffsetMs": 4600, + "acAsrConf": 200 + }, { + "utf8": " सहस्त्र", + "tOffsetMs": 5560, + "acAsrConf": 167 + } ] + }, { + "tStartMs": 258759, + "dDurationMs": 3981, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 258769, + "dDurationMs": 8381, + "wWinId": 1, + "segs": [ { + "utf8": "योजन", + "acAsrConf": 151 + }, { + "utf8": " पर", + "tOffsetMs": 1021, + "acAsrConf": 151 + }, { + "utf8": " भानु", + "tOffsetMs": 2021, + "acAsrConf": 141 + }, { + "utf8": " झाल", + "tOffsetMs": 3021, + "acAsrConf": 52 + } ] + }, { + "tStartMs": 262730, + "dDurationMs": 4420, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 262740, + "dDurationMs": 4410, + "wWinId": 1, + "segs": [ { + "utf8": "लील्यो", + "acAsrConf": 170 + }, { + "utf8": " ताहि", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " मधुर", + "tOffsetMs": 1410, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 267320, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 267330, + "dDurationMs": 3000, + "wWinId": 1, + "segs": [ { + "utf8": "धुनें", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 273200, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 273210, + "dDurationMs": 4170, + "wWinId": 1, + "segs": [ { + "utf8": "प्रभु", + "acAsrConf": 229 + }, { + "utf8": " मुद्रिका", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 275720, + "dDurationMs": 1660, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 275730, + "dDurationMs": 4020, + "wWinId": 1, + "segs": [ { + "utf8": "मेलि", + "acAsrConf": 142 + }, { + "utf8": " मुख", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 277370, + "dDurationMs": 2380, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 277380, + "dDurationMs": 5970, + "wWinId": 1, + "segs": [ { + "utf8": "माही", + "acAsrConf": 184 + }, { + "utf8": " जलधि", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 279740, + "dDurationMs": 3610, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 279750, + "dDurationMs": 5340, + "wWinId": 1, + "segs": [ { + "utf8": "लांघि", + "acAsrConf": 191 + }, { + "utf8": " गए", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " अचरज", + "tOffsetMs": 1060, + "acAsrConf": 229 + }, { + "utf8": " नाहीं", + "tOffsetMs": 1950, + "acAsrConf": 218 + } ] + }, { + "tStartMs": 283340, + "dDurationMs": 1750, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 283350, + "dDurationMs": 6600, + "wWinId": 1, + "segs": [ { + "utf8": "दुर्गम", + "acAsrConf": 214 + } ] + }, { + "tStartMs": 285080, + "dDurationMs": 4870, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 285090, + "dDurationMs": 9000, + "wWinId": 1, + "segs": [ { + "utf8": "पास", + "acAsrConf": 141 + }, { + "utf8": " जगत", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1990, + "acAsrConf": 229 + }, { + "utf8": " जेते", + "tOffsetMs": 2640, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 289940, + "dDurationMs": 4150, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 289950, + "dDurationMs": 6060, + "wWinId": 1, + "segs": [ { + "utf8": "शुभेंदु", + "acAsrConf": 229 + }, { + "utf8": " कह", + "tOffsetMs": 1080, + "acAsrConf": 133 + }, { + "utf8": " तुम्हरे", + "tOffsetMs": 2080, + "acAsrConf": 229 + }, { + "utf8": " तेते", + "tOffsetMs": 3040, + "acAsrConf": 185 + } ] + }, { + "tStartMs": 294080, + "dDurationMs": 1930, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 294090, + "dDurationMs": 5700, + "wWinId": 1, + "segs": [ { + "utf8": "राम", + "acAsrConf": 189 + } ] + }, { + "tStartMs": 296000, + "dDurationMs": 3790, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 296010, + "dDurationMs": 8640, + "wWinId": 1, + "segs": [ { + "utf8": "द्वारे", + "acAsrConf": 144 + }, { + "utf8": " तुम", + "tOffsetMs": 1000, + "acAsrConf": 228 + }, { + "utf8": " रखवारे", + "tOffsetMs": 1360, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 299780, + "dDurationMs": 4870, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 299790, + "dDurationMs": 9150, + "wWinId": 1, + "segs": [ { + "utf8": "होत", + "acAsrConf": 205 + }, { + "utf8": " न", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " आज्ञा", + "tOffsetMs": 1300, + "acAsrConf": 229 + }, { + "utf8": " बिनु", + "tOffsetMs": 2200, + "acAsrConf": 229 + }, { + "utf8": " पैसारे", + "tOffsetMs": 2830, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 304640, + "dDurationMs": 4300, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 304650, + "dDurationMs": 6870, + "wWinId": 1, + "segs": [ { + "utf8": "सब", + "acAsrConf": 229 + }, { + "utf8": " सुख", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " लहै", + "tOffsetMs": 1420, + "acAsrConf": 229 + }, { + "utf8": " तुम्हारी", + "tOffsetMs": 2160, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 308930, + "dDurationMs": 2590, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 308940, + "dDurationMs": 6270, + "wWinId": 1, + "segs": [ { + "utf8": "सरना", + "acAsrConf": 229 + }, { + "utf8": " तुम", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 311510, + "dDurationMs": 3700, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 311520, + "dDurationMs": 7190, + "wWinId": 1, + "segs": [ { + "utf8": "रहते", + "acAsrConf": 189 + }, { + "utf8": " कहां", + "tOffsetMs": 1000, + "acAsrConf": 189 + }, { + "utf8": " हो", + "tOffsetMs": 1030, + "acAsrConf": 191 + }, { + "utf8": " खोज", + "tOffsetMs": 1870, + "acAsrConf": 189 + } ] + }, { + "tStartMs": 315200, + "dDurationMs": 3510, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 315210, + "dDurationMs": 7000, + "wWinId": 1, + "segs": [ { + "utf8": "धरना", + "acAsrConf": 188 + }, { + "utf8": " आज", + "tOffsetMs": 1000, + "acAsrConf": 43 + } ] + }, { + "tStartMs": 318700, + "dDurationMs": 3510, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 318710, + "dDurationMs": 6139, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 322200, + "dDurationMs": 2649, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 322210, + "dDurationMs": 9970, + "wWinId": 1, + "segs": [ { + "utf8": "टॉयज", + "acAsrConf": 179 + } ] + }, { + "tStartMs": 324839, + "dDurationMs": 7341, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 324849, + "dDurationMs": 13231, + "wWinId": 1, + "segs": [ { + "utf8": "समारोह", + "acAsrConf": 221 + }, { + "utf8": " पर", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " तीनों", + "tOffsetMs": 1931, + "acAsrConf": 203 + }, { + "utf8": " लोक", + "tOffsetMs": 2880, + "acAsrConf": 229 + }, { + "utf8": " हांक", + "tOffsetMs": 3880, + "acAsrConf": 229 + }, { + "utf8": " ते", + "tOffsetMs": 4410, + "acAsrConf": 214 + }, { + "utf8": " कांपै", + "tOffsetMs": 5611, + "acAsrConf": 229 + }, { + "utf8": " भूत", + "tOffsetMs": 6611, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 332170, + "dDurationMs": 5910, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 332180, + "dDurationMs": 10340, + "wWinId": 1, + "segs": [ { + "utf8": "पिसाच", + "acAsrConf": 229 + }, { + "utf8": " निकट", + "tOffsetMs": 949, + "acAsrConf": 229 + }, { + "utf8": " नहिं", + "tOffsetMs": 2359, + "acAsrConf": 229 + }, { + "utf8": " आवै", + "tOffsetMs": 3359, + "acAsrConf": 229 + }, { + "utf8": " महाबीर", + "tOffsetMs": 3810, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 338070, + "dDurationMs": 4450, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 338080, + "dDurationMs": 6149, + "wWinId": 1, + "segs": [ { + "utf8": "जब", + "acAsrConf": 229 + }, { + "utf8": " नाम", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " सुनावै", + "tOffsetMs": 1589, + "acAsrConf": 208 + }, { + "utf8": " है", + "tOffsetMs": 2640, + "acAsrConf": 96 + } ] + }, { + "tStartMs": 342510, + "dDurationMs": 1719, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 342520, + "dDurationMs": 4619, + "wWinId": 1, + "segs": [ { + "utf8": "नासै", + "acAsrConf": 217 + }, { + "utf8": " रोग", + "tOffsetMs": 1000, + "acAsrConf": 223 + } ] + }, { + "tStartMs": 344219, + "dDurationMs": 2920, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 344229, + "dDurationMs": 5131, + "wWinId": 1, + "segs": [ { + "utf8": "हरे", + "acAsrConf": 229 + }, { + "utf8": " सब", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " पीरा", + "tOffsetMs": 1481, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 347129, + "dDurationMs": 2231, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 347139, + "dDurationMs": 3810, + "wWinId": 1, + "segs": [ { + "utf8": "जपत", + "acAsrConf": 229 + }, { + "utf8": " निरंतर", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 349350, + "dDurationMs": 1599, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 349360, + "dDurationMs": 7739, + "wWinId": 1, + "segs": [ { + "utf8": "हनुमत", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 350939, + "dDurationMs": 6160, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 350949, + "dDurationMs": 6150, + "wWinId": 1, + "segs": [ { + "utf8": "दी", + "acAsrConf": 229 + }, { + "utf8": " रात", + "tOffsetMs": 1291, + "acAsrConf": 26 + }, { + "utf8": " संकट", + "tOffsetMs": 2291, + "acAsrConf": 229 + }, { + "utf8": " ते", + "tOffsetMs": 2981, + "acAsrConf": 229 + }, { + "utf8": " हनुमान", + "tOffsetMs": 3731, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 357480, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 357490, + "dDurationMs": 8130, + "wWinId": 1, + "segs": [ { + "utf8": "छुड़ावै", + "acAsrConf": 229 + }, { + "utf8": " मन", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " क्रम", + "tOffsetMs": 1030, + "acAsrConf": 229 + }, { + "utf8": " बचन", + "tOffsetMs": 1540, + "acAsrConf": 229 + }, { + "utf8": " ध्यान", + "tOffsetMs": 2130, + "acAsrConf": 229 + }, { + "utf8": " जो", + "tOffsetMs": 3130, + "acAsrConf": 229 + }, { + "utf8": " लावै", + "tOffsetMs": 4120, + "acAsrConf": 229 + }, { + "utf8": " सब", + "tOffsetMs": 5130, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 366700, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 366710, + "dDurationMs": 5060, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 368640, + "dDurationMs": 3130, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 368650, + "dDurationMs": 4769, + "wWinId": 1, + "segs": [ { + "utf8": "पर", + "acAsrConf": 229 + }, { + "utf8": " राम", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " तपस्वी", + "tOffsetMs": 1560, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 371760, + "dDurationMs": 1659, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 371770, + "dDurationMs": 10600, + "wWinId": 1, + "segs": [ { + "utf8": "राजा", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 373409, + "dDurationMs": 8961, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 373419, + "dDurationMs": 17351, + "wWinId": 1, + "segs": [ { + "utf8": "तिन", + "acAsrConf": 203 + }, { + "utf8": " के", + "tOffsetMs": 1000, + "acAsrConf": 203 + }, { + "utf8": " काज", + "tOffsetMs": 1481, + "acAsrConf": 229 + }, { + "utf8": " सकल", + "tOffsetMs": 2231, + "acAsrConf": 229 + }, { + "utf8": " तुम", + "tOffsetMs": 3131, + "acAsrConf": 229 + }, { + "utf8": " साजा", + "tOffsetMs": 4120, + "acAsrConf": 229 + }, { + "utf8": " और", + "tOffsetMs": 5220, + "acAsrConf": 229 + }, { + "utf8": " मनोरथ", + "tOffsetMs": 6220, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 382360, + "dDurationMs": 8410, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 382370, + "dDurationMs": 12299, + "wWinId": 1, + "segs": [ { + "utf8": "कुंवारी", + "acAsrConf": 138 + }, { + "utf8": " लावै", + "tOffsetMs": 1049, + "acAsrConf": 229 + }, { + "utf8": " सोइ", + "tOffsetMs": 2049, + "acAsrConf": 229 + }, { + "utf8": " अमित", + "tOffsetMs": 2950, + "acAsrConf": 229 + }, { + "utf8": " जीवन", + "tOffsetMs": 3549, + "acAsrConf": 229 + }, { + "utf8": " फल", + "tOffsetMs": 4890, + "acAsrConf": 229 + }, { + "utf8": " पावै", + "tOffsetMs": 5890, + "acAsrConf": 229 + }, { + "utf8": " चारों", + "tOffsetMs": 6720, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 390760, + "dDurationMs": 3909, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 390770, + "dDurationMs": 5940, + "wWinId": 1, + "segs": [ { + "utf8": "जुग", + "acAsrConf": 229 + }, { + "utf8": " परताप", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " तुम्हारा", + "tOffsetMs": 1710, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 394659, + "dDurationMs": 2051, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 394669, + "dDurationMs": 5970, + "wWinId": 1, + "segs": [ { + "utf8": "है", + "acAsrConf": 229 + }, { + "utf8": " परसिद्ध", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 396700, + "dDurationMs": 3939, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 396710, + "dDurationMs": 8970, + "wWinId": 1, + "segs": [ { + "utf8": "जगत", + "acAsrConf": 229 + }, { + "utf8": " उजियारा", + "tOffsetMs": 1080, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 400629, + "dDurationMs": 5051, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 400639, + "dDurationMs": 10051, + "wWinId": 1, + "segs": [ { + "utf8": "साधु-संत", + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1021, + "acAsrConf": 229 + }, { + "utf8": " तुम", + "tOffsetMs": 2021, + "acAsrConf": 229 + }, { + "utf8": " रखवारे", + "tOffsetMs": 2651, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 405670, + "dDurationMs": 5020, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 405680, + "dDurationMs": 8010, + "wWinId": 1, + "segs": [ { + "utf8": "असुर", + "acAsrConf": 229 + }, { + "utf8": " निकंदन", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " राम", + "tOffsetMs": 1739, + "acAsrConf": 229 + }, { + "utf8": " दुलारे", + "tOffsetMs": 2790, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 410680, + "dDurationMs": 3010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 410690, + "dDurationMs": 3000, + "wWinId": 1, + "segs": [ { + "utf8": "अष्ट", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 414050, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 414060, + "dDurationMs": 3110, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 417340, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 417350, + "dDurationMs": 3750, + "wWinId": 1, + "segs": [ { + "utf8": "सिद्घि", + "acAsrConf": 229 + }, { + "utf8": " नवनिधि", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 418930, + "dDurationMs": 2170, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 418940, + "dDurationMs": 5670, + "wWinId": 1, + "segs": [ { + "utf8": "के", + "acAsrConf": 229 + }, { + "utf8": " दाता", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 421090, + "dDurationMs": 3520, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 421100, + "dDurationMs": 12180, + "wWinId": 1, + "segs": [ { + "utf8": "अस", + "acAsrConf": 229 + }, { + "utf8": " बर", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " दीन", + "tOffsetMs": 1450, + "acAsrConf": 229 + }, { + "utf8": " जानकी", + "tOffsetMs": 1900, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 424600, + "dDurationMs": 8680, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 424610, + "dDurationMs": 12570, + "wWinId": 1, + "segs": [ { + "utf8": "माता", + "acAsrConf": 229 + }, { + "utf8": " राम", + "tOffsetMs": 1350, + "acAsrConf": 229 + }, { + "utf8": " रसायन", + "tOffsetMs": 2430, + "acAsrConf": 229 + }, { + "utf8": " तुम्हरे", + "tOffsetMs": 3809, + "acAsrConf": 229 + }, { + "utf8": " पासा", + "tOffsetMs": 5279, + "acAsrConf": 229 + }, { + "utf8": " सदा", + "tOffsetMs": 6420, + "acAsrConf": 229 + }, { + "utf8": " रहो", + "tOffsetMs": 7559, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 433270, + "dDurationMs": 3910, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 433280, + "dDurationMs": 10000, + "wWinId": 1, + "segs": [ { + "utf8": "रघुपति", + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1230, + "acAsrConf": 229 + }, { + "utf8": " दासा", + "tOffsetMs": 2230, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 437170, + "dDurationMs": 6110, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 437180, + "dDurationMs": 9880, + "wWinId": 1, + "segs": [ { + "utf8": "तुम्हरे", + "acAsrConf": 229 + }, { + "utf8": " भजन", + "tOffsetMs": 1170, + "acAsrConf": 229 + }, { + "utf8": " राम", + "tOffsetMs": 2170, + "acAsrConf": 229 + }, { + "utf8": " को", + "tOffsetMs": 3130, + "acAsrConf": 229 + }, { + "utf8": " पावै", + "tOffsetMs": 3550, + "acAsrConf": 208 + }, { + "utf8": " लुटेरे", + "tOffsetMs": 4610, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 443270, + "dDurationMs": 3790, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 443280, + "dDurationMs": 5640, + "wWinId": 1, + "segs": [ { + "utf8": "जनम-जनम", + "acAsrConf": 229 + }, { + "utf8": " के", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " दुख", + "tOffsetMs": 1690, + "acAsrConf": 229 + }, { + "utf8": " बिसरावै", + "tOffsetMs": 2020, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 447050, + "dDurationMs": 1870, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 447060, + "dDurationMs": 5460, + "wWinId": 1, + "segs": [ { + "utf8": "अंतकाल", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 448910, + "dDurationMs": 3610, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 448920, + "dDurationMs": 6960, + "wWinId": 1, + "segs": [ { + "utf8": "रघुबर", + "acAsrConf": 229 + }, { + "utf8": " पुर", + "tOffsetMs": 1350, + "acAsrConf": 229 + }, { + "utf8": " जाई", + "tOffsetMs": 2350, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 452510, + "dDurationMs": 3370, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 452520, + "dDurationMs": 5940, + "wWinId": 1, + "segs": [ { + "utf8": "जहां", + "acAsrConf": 229 + }, { + "utf8": " जन्म", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " हरि-भक्त", + "tOffsetMs": 1710, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 455870, + "dDurationMs": 2590, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 455880, + "dDurationMs": 4470, + "wWinId": 1, + "segs": [ { + "utf8": "कहाई", + "acAsrConf": 229 + }, { + "utf8": " और", + "tOffsetMs": 1000, + "acAsrConf": 80 + } ] + }, { + "tStartMs": 458450, + "dDurationMs": 1900, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 458460, + "dDurationMs": 4940, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 460340, + "dDurationMs": 3060, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 460350, + "dDurationMs": 3050, + "wWinId": 1, + "segs": [ { + "utf8": "में", + "acAsrConf": 20 + }, { + "utf8": " एक", + "tOffsetMs": 50, + "acAsrConf": 141 + } ] + }, { + "tStartMs": 463450, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 463460, + "dDurationMs": 8580, + "wWinId": 1, + "segs": [ { + "utf8": "बार", + "acAsrConf": 150 + } ] + }, { + "tStartMs": 465220, + "dDurationMs": 6820, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 465230, + "dDurationMs": 11970, + "wWinId": 1, + "segs": [ { + "utf8": "देवता", + "acAsrConf": 229 + }, { + "utf8": " चित्त", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " न", + "tOffsetMs": 1720, + "acAsrConf": 229 + }, { + "utf8": " धरई", + "tOffsetMs": 2380, + "acAsrConf": 229 + }, { + "utf8": " हनुमत", + "tOffsetMs": 2910, + "acAsrConf": 229 + }, { + "utf8": " सेइ", + "tOffsetMs": 4260, + "acAsrConf": 190 + }, { + "utf8": " सर्ब", + "tOffsetMs": 5260, + "acAsrConf": 189 + } ] + }, { + "tStartMs": 472030, + "dDurationMs": 5170, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 472040, + "dDurationMs": 12330, + "wWinId": 1, + "segs": [ { + "utf8": "नुस्खे", + "acAsrConf": 188 + }, { + "utf8": " करई", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " संकट", + "tOffsetMs": 1930, + "acAsrConf": 229 + }, { + "utf8": " कटै", + "tOffsetMs": 2670, + "acAsrConf": 229 + }, { + "utf8": " मिटै", + "tOffsetMs": 3670, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 477190, + "dDurationMs": 7180, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 477200, + "dDurationMs": 9780, + "wWinId": 1, + "segs": [ { + "utf8": "सब", + "acAsrConf": 229 + }, { + "utf8": " पीरा", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " जो", + "tOffsetMs": 1380, + "acAsrConf": 229 + }, { + "utf8": " सुमिरै", + "tOffsetMs": 2380, + "acAsrConf": 229 + }, { + "utf8": " हनुमत", + "tOffsetMs": 3450, + "acAsrConf": 229 + }, { + "utf8": " बलबीरा", + "tOffsetMs": 4650, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 484360, + "dDurationMs": 2620, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 484370, + "dDurationMs": 4140, + "wWinId": 1, + "segs": [ { + "utf8": "जय", + "acAsrConf": 190 + }, { + "utf8": " जय", + "tOffsetMs": 1000, + "acAsrConf": 227 + } ] + }, { + "tStartMs": 486970, + "dDurationMs": 1540, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 486980, + "dDurationMs": 3780, + "wWinId": 1, + "segs": [ { + "utf8": "हनुमान", + "acAsrConf": 152 + } ] + }, { + "tStartMs": 488500, + "dDurationMs": 2260, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 488510, + "dDurationMs": 9040, + "wWinId": 1, + "segs": [ { + "utf8": "गोसाई", + "acAsrConf": 149 + }, { + "utf8": " कृपा", + "tOffsetMs": 1000, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 490750, + "dDurationMs": 6800, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 490760, + "dDurationMs": 16650, + "wWinId": 1, + "segs": [ { + "utf8": "करहु", + "acAsrConf": 229 + }, { + "utf8": " गुरुदेव", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " दत्त", + "tOffsetMs": 1650, + "acAsrConf": 190 + }, { + "utf8": " कि", + "tOffsetMs": 2650, + "acAsrConf": 191 + }, { + "utf8": " आईईए", + "tOffsetMs": 3570, + "acAsrConf": 82 + }, { + "utf8": " जो", + "tOffsetMs": 4570, + "acAsrConf": 229 + }, { + "utf8": " सत", + "tOffsetMs": 5110, + "acAsrConf": 188 + }, { + "utf8": " बार", + "tOffsetMs": 5500, + "acAsrConf": 194 + }, { + "utf8": " पाठ", + "tOffsetMs": 6400, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 497540, + "dDurationMs": 9870, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 497550, + "dDurationMs": 9860, + "wWinId": 1, + "segs": [ { + "utf8": "कर", + "acAsrConf": 229 + }, { + "utf8": " कोई", + "tOffsetMs": 990, + "acAsrConf": 204 + }, { + "utf8": " छूटहि", + "tOffsetMs": 2000, + "acAsrConf": 229 + }, { + "utf8": " बंदि", + "tOffsetMs": 3320, + "acAsrConf": 229 + }, { + "utf8": " महा", + "tOffsetMs": 4320, + "acAsrConf": 229 + }, { + "utf8": " सुख", + "tOffsetMs": 5190, + "acAsrConf": 229 + }, { + "utf8": " होई", + "tOffsetMs": 6180, + "acAsrConf": 179 + }, { + "utf8": " जो", + "tOffsetMs": 6900, + "acAsrConf": 179 + }, { + "utf8": " यह", + "tOffsetMs": 7110, + "acAsrConf": 179 + } ] + }, { + "tStartMs": 508560, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 508570, + "dDurationMs": 7030, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 511300, + "dDurationMs": 4300, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 511310, + "dDurationMs": 11130, + "wWinId": 1, + "segs": [ { + "utf8": "पढ़ै", + "acAsrConf": 180 + }, { + "utf8": " हनुमान", + "tOffsetMs": 1000, + "acAsrConf": 180 + }, { + "utf8": " चल", + "tOffsetMs": 1750, + "acAsrConf": 14 + } ] + }, { + "tStartMs": 515590, + "dDurationMs": 6850, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 515600, + "dDurationMs": 10470, + "wWinId": 1, + "segs": [ { + "utf8": "झाल", + "acAsrConf": 125 + }, { + "utf8": " हुई", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " एक", + "tOffsetMs": 1510, + "acAsrConf": 229 + }, { + "utf8": " साथी", + "tOffsetMs": 2700, + "acAsrConf": 189 + }, { + "utf8": " मज़बूरी", + "tOffsetMs": 3930, + "acAsrConf": 88 + }, { + "utf8": " तक", + "tOffsetMs": 5160, + "acAsrConf": 146 + } ] + }, { + "tStartMs": 522430, + "dDurationMs": 3640, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 522440, + "dDurationMs": 12330, + "wWinId": 1, + "segs": [ { + "utf8": "तुलसीदास", + "acAsrConf": 229 + }, { + "utf8": " सदा", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " हरि", + "tOffsetMs": 1950, + "acAsrConf": 228 + }, { + "utf8": " चेरा", + "tOffsetMs": 2950, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 526060, + "dDurationMs": 8710, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 526070, + "dDurationMs": 14010, + "wWinId": 1, + "segs": [ { + "utf8": "कीजै", + "acAsrConf": 229 + }, { + "utf8": " नाथ", + "tOffsetMs": 1000, + "acAsrConf": 229 + }, { + "utf8": " हृदय", + "tOffsetMs": 1950, + "acAsrConf": 229 + }, { + "utf8": " महं", + "tOffsetMs": 3420, + "acAsrConf": 228 + }, { + "utf8": " डेढ", + "tOffsetMs": 4420, + "acAsrConf": 191 + }, { + "utf8": " इलाका", + "tOffsetMs": 5170, + "acAsrConf": 126 + }, { + "utf8": " कीजै", + "tOffsetMs": 6510, + "acAsrConf": 229 + }, { + "utf8": " नाथ", + "tOffsetMs": 7510, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 534760, + "dDurationMs": 5320, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 534770, + "dDurationMs": 6840, + "wWinId": 1, + "segs": [ { + "utf8": "हृदय", + "acAsrConf": 229 + }, { + "utf8": " और", + "tOffsetMs": 1290, + "acAsrConf": 190 + }, { + "utf8": " महेंद्र", + "tOffsetMs": 2700, + "acAsrConf": 229 + }, { + "utf8": " और", + "tOffsetMs": 3700, + "acAsrConf": 185 + } ] + }, { + "tStartMs": 540070, + "dDurationMs": 1540, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 540080, + "dDurationMs": 4440, + "wWinId": 1, + "segs": [ { + "utf8": "अव्वल", + "acAsrConf": 125 + } ] + }, { + "tStartMs": 541600, + "dDurationMs": 2920, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 541610, + "dDurationMs": 6420, + "wWinId": 1, + "segs": [ { + "utf8": "अल्लाह", + "acAsrConf": 77 + } ] + }, { + "tStartMs": 544510, + "dDurationMs": 3520, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 544520, + "dDurationMs": 6960, + "wWinId": 1, + "segs": [ { + "utf8": "संकट", + "acAsrConf": 218 + }, { + "utf8": " हरण", + "tOffsetMs": 1140, + "acAsrConf": 229 + }, { + "utf8": " मंगल", + "tOffsetMs": 2140, + "acAsrConf": 229 + } ] + }, { + "tStartMs": 548020, + "dDurationMs": 3460, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 548030, + "dDurationMs": 6450, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 551470, + "dDurationMs": 3010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 551480, + "dDurationMs": 3000, + "wWinId": 1, + "segs": [ { + "utf8": "धीमी", + "acAsrConf": 44 + } ] + }, { + "tStartMs": 555140, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 555150, + "dDurationMs": 4820, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + }, { + "tStartMs": 557770, + "dDurationMs": 2200, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 557780, + "dDurationMs": 5730, + "wWinId": 1, + "segs": [ { + "utf8": "रावण", + "acAsrConf": 229 + } ] + }, { + "tStartMs": 559960, + "dDurationMs": 3550, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 559970, + "dDurationMs": 6240, + "wWinId": 1, + "segs": [ { + "utf8": "सिद्घियां", + "acAsrConf": 225 + }, { + "utf8": " रणबीर", + "tOffsetMs": 1350, + "acAsrConf": 104 + } ] + }, { + "tStartMs": 563500, + "dDurationMs": 2710, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 563510, + "dDurationMs": 6700, + "wWinId": 1, + "segs": [ { + "utf8": "विजय", + "acAsrConf": 132 + }, { + "utf8": " भगत", + "tOffsetMs": 1000, + "acAsrConf": 73 + } ] + }, { + "tStartMs": 566200, + "dDurationMs": 4010, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 566210, + "dDurationMs": 4000, + "wWinId": 1, + "segs": [ { + "utf8": "शुरू", + "acAsrConf": 164 + }, { + "utf8": " हो", + "tOffsetMs": 1000, + "acAsrConf": 163 + } ] + }, { + "tStartMs": 570569, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 570579, + "dDurationMs": 2750, + "wWinId": 1, + "segs": [ { + "utf8": "अजय", + "acAsrConf": 14 + }, { + "utf8": " को", + "tOffsetMs": 91, + "acAsrConf": 17 + } ] + }, { + "tStartMs": 573490, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 573500, + "dDurationMs": 3090, + "wWinId": 1, + "segs": [ { + "utf8": "अजय", + "acAsrConf": 14 + }, { + "utf8": " को", + "tOffsetMs": 90, + "acAsrConf": 14 + } ] + }, { + "tStartMs": 580270, + "wWinId": 1, + "aAppend": 1, + "segs": [ { + "utf8": "\n" + } ] + }, { + "tStartMs": 580280, + "dDurationMs": 3139, + "wWinId": 1, + "segs": [ { + "utf8": "[संगीत]" + } ] + } ] +} diff --git a/scripts/chalisa_2.srt b/scripts/chalisa_2.srt new file mode 100644 index 00000000..123bc98b --- /dev/null +++ b/scripts/chalisa_2.srt @@ -0,0 +1,1042 @@ +1 +00:00:00,000 --> 00:09:43,419 + +2 +00:00:00,000 --> 00:00:08,690 +को +3 +00:00:01,360 --> 00:00:08,690 + + +4 +00:00:01,370 --> 00:00:12,740 +अच्छी तरह गुरु चरण सरोज रज निज +5 +00:00:08,680 --> 00:00:12,740 + + +6 +00:00:08,690 --> 00:00:12,740 +मनु मुकुरु सुधारि +7 +00:00:13,930 --> 00:00:13,930 + + +8 +00:00:13,940 --> 00:00:22,170 +बरनउं रघुबर विमल जसु +9 +00:00:18,160 --> 00:00:22,170 + + +10 +00:00:18,170 --> 00:00:22,170 +जो लायक +11 +00:00:22,390 --> 00:00:22,390 + + +12 +00:00:22,400 --> 00:00:27,990 +झाल बीम +13 +00:00:25,150 --> 00:00:27,990 + + +14 +00:00:25,160 --> 00:00:30,199 +बुद्धिहीन तनु जानिके +15 +00:00:27,980 --> 00:00:30,199 + + +16 +00:00:27,990 --> 00:00:34,130 +[हंसी] +17 +00:00:30,189 --> 00:00:34,130 + + +18 +00:00:30,199 --> 00:00:34,130 +सुमिरौं पवन-कुमार +19 +00:00:34,450 --> 00:00:34,450 + + +20 +00:00:34,460 --> 00:00:41,840 +बल +21 +00:00:36,819 --> 00:00:41,840 + + +22 +00:00:36,829 --> 00:00:44,719 +धुंध गार्द देश +23 +00:00:41,830 --> 00:00:44,719 + + +24 +00:00:41,840 --> 00:00:46,910 +मोहनियां अ +25 +00:00:44,709 --> 00:00:46,910 + + +26 +00:00:44,719 --> 00:00:49,520 +करे +27 +00:00:46,900 --> 00:00:49,520 + + +28 +00:00:46,910 --> 00:00:54,739 +बिकता बार +29 +00:00:49,510 --> 00:00:54,739 + + +30 +00:00:49,520 --> 00:00:54,739 +[संगीत] +31 +00:00:55,930 --> 00:00:55,930 + + +32 +00:00:55,940 --> 00:01:07,549 +जय हनुमान ज्ञान गुण सागर +33 +00:01:01,000 --> 00:01:07,549 + + +34 +00:01:01,010 --> 00:01:09,500 +जय कपीस तिहुं लोक तुझ कर +35 +00:01:07,539 --> 00:01:09,500 + + +36 +00:01:07,549 --> 00:01:15,170 +रामदूत अतुलित +37 +00:01:09,490 --> 00:01:15,170 + + +38 +00:01:09,500 --> 00:01:17,330 +बल धामा अंजनि-पुत्र पवनसुत +39 +00:01:15,160 --> 00:01:17,330 + + +40 +00:01:15,170 --> 00:01:21,330 +नामा +41 +00:01:17,320 --> 00:01:21,330 + + +42 +00:01:17,330 --> 00:01:21,330 +मां ने +43 +00:01:21,780 --> 00:01:21,780 + + +44 +00:01:21,790 --> 00:01:26,450 +श्रुति +45 +00:01:23,600 --> 00:01:26,450 + + +46 +00:01:23,610 --> 00:01:27,570 +महाबीर बिक्रम बजरंगी +47 +00:01:26,440 --> 00:01:27,570 + + +48 +00:01:26,450 --> 00:01:32,850 +[संगीत] +49 +00:01:27,560 --> 00:01:32,850 + + +50 +00:01:27,570 --> 00:01:37,740 +कुमति निवार सुमति के संगी +51 +00:01:32,840 --> 00:01:37,740 + + +52 +00:01:32,850 --> 00:01:41,970 +कंचन बरन बिराज सुबेसा +53 +00:01:37,730 --> 00:01:41,970 + + +54 +00:01:37,740 --> 00:01:48,060 +कानन कुंडल कुंचित +55 +00:01:41,960 --> 00:01:48,060 + + +56 +00:01:41,970 --> 00:01:52,350 +के आई हाथ बज्र औ ध्वजा +57 +00:01:48,050 --> 00:01:52,350 + + +58 +00:01:48,060 --> 00:01:55,020 +विराजे कांधे मूंज जनेऊ +59 +00:01:52,340 --> 00:01:55,020 + + +60 +00:01:52,350 --> 00:02:01,620 +साजै संकर +61 +00:01:55,010 --> 00:02:01,620 + + +62 +00:01:55,020 --> 00:02:05,310 +सुवन के तिरछी टू नंदन तेज प्रताप +63 +00:02:01,610 --> 00:02:05,310 + + +64 +00:02:01,620 --> 00:02:08,359 +महा जग बंदन विद्यावान +65 +00:02:05,300 --> 00:02:08,359 + + +66 +00:02:05,310 --> 00:02:08,359 +[संगीत] +67 +00:02:11,840 --> 00:02:11,840 + + +68 +00:02:11,850 --> 00:02:21,970 +गुनी अति चातुर +69 +00:02:15,200 --> 00:02:21,970 + + +70 +00:02:15,210 --> 00:02:29,780 +राम काज करिबे को आतुर प्रभु +71 +00:02:21,960 --> 00:02:29,780 + + +72 +00:02:21,970 --> 00:02:31,630 +पिंपरी सुनिबे को रसिया राम लखन सीता मन +73 +00:02:29,770 --> 00:02:31,630 + + +74 +00:02:29,780 --> 00:02:33,520 +बसिया +75 +00:02:31,620 --> 00:02:33,520 + + +76 +00:02:31,630 --> 00:02:36,640 +सूक्ष्म रूप +77 +00:02:33,510 --> 00:02:36,640 + + +78 +00:02:33,520 --> 00:02:38,410 +धरि सियहि दिखावा +79 +00:02:36,630 --> 00:02:38,410 + + +80 +00:02:36,640 --> 00:02:45,920 +बिकट +81 +00:02:38,400 --> 00:02:45,920 + + +82 +00:02:38,410 --> 00:02:48,370 +दुग्गर लंक जरावा भीम रूप धरि असुर अच्छा +83 +00:02:45,910 --> 00:02:48,370 + + +84 +00:02:45,920 --> 00:02:52,480 +हां रे +85 +00:02:48,360 --> 00:02:52,480 + + +86 +00:02:48,370 --> 00:02:55,480 +रामचंद्र के काज संवारे +87 +00:02:52,470 --> 00:02:55,480 + + +88 +00:02:52,480 --> 00:02:55,480 +लाय +89 +00:02:55,990 --> 00:02:55,990 + + +90 +00:02:56,000 --> 00:02:59,920 +[संगीत] +91 +00:02:58,290 --> 00:02:59,920 + + +92 +00:02:58,300 --> 00:03:02,500 +सजीवन +93 +00:02:59,910 --> 00:03:02,500 + + +94 +00:02:59,920 --> 00:03:04,150 +लखन जियाये +95 +00:03:02,490 --> 00:03:04,150 + + +96 +00:03:02,500 --> 00:03:05,860 +श्रीरघुबीर +97 +00:03:04,140 --> 00:03:05,860 + + +98 +00:03:04,150 --> 00:03:07,480 +हरषि +99 +00:03:05,850 --> 00:03:07,480 + + +100 +00:03:05,860 --> 00:03:09,160 +उर +101 +00:03:07,470 --> 00:03:09,160 + + +102 +00:03:07,480 --> 00:03:10,900 +लाये रघुपति +103 +00:03:09,150 --> 00:03:10,900 + + +104 +00:03:09,160 --> 00:03:13,060 +कीन्ही +105 +00:03:10,890 --> 00:03:13,060 + + +106 +00:03:10,900 --> 00:03:18,610 +बहुत बड़ाई +107 +00:03:13,050 --> 00:03:18,610 + + +108 +00:03:13,060 --> 00:03:25,680 +तुम मम प्रिय भरतहि सम भाई +109 +00:03:18,600 --> 00:03:25,680 + + +110 +00:03:18,610 --> 00:03:28,760 +सहस बदन तुम्हरो तो जज का या वेब अस कहि +111 +00:03:25,670 --> 00:03:28,760 + + +112 +00:03:25,680 --> 00:03:30,440 +श्रीपति कंठ लगावैं +113 +00:03:28,750 --> 00:03:30,440 + + +114 +00:03:28,760 --> 00:03:32,270 +सनकादिक +115 +00:03:30,430 --> 00:03:32,270 + + +116 +00:03:30,440 --> 00:03:34,370 +ब्रह्मादि +117 +00:03:32,260 --> 00:03:34,370 + + +118 +00:03:32,270 --> 00:03:40,160 +मुनीसा +119 +00:03:34,360 --> 00:03:40,160 + + +120 +00:03:34,370 --> 00:03:42,860 +नारद सारद सहित तरह की +121 +00:03:40,150 --> 00:03:42,860 + + +122 +00:03:40,160 --> 00:03:45,140 +डिफ़ाल्ट +123 +00:03:42,850 --> 00:03:45,140 + + +124 +00:03:42,860 --> 00:03:52,770 +[संगीत] +125 +00:03:45,130 --> 00:03:52,770 + + +126 +00:03:45,140 --> 00:04:00,480 +जॉब मे झांक पाल जहां ते कबि कोबिद कहि +127 +00:03:52,760 --> 00:04:00,480 + + +128 +00:03:52,770 --> 00:04:07,190 +सके का या तेल कुएं कार सुशील जीवन की +129 +00:04:00,470 --> 00:04:07,190 + + +130 +00:04:00,480 --> 00:04:08,810 +मीटिंग हाथ राम मिलाय राज पद प्रति +131 +00:04:07,180 --> 00:04:08,810 + + +132 +00:04:07,190 --> 00:04:12,530 +तुम्हरो मंत्र +133 +00:04:08,800 --> 00:04:12,530 + + +134 +00:04:08,810 --> 00:04:18,769 +विधि क्षण माना +135 +00:04:12,520 --> 00:04:18,769 + + +136 +00:04:12,530 --> 00:04:22,740 +लंकेस्वर है अ व्यूज अ अ जुग जुग सहस्त्र +137 +00:04:18,759 --> 00:04:22,740 + + +138 +00:04:18,769 --> 00:04:27,150 +योजन पर भानु झाल +139 +00:04:22,730 --> 00:04:27,150 + + +140 +00:04:22,740 --> 00:04:27,150 +लील्यो ताहि मधुर +141 +00:04:27,320 --> 00:04:27,320 + + +142 +00:04:27,330 --> 00:04:30,330 +धुनें +143 +00:04:33,200 --> 00:04:33,200 + + +144 +00:04:33,210 --> 00:04:37,380 +प्रभु मुद्रिका +145 +00:04:35,720 --> 00:04:37,380 + + +146 +00:04:35,730 --> 00:04:39,750 +मेलि मुख +147 +00:04:37,370 --> 00:04:39,750 + + +148 +00:04:37,380 --> 00:04:43,350 +माही जलधि +149 +00:04:39,740 --> 00:04:43,350 + + +150 +00:04:39,750 --> 00:04:45,090 +लांघि गए अचरज नाहीं +151 +00:04:43,340 --> 00:04:45,090 + + +152 +00:04:43,350 --> 00:04:49,950 +दुर्गम +153 +00:04:45,080 --> 00:04:49,950 + + +154 +00:04:45,090 --> 00:04:54,090 +पास जगत के जेते +155 +00:04:49,940 --> 00:04:54,090 + + +156 +00:04:49,950 --> 00:04:56,010 +शुभेंदु कह तुम्हरे तेते +157 +00:04:54,080 --> 00:04:56,010 + + +158 +00:04:54,090 --> 00:04:59,790 +राम +159 +00:04:56,000 --> 00:04:59,790 + + +160 +00:04:56,010 --> 00:05:04,650 +द्वारे तुम रखवारे +161 +00:04:59,780 --> 00:05:04,650 + + +162 +00:04:59,790 --> 00:05:08,940 +होत न आज्ञा बिनु पैसारे +163 +00:05:04,640 --> 00:05:08,940 + + +164 +00:05:04,650 --> 00:05:11,520 +सब सुख लहै तुम्हारी +165 +00:05:08,930 --> 00:05:11,520 + + +166 +00:05:08,940 --> 00:05:15,210 +सरना तुम +167 +00:05:11,510 --> 00:05:15,210 + + +168 +00:05:11,520 --> 00:05:18,710 +रहते कहां हो खोज +169 +00:05:15,200 --> 00:05:18,710 + + +170 +00:05:15,210 --> 00:05:22,210 +धरना आज +171 +00:05:18,700 --> 00:05:22,210 + + +172 +00:05:18,710 --> 00:05:24,849 +[संगीत] +173 +00:05:22,200 --> 00:05:24,849 + + +174 +00:05:22,210 --> 00:05:32,180 +टॉयज +175 +00:05:24,839 --> 00:05:32,180 + + +176 +00:05:24,849 --> 00:05:38,080 +समारोह पर तीनों लोक हांक ते कांपै भूत +177 +00:05:32,170 --> 00:05:38,080 + + +178 +00:05:32,180 --> 00:05:42,520 +पिसाच निकट नहिं आवै महाबीर +179 +00:05:38,070 --> 00:05:42,520 + + +180 +00:05:38,080 --> 00:05:44,229 +जब नाम सुनावै है +181 +00:05:42,510 --> 00:05:44,229 + + +182 +00:05:42,520 --> 00:05:47,139 +नासै रोग +183 +00:05:44,219 --> 00:05:47,139 + + +184 +00:05:44,229 --> 00:05:49,360 +हरे सब पीरा +185 +00:05:47,129 --> 00:05:49,360 + + +186 +00:05:47,139 --> 00:05:50,949 +जपत निरंतर +187 +00:05:49,350 --> 00:05:50,949 + + +188 +00:05:49,360 --> 00:05:57,099 +हनुमत +189 +00:05:50,939 --> 00:05:57,099 + + +190 +00:05:50,949 --> 00:05:57,099 +दी रात संकट ते हनुमान +191 +00:05:57,480 --> 00:05:57,480 + + +192 +00:05:57,490 --> 00:06:05,620 +छुड़ावै मन क्रम बचन ध्यान जो लावै सब +193 +00:06:06,700 --> 00:06:06,700 + + +194 +00:06:06,710 --> 00:06:11,770 +[संगीत] +195 +00:06:08,640 --> 00:06:11,770 + + +196 +00:06:08,650 --> 00:06:13,419 +पर राम तपस्वी +197 +00:06:11,760 --> 00:06:13,419 + + +198 +00:06:11,770 --> 00:06:22,370 +राजा +199 +00:06:13,409 --> 00:06:22,370 + + +200 +00:06:13,419 --> 00:06:30,770 +तिन के काज सकल तुम साजा और मनोरथ +201 +00:06:22,360 --> 00:06:30,770 + + +202 +00:06:22,370 --> 00:06:34,669 +कुंवारी लावै सोइ अमित जीवन फल पावै चारों +203 +00:06:30,760 --> 00:06:34,669 + + +204 +00:06:30,770 --> 00:06:36,710 +जुग परताप तुम्हारा +205 +00:06:34,659 --> 00:06:36,710 + + +206 +00:06:34,669 --> 00:06:40,639 +है परसिद्ध +207 +00:06:36,700 --> 00:06:40,639 + + +208 +00:06:36,710 --> 00:06:45,680 +जगत उजियारा +209 +00:06:40,629 --> 00:06:45,680 + + +210 +00:06:40,639 --> 00:06:50,690 +साधु-संत के तुम रखवारे +211 +00:06:45,670 --> 00:06:50,690 + + +212 +00:06:45,680 --> 00:06:53,690 +असुर निकंदन राम दुलारे +213 +00:06:50,680 --> 00:06:53,690 + + +214 +00:06:50,690 --> 00:06:53,690 +अष्ट +215 +00:06:54,050 --> 00:06:54,050 + + +216 +00:06:54,060 --> 00:06:57,170 +[संगीत] +217 +00:06:57,340 --> 00:06:57,340 + + +218 +00:06:57,350 --> 00:07:01,100 +सिद्घि नवनिधि +219 +00:06:58,930 --> 00:07:01,100 + + +220 +00:06:58,940 --> 00:07:04,610 +के दाता +221 +00:07:01,090 --> 00:07:04,610 + + +222 +00:07:01,100 --> 00:07:13,280 +अस बर दीन जानकी +223 +00:07:04,600 --> 00:07:13,280 + + +224 +00:07:04,610 --> 00:07:17,180 +माता राम रसायन तुम्हरे पासा सदा रहो +225 +00:07:13,270 --> 00:07:17,180 + + +226 +00:07:13,280 --> 00:07:23,280 +रघुपति के दासा +227 +00:07:17,170 --> 00:07:23,280 + + +228 +00:07:17,180 --> 00:07:27,060 +तुम्हरे भजन राम को पावै लुटेरे +229 +00:07:23,270 --> 00:07:27,060 + + +230 +00:07:23,280 --> 00:07:28,920 +जनम-जनम के दुख बिसरावै +231 +00:07:27,050 --> 00:07:28,920 + + +232 +00:07:27,060 --> 00:07:32,520 +अंतकाल +233 +00:07:28,910 --> 00:07:32,520 + + +234 +00:07:28,920 --> 00:07:35,880 +रघुबर पुर जाई +235 +00:07:32,510 --> 00:07:35,880 + + +236 +00:07:32,520 --> 00:07:38,460 +जहां जन्म हरि-भक्त +237 +00:07:35,870 --> 00:07:38,460 + + +238 +00:07:35,880 --> 00:07:40,350 +कहाई और +239 +00:07:38,450 --> 00:07:40,350 + + +240 +00:07:38,460 --> 00:07:43,400 +[संगीत] +241 +00:07:40,340 --> 00:07:43,400 + + +242 +00:07:40,350 --> 00:07:43,400 +में एक +243 +00:07:43,450 --> 00:07:43,450 + + +244 +00:07:43,460 --> 00:07:52,040 +बार +245 +00:07:45,220 --> 00:07:52,040 + + +246 +00:07:45,230 --> 00:07:57,200 +देवता चित्त न धरई हनुमत सेइ सर्ब +247 +00:07:52,030 --> 00:07:57,200 + + +248 +00:07:52,040 --> 00:08:04,370 +नुस्खे करई संकट कटै मिटै +249 +00:07:57,190 --> 00:08:04,370 + + +250 +00:07:57,200 --> 00:08:06,980 +सब पीरा जो सुमिरै हनुमत बलबीरा +251 +00:08:04,360 --> 00:08:06,980 + + +252 +00:08:04,370 --> 00:08:08,510 +जय जय +253 +00:08:06,970 --> 00:08:08,510 + + +254 +00:08:06,980 --> 00:08:10,760 +हनुमान +255 +00:08:08,500 --> 00:08:10,760 + + +256 +00:08:08,510 --> 00:08:17,550 +गोसाई कृपा +257 +00:08:10,750 --> 00:08:17,550 + + +258 +00:08:10,760 --> 00:08:27,410 +करहु गुरुदेव दत्त कि आईईए जो सत बार पाठ +259 +00:08:17,540 --> 00:08:27,410 + + +260 +00:08:17,550 --> 00:08:27,410 +कर कोई छूटहि बंदि महा सुख होई जो यह +261 +00:08:28,560 --> 00:08:28,560 + + +262 +00:08:28,570 --> 00:08:35,600 +[संगीत] +263 +00:08:31,300 --> 00:08:35,600 + + +264 +00:08:31,310 --> 00:08:42,440 +पढ़ै हनुमान चल +265 +00:08:35,590 --> 00:08:42,440 + + +266 +00:08:35,600 --> 00:08:46,070 +झाल हुई एक साथी मज़बूरी तक +267 +00:08:42,430 --> 00:08:46,070 + + +268 +00:08:42,440 --> 00:08:54,770 +तुलसीदास सदा हरि चेरा +269 +00:08:46,060 --> 00:08:54,770 + + +270 +00:08:46,070 --> 00:09:00,080 +कीजै नाथ हृदय महं डेढ इलाका कीजै नाथ +271 +00:08:54,760 --> 00:09:00,080 + + +272 +00:08:54,770 --> 00:09:01,610 +हृदय और महेंद्र और +273 +00:09:00,070 --> 00:09:01,610 + + +274 +00:09:00,080 --> 00:09:04,520 +अव्वल +275 +00:09:01,600 --> 00:09:04,520 + + +276 +00:09:01,610 --> 00:09:08,030 +अल्लाह +277 +00:09:04,510 --> 00:09:08,030 + + +278 +00:09:04,520 --> 00:09:11,480 +संकट हरण मंगल +279 +00:09:08,020 --> 00:09:11,480 + + +280 +00:09:08,030 --> 00:09:14,480 +[संगीत] +281 +00:09:11,470 --> 00:09:14,480 + + +282 +00:09:11,480 --> 00:09:14,480 +धीमी +283 +00:09:15,140 --> 00:09:15,140 + + +284 +00:09:15,150 --> 00:09:19,970 +[संगीत] +285 +00:09:17,770 --> 00:09:19,970 + + +286 +00:09:17,780 --> 00:09:23,510 +रावण +287 +00:09:19,960 --> 00:09:23,510 + + +288 +00:09:19,970 --> 00:09:26,210 +सिद्घियां रणबीर +289 +00:09:23,500 --> 00:09:26,210 + + +290 +00:09:23,510 --> 00:09:30,210 +विजय भगत +291 +00:09:26,200 --> 00:09:30,210 + + +292 +00:09:26,210 --> 00:09:30,210 +शुरू हो +293 +00:09:30,569 --> 00:09:30,569 + + +294 +00:09:30,579 --> 00:09:33,329 +अजय को +295 +00:09:33,490 --> 00:09:33,490 + + +296 +00:09:33,500 --> 00:09:36,590 +अजय को +297 +00:09:40,270 --> 00:09:40,270 + + +298 +00:09:40,280 --> 00:09:43,419 +[संगीत] diff --git a/scripts/chalisa_mapping_v1.json b/scripts/chalisa_mapping_v1.json new file mode 100644 index 00000000..beb523cb --- /dev/null +++ b/scripts/chalisa_mapping_v1.json @@ -0,0 +1,865 @@ +{ + "text": "hanuman chalisa", + "mappings": [ + { + "is_exact_match": false, + "verse_count": 1, + "caption_event_num": 8, + "similarity": 0.5447024979066774, + "verse": { + "count": 1, + "transliteration": "śrīguru carana saroja raja nija manu mukuru sudhāri .\n\nbaranaüm̐ raghubara bimala jasu jo dāyaku phala cāri ..", + "text": "श्रीगुरु चरन सरोज रज निज मनु मुकुरु सुधारि ।\n\nबरनउँ रघुबर बिमल जसु जो दायकु फल चारि ॥", + "meaning": "Having polished the mirror of my heart with the dust of my Guru’s lotus feet, I recite the divine fame of the greatest king of Raghukul dynasty, which bestows us with the fruit of all the four efforts." + }, + "caption": { + "event_num": 8, + "text": "बरनउं रघुबर विमल जसु", + "is_empty": false, + "start_ms": 13940, + "end_ms": 22170, + "duration_ms": 8230 + } + }, + { + "is_exact_match": false, + "verse_count": 2, + "caption_event_num": 20, + "similarity": 0.33517574332792605, + "verse": { + "count": 2, + "transliteration": "buddhihīna tanu jānike sumirauṃ pavana-kumāra .\n\nbala budhi bidyā dehu mohiṃ harahu kalesa bikāra ..", + "text": "बुद्धिहीन तनु जानिके सुमिरौं पवन-कुमार ।\n\nबल बुधि बिद्या देहु मोहिं हरहु कलेस बिकार ॥", + "meaning": "Knowing that this mind of mine has less intelligence, I remember the ‘Son of Wind’ who, granting me strength, wisdom and all kinds of knowledge, removes all my suffering and shortcomings." + }, + "caption": { + "event_num": 20, + "text": "बल", + "is_empty": false, + "start_ms": 34460, + "end_ms": 41840, + "duration_ms": 7380 + } + }, + { + "is_exact_match": false, + "verse_count": 3, + "caption_event_num": 32, + "similarity": 0.8021643431066532, + "verse": { + "count": 3, + "transliteration": "jaya hanumāna jñāna guna sāgara .\n\njaya kapīsa tihum̐ loka ujāgara ..1..", + "text": "॥चौपाई॥\n\nजय हनुमान ज्ञान गुन सागर ।\n\nजय कपीस तिहुँ लोक उजागर ॥१॥", + "meaning": "Victory to Lord Hanuman, the ocean of wisdom and virtue. Victory to the Lord who is supreme among the monkeys, illuminator of the three worlds." + }, + "caption": { + "event_num": 32, + "text": "जय हनुमान ज्ञान गुण सागर", + "is_empty": false, + "start_ms": 55940, + "end_ms": 67549, + "duration_ms": 11609 + } + }, + { + "is_exact_match": false, + "verse_count": 4, + "caption_event_num": 38, + "similarity": 0.6569729210330907, + "verse": { + "count": 4, + "transliteration": "rāma dūta atulita bala dhāmā .\n\nañjani-putra pavanasuta nāmā ..2..", + "text": "राम दूत अतुलित बल धामा ।\n\nअञ्जनि-पुत्र पवनसुत नामा ॥२॥", + "meaning": "you are Lord Rama’s emissary,‌ the abode of matchless power, Mother Anjani’s son and also popular as the ‘Son of the Wind’." + }, + "caption": { + "event_num": 38, + "text": "बल धामा अंजनि-पुत्र पवनसुत", + "is_empty": false, + "start_ms": 69500, + "end_ms": 77330, + "duration_ms": 7830 + } + }, + { + "is_exact_match": false, + "verse_count": 5, + "caption_event_num": 50, + "similarity": 0.5797386715376658, + "verse": { + "count": 5, + "transliteration": "mahābīra bikrama bajaraṅgī .\n\nkumati nivāra sumati ke saṅgī ..3..", + "text": "महाबीर बिक्रम बजरङ्गी ।\n\nकुमति निवार सुमति के सङ्गी ॥३॥", + "meaning": "Great hero, you are as mighty as a thunderbolt. you remove evil intellect and are the companion of those having good ones." + }, + "caption": { + "event_num": 50, + "text": "कुमति निवार सुमति के संगी", + "is_empty": false, + "start_ms": 87570, + "end_ms": 97740, + "duration_ms": 10170 + } + }, + { + "is_exact_match": false, + "verse_count": 6, + "caption_event_num": 54, + "similarity": 0.5023287782256718, + "verse": { + "count": 6, + "transliteration": "kañcana barana birāja subesā .\n\nkānana kuṇḍala kuñcita kesā ..4..", + "text": "कञ्चन बरन बिराज सुबेसा ।\n\nकानन कुण्डल कुञ्चित केसा ॥४॥", + "meaning": "your skin is golden in color and you are adorned with beautiful clothes. you have adorning earrings in your ears and your hair is curly and thick." + }, + "caption": { + "event_num": 54, + "text": "कानन कुंडल कुंचित", + "is_empty": false, + "start_ms": 97740, + "end_ms": 108060, + "duration_ms": 10320 + } + }, + { + "is_exact_match": false, + "verse_count": 7, + "caption_event_num": 56, + "similarity": 0.5031026124151314, + "verse": { + "count": 7, + "transliteration": "hātha bajra au dhvajā birājai .\n\nkām̐dhe mūm̐ja janeu sājai ..5..", + "text": "हाथ बज्र औ ध्वजा बिराजै ।\n\nकाँधे मूँज जनेउ साजै ॥५॥", + "meaning": "In your hands, shine a mace and a flag of righteousness. A sacred thread adorns your right shoulder." + }, + "caption": { + "event_num": 56, + "text": "के आई हाथ बज्र औ ध्वजा", + "is_empty": false, + "start_ms": 101970, + "end_ms": 112350, + "duration_ms": 10380 + } + }, + { + "is_exact_match": false, + "verse_count": 8, + "caption_event_num": 64, + "similarity": 0.5186415412370031, + "verse": { + "count": 8, + "transliteration": "saṅkara suvana kesarīnandana .\n\nteja pratāpa mahā jaga bandana ..6..", + "text": "सङ्कर सुवन केसरीनन्दन ।\n\nतेज प्रताप महा जग बन्दन ॥६॥", + "meaning": "You are the embodiment of Lord Shiva and vanar-raj Kesari’s son. There is no limit or end to your glory, your magnificence. The whole universe worships you." + }, + "caption": { + "event_num": 64, + "text": "महा जग बंदन विद्यावान", + "is_empty": false, + "start_ms": 121620, + "end_ms": 128359, + "duration_ms": 6739 + } + }, + { + "is_exact_match": false, + "verse_count": 9, + "caption_event_num": 70, + "similarity": 0.5031026124151314, + "verse": { + "count": 9, + "transliteration": "bidyāvāna gunī ati cātura .\n\nrāma kāja karibe ko ātura ..7..", + "text": "बिद्यावान गुनी अति चातुर ।\n\nराम काज करिबे को आतुर ॥७॥", + "meaning": "You are the wisest of the wise, virtuous and (morally) clever. You are always eager to do Lord Rama’s works." + }, + "caption": { + "event_num": 70, + "text": "राम काज करिबे को आतुर प्रभु", + "is_empty": false, + "start_ms": 135210, + "end_ms": 149780, + "duration_ms": 14570 + } + }, + { + "is_exact_match": false, + "verse_count": 10, + "caption_event_num": 72, + "similarity": 0.4501755023269898, + "verse": { + "count": 10, + "transliteration": "prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..", + "text": "प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥", + "meaning": "You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart." + }, + "caption": { + "event_num": 72, + "text": "पिंपरी सुनिबे को रसिया राम लखन सीता मन", + "is_empty": false, + "start_ms": 141970, + "end_ms": 151630, + "duration_ms": 9660 + } + }, + { + "is_exact_match": false, + "verse_count": 11, + "caption_event_num": 78, + "similarity": 0.641764556549105, + "verse": { + "count": 11, + "transliteration": "sūkṣma rūpa dhari siyahiṃ dikhāvā .\n\nbikaṭa rūpa dhari laṅka jarāvā ..9..", + "text": "सूक्ष्म रूप धरि सियहिं दिखावा ।\n\nबिकट रूप धरि लङ्क जरावा ॥९॥", + "meaning": "Taking the subtle form, you appeared in front of Mother Sita. And, taking the formidable form, you burnt the Lanka (Ravana’s kingdom)." + }, + "caption": { + "event_num": 78, + "text": "धरि सियहि दिखावा", + "is_empty": false, + "start_ms": 153520, + "end_ms": 158410, + "duration_ms": 4890 + } + }, + { + "is_exact_match": false, + "verse_count": 12, + "caption_event_num": 82, + "similarity": 0.2912194185636897, + "verse": { + "count": 12, + "transliteration": "bhīma rūpa dhari asura sam̐hāre .\n\nrāmacandra ke kāja sam̐vāre ..10..", + "text": "भीम रूप धरि असुर सँहारे ।\n\nरामचन्द्र के काज सँवारे ॥१०॥", + "meaning": "Taking the massive form (like that of Bheema), you slaughtered the demons. This is how, you completed Lord Rama’s tasks, successfully." + }, + "caption": { + "event_num": 82, + "text": "दुग्गर लंक जरावा भीम रूप धरि असुर अच्छा", + "is_empty": false, + "start_ms": 158410, + "end_ms": 168370, + "duration_ms": 9960 + } + }, + { + "is_exact_match": false, + "verse_count": 13, + "caption_event_num": 100, + "similarity": 0.2789425453258252, + "verse": { + "count": 13, + "transliteration": "lāya sañjīvana lakhana jiyāye .\n\nśrīraghubīra haraṣi ura lāye ..11..", + "text": "लाय सञ्जीवन लखन जियाये ।\n\nश्रीरघुबीर हरषि उर लाये ॥११॥", + "meaning": "Bringing the magic-herb (sanjivani), you revived Lord Laxmana." + }, + "caption": { + "event_num": 100, + "text": "उर", + "is_empty": false, + "start_ms": 185860, + "end_ms": 189160, + "duration_ms": 3300 + } + }, + { + "is_exact_match": false, + "verse_count": 14, + "caption_event_num": 108, + "similarity": 0.4826796606496646, + "verse": { + "count": 14, + "transliteration": "raghupati kīhnī bahuta bar̤āī .\n\ntuma mama priya bharatahi sama bhāī ..12..", + "text": "रघुपति कीह्नी बहुत बड़ाई ।\n\nतुम मम प्रिय भरतहि सम भाई ॥१२॥", + "meaning": "Raghupati, Lord Rama praised you greatly and overflowing in gratitude, said that you are a dear brother to him just as Bharat is." + }, + "caption": { + "event_num": 108, + "text": "तुम मम प्रिय भरतहि सम भाई", + "is_empty": false, + "start_ms": 193060, + "end_ms": 205680, + "duration_ms": 12620 + } + }, + { + "is_exact_match": false, + "verse_count": 15, + "caption_event_num": 110, + "similarity": 0.38081653297711143, + "verse": { + "count": 15, + "transliteration": "sahasa badana tuhmāro jasa gāvaiṃ .\n\nasa kahi śrīpati kaṇṭha lagāvaiṃ ..13..", + "text": "सहस बदन तुह्मारो जस गावैं ।\n\nअस कहि श्रीपति कण्ठ लगावैं ॥१३॥", + "meaning": "Saying this, Lord Rama drew you to himself and embraced you. Sages like Sanaka, Gods like Brahma and sages like Narada and even the thousand-mouthed serpent sing your fame!" + }, + "caption": { + "event_num": 110, + "text": "सहस बदन तुम्हरो तो जज का या वेब अस कहि", + "is_empty": false, + "start_ms": 198610, + "end_ms": 208760, + "duration_ms": 10150 + } + }, + { + "is_exact_match": false, + "verse_count": 16, + "caption_event_num": 120, + "similarity": 0.5270724758293458, + "verse": { + "count": 16, + "transliteration": "sanakādika brahmādi munīsā .\n\nnārada sārada sahita ahīsā ..14..", + "text": "सनकादिक ब्रह्मादि मुनीसा ।\n\nनारद सारद सहित अहीसा ॥१४॥", + "meaning": "Sanak, Sanandan and the other Rishis and great saints; Brahma – the god, Narada, Saraswati – the Mother Divine and the King of serpents sing your glory." + }, + "caption": { + "event_num": 120, + "text": "नारद सारद सहित तरह की", + "is_empty": false, + "start_ms": 214370, + "end_ms": 222860, + "duration_ms": 8490 + } + }, + { + "is_exact_match": false, + "verse_count": 17, + "caption_event_num": 126, + "similarity": 0.6194000100245768, + "verse": { + "count": 17, + "transliteration": "jama kubera digapāla jahām̐ te .\n\nkabi kobida kahi sake kahām̐ te ..15..", + "text": "जम कुबेर दिगपाल जहाँ ते ।\n\nकबि कोबिद कहि सके कहाँ ते ॥१५॥", + "meaning": "Yama, Kubera and the guardians of the four quarters; poets and scholars – none can express your glory." + }, + "caption": { + "event_num": 126, + "text": "जॉब मे झांक पाल जहां ते कबि कोबिद कहि", + "is_empty": false, + "start_ms": 225140, + "end_ms": 240480, + "duration_ms": 15340 + } + }, + { + "is_exact_match": false, + "verse_count": 18, + "caption_event_num": 130, + "similarity": 0.22028815056182974, + "verse": { + "count": 18, + "transliteration": "tuma upakāra sugrīvahiṃ kīhnā .\n\nrāma milāya rāja pada dīhnā ..16..", + "text": "तुम उपकार सुग्रीवहिं कीह्ना ।\n\nराम मिलाय राज पद दीह्ना ॥१६॥", + "meaning": "You helped Sugriva by introducing him to Lord Rama and regaining his crown. Therefore, you gave him the Kingship (the dignity of being called a king)." + }, + "caption": { + "event_num": 130, + "text": "मीटिंग हाथ राम मिलाय राज पद प्रति", + "is_empty": false, + "start_ms": 240480, + "end_ms": 248810, + "duration_ms": 8330 + } + }, + { + "is_exact_match": false, + "verse_count": 19, + "caption_event_num": 6, + "similarity": 0.24395572500006343, + "verse": { + "count": 19, + "transliteration": "tuhmaro mantra bibhīṣana mānā .\n\nlaṅkesvara bhae saba jaga jānā ..17..", + "text": "तुह्मरो मन्त्र बिभीषन माना ।\n\nलङ्केस्वर भए सब जग जाना ॥१७॥", + "meaning": "Likewise, complying with your preachings, even Vibhishana became the King of Lanka." + }, + "caption": { + "event_num": 6, + "text": "मनु मुकुरु सुधारि", + "is_empty": false, + "start_ms": 8690, + "end_ms": 12740, + "duration_ms": 4050 + } + }, + { + "is_exact_match": false, + "verse_count": 20, + "caption_event_num": 138, + "similarity": 0.4494364165239822, + "verse": { + "count": 20, + "transliteration": "juga sahasra jojana para bhānu .\n\nlīlyo tāhi madhura phala jānū ..18..", + "text": "जुग सहस्र जोजन पर भानु ।\n\nलील्यो ताहि मधुर फल जानू ॥१८॥", + "meaning": "You swallowed the sun, located thousands of miles away, mistaking it to be a sweet, red fruit!" + }, + "caption": { + "event_num": 138, + "text": "योजन पर भानु झाल", + "is_empty": false, + "start_ms": 258769, + "end_ms": 267150, + "duration_ms": 8381 + } + }, + { + "is_exact_match": false, + "verse_count": 21, + "caption_event_num": 148, + "similarity": 0.33517574332792605, + "verse": { + "count": 21, + "transliteration": "prabhu mudrikā meli mukha māhīṃ .\n\njaladhi lām̐ghi gaye acaraja nāhīṃ ..19..", + "text": "प्रभु मुद्रिका मेलि मुख माहीं ।\n\nजलधि लाँघि गये अचरज नाहीं ॥१९॥", + "meaning": "Keeping the ring in your mouth, which was given to you by Lord Rama, you crossed over the ocean, to no astonishment, whatsoever." + }, + "caption": { + "event_num": 148, + "text": "माही जलधि", + "is_empty": false, + "start_ms": 277380, + "end_ms": 283350, + "duration_ms": 5970 + } + }, + { + "is_exact_match": false, + "verse_count": 22, + "caption_event_num": 152, + "similarity": 0.5368927118515179, + "verse": { + "count": 22, + "transliteration": "durgama kāja jagata ke jete .\n\nsugama anugraha tuhmare tete ..20..", + "text": "दुर्गम काज जगत के जेते ।\n\nसुगम अनुग्रह तुह्मरे तेते ॥२०॥", + "meaning": "All difficult tasks of this world become easy, with your grace." + }, + "caption": { + "event_num": 152, + "text": "दुर्गम", + "is_empty": false, + "start_ms": 283350, + "end_ms": 289950, + "duration_ms": 6600 + } + }, + { + "is_exact_match": false, + "verse_count": 23, + "caption_event_num": 210, + "similarity": 0.3799783615910079, + "verse": { + "count": 23, + "transliteration": "rāma duāre tuma rakhavāre .\n\nhota na ājñā binu paisāre ..21..", + "text": "राम दुआरे तुम रखवारे ।\n\nहोत न आज्ञा बिनु पैसारे ॥२१॥", + "meaning": "You are the guardian at Lord Rama’s door. Nobody can move forward without your permission which means that Lord Rama’s darshans (to get the sight of) are possible only with your blessings." + }, + "caption": { + "event_num": 210, + "text": "साधु-संत के तुम रखवारे", + "is_empty": false, + "start_ms": 400639, + "end_ms": 410690, + "duration_ms": 10051 + } + }, + { + "is_exact_match": false, + "verse_count": 24, + "caption_event_num": 164, + "similarity": 0.41036264495218466, + "verse": { + "count": 24, + "transliteration": "saba sukha lahai tuhmārī saranā .\n\ntuma racchaka kāhū ko ḍara nā ..22..", + "text": "सब सुख लहै तुह्मारी सरना ।\n\nतुम रच्छक काहू को डर ना ॥२२॥", + "meaning": "Those who take refuge in you, find all the comforts and happiness. When we have a protector like you, we do not need to get scared of anybody or anything." + }, + "caption": { + "event_num": 164, + "text": "सब सुख लहै तुम्हारी", + "is_empty": false, + "start_ms": 304650, + "end_ms": 311520, + "duration_ms": 6870 + } + }, + { + "is_exact_match": false, + "verse_count": 25, + "caption_event_num": 120, + "similarity": 0.11521554337793123, + "verse": { + "count": 25, + "transliteration": "āpana teja sahmāro āpai .\n\ntīnoṃ loka hām̐ka teṃ kām̐pai ..23..", + "text": "आपन तेज सह्मारो आपै ।\n\nतीनों लोक हाँक तें काँपै ॥२३॥", + "meaning": "You alone can withstand your magnificence. All the three worlds start trembling at one roar of yours." + }, + "caption": { + "event_num": 120, + "text": "नारद सारद सहित तरह की", + "is_empty": false, + "start_ms": 214370, + "end_ms": 222860, + "duration_ms": 8490 + } + }, + { + "is_exact_match": false, + "verse_count": 26, + "caption_event_num": 178, + "similarity": 0.7092972666062738, + "verse": { + "count": 26, + "transliteration": "bhūta pisāca nikaṭa nahiṃ āvai .\n\nmahābīra jaba nāma sunāvai ..24..", + "text": "भूत पिसाच निकट नहिं आवै ।\n\nमहाबीर जब नाम सुनावै ॥२४॥", + "meaning": "O Mahaveer! No ghosts or evil spirits come near the ones who remember your name. Therefore, just remembering your name does everything!" + }, + "caption": { + "event_num": 178, + "text": "पिसाच निकट नहिं आवै महाबीर", + "is_empty": false, + "start_ms": 332180, + "end_ms": 342520, + "duration_ms": 10340 + } + }, + { + "is_exact_match": false, + "verse_count": 27, + "caption_event_num": 188, + "similarity": 0.3799783615910079, + "verse": { + "count": 27, + "transliteration": "nāsai roga harai saba pīrā .\n\njapata nirantara hanumata bīrā ..25..", + "text": "नासै रोग हरै सब पीरा ।\n\nजपत निरन्तर हनुमत बीरा ॥२५॥", + "meaning": "O Hanuman! All diseases and all kinds of pain get eradicated when one recites or chants your name. Therefore, chanting your name regularly is considered to be very significant." + }, + "caption": { + "event_num": 188, + "text": "हनुमत", + "is_empty": false, + "start_ms": 349360, + "end_ms": 357099, + "duration_ms": 7739 + } + }, + { + "is_exact_match": false, + "verse_count": 28, + "caption_event_num": 190, + "similarity": 0.41036264495218466, + "verse": { + "count": 28, + "transliteration": "saṅkaṭa teṃ hanumāna chur̤āvai .\n\nmana krama bacana dhyāna jo lāvai ..26..", + "text": "सङ्कट तें हनुमान छुड़ावै ।\n\nमन क्रम बचन ध्यान जो लावै ॥२६॥", + "meaning": "Whoever meditates upon or worships you with thought, word, and deed, gets freedom from all kinds of crisis and affliction." + }, + "caption": { + "event_num": 190, + "text": "दी रात संकट ते हनुमान", + "is_empty": false, + "start_ms": 350949, + "end_ms": 357099, + "duration_ms": 6150 + } + }, + { + "is_exact_match": false, + "verse_count": 29, + "caption_event_num": 196, + "similarity": 0.5023287782256718, + "verse": { + "count": 29, + "transliteration": "saba para rāma tapasvī rājā .\n\ntina ke kāja sakala tuma sājā ..27..", + "text": "सब पर राम तपस्वी राजा ।\n\nतिन के काज सकल तुम साजा ॥२७॥", + "meaning": "Lord Rama is the greatest ascetic amongst all the kings. But, it’s only you who carried out all the tasks of Lord Sri Rama." + }, + "caption": { + "event_num": 196, + "text": "पर राम तपस्वी", + "is_empty": false, + "start_ms": 368650, + "end_ms": 373419, + "duration_ms": 4769 + } + }, + { + "is_exact_match": false, + "verse_count": 30, + "caption_event_num": 202, + "similarity": 0.5245910904457138, + "verse": { + "count": 30, + "transliteration": "aura manoratha jo koī lāvai .\n\nsoī amita jīvana phala pāvai ..28..", + "text": "और मनोरथ जो कोई लावै ।\n\nसोई अमित जीवन फल पावै ॥२८॥", + "meaning": "One who comes to you with any longing or a sincere desire obtains the abundance of the manifested fruit, which remains undying throughout life." + }, + "caption": { + "event_num": 202, + "text": "कुंवारी लावै सोइ अमित जीवन फल पावै चारों", + "is_empty": false, + "start_ms": 382370, + "end_ms": 394669, + "duration_ms": 12299 + } + }, + { + "is_exact_match": false, + "verse_count": 31, + "caption_event_num": 208, + "similarity": 0.5023287782256718, + "verse": { + "count": 31, + "transliteration": "cāroṃ juga paratāpa tuhmārā .\n\nhai parasiddha jagata ujiyārā ..29..", + "text": "चारों जुग परताप तुह्मारा ।\n\nहै परसिद्ध जगत उजियारा ॥२९॥", + "meaning": "Your splendor fills all the four ages. And, your glory is renowned throughout the world." + }, + "caption": { + "event_num": 208, + "text": "जगत उजियारा", + "is_empty": false, + "start_ms": 396710, + "end_ms": 405680, + "duration_ms": 8970 + } + }, + { + "is_exact_match": false, + "verse_count": 32, + "caption_event_num": 212, + "similarity": 0.4494364165239822, + "verse": { + "count": 32, + "transliteration": "sādhu santa ke tuma rakhavāre .\n\nasura nikandana rāma dulāre ..30..", + "text": "साधु सन्त के तुम रखवारे ।\n\nअसुर निकन्दन राम दुलारे ॥३०॥", + "meaning": "You are the guardian of saints and sages; the destroyer of demons and adored by Lord Rama." + }, + "caption": { + "event_num": 212, + "text": "असुर निकंदन राम दुलारे", + "is_empty": false, + "start_ms": 405680, + "end_ms": 413690, + "duration_ms": 8010 + } + }, + { + "is_exact_match": false, + "verse_count": 33, + "caption_event_num": 222, + "similarity": 0.5797386715376658, + "verse": { + "count": 33, + "transliteration": "aṣṭasiddhi nau nidhi ke dātā .\n\nasa bara dīna jānakī mātā ..31..", + "text": "अष्टसिद्धि नौ निधि के दाता ।\n\nअस बर दीन जानकी माता ॥३१॥", + "meaning": "You have been blessed by Mother Janaki to give boon further, to the deserving ones, wherein you can grant the siddhis (eight different powers) and the nidhis (nine different kinds of wealth)." + }, + "caption": { + "event_num": 222, + "text": "अस बर दीन जानकी", + "is_empty": false, + "start_ms": 421100, + "end_ms": 433280, + "duration_ms": 12180 + } + }, + { + "is_exact_match": false, + "verse_count": 34, + "caption_event_num": 224, + "similarity": 0.4743307064971939, + "verse": { + "count": 34, + "transliteration": "rāma rasāyana tuhmare pāsā .\n\nsadā raho raghupati ke dāsā ..32..", + "text": "राम रसायन तुह्मरे पासा ।\n\nसदा रहो रघुपति के दासा ॥३२॥", + "meaning": "You have the essence of Ram bhakti, may you always remain the humble and devoted servant of Raghupati." + }, + "caption": { + "event_num": 224, + "text": "माता राम रसायन तुम्हरे पासा सदा रहो", + "is_empty": false, + "start_ms": 424610, + "end_ms": 437180, + "duration_ms": 12570 + } + }, + { + "is_exact_match": false, + "verse_count": 35, + "caption_event_num": 230, + "similarity": 0.6764792400877006, + "verse": { + "count": 35, + "transliteration": "tuhmare bhajana rāma ko pāvai .\n\njanama janama ke dukha bisarāvai ..33..", + "text": "तुह्मरे भजन राम को पावै ।\n\nजनम जनम के दुख बिसरावै ॥३३॥", + "meaning": "When one sings your praise, your name, he gets to meet Lord Rama and finds relief from the sorrows of many lifetimes." + }, + "caption": { + "event_num": 230, + "text": "जनम-जनम के दुख बिसरावै", + "is_empty": false, + "start_ms": 443280, + "end_ms": 448920, + "duration_ms": 5640 + } + }, + { + "is_exact_match": false, + "verse_count": 36, + "caption_event_num": 236, + "similarity": 0.5368927118515179, + "verse": { + "count": 36, + "transliteration": "anta kāla raghubara pura jāī .\n\njahām̐ janma haribhakta kahāī ..34..", + "text": "अन्त काल रघुबर पुर जाई ।\n\nजहाँ जन्म हरिभक्त कहाई ॥३४॥", + "meaning": "By your grace, one will go to the immortal abode of Lord Rama after death and remain devoted to him." + }, + "caption": { + "event_num": 236, + "text": "जहां जन्म हरि-भक्त", + "is_empty": false, + "start_ms": 452520, + "end_ms": 458460, + "duration_ms": 5940 + } + }, + { + "is_exact_match": false, + "verse_count": 37, + "caption_event_num": 246, + "similarity": 0.6764792400877006, + "verse": { + "count": 37, + "transliteration": "aura devatā citta na dharaī .\n\nhanumata sei sarba sukha karaī ..35..", + "text": "और देवता चित्त न धरई ।\n\nहनुमत सेइ सर्ब सुख करई ॥३५॥", + "meaning": "It is not needed to serve any other deity or god. Service to Lord Hanuman gives all the comforts." + }, + "caption": { + "event_num": 246, + "text": "देवता चित्त न धरई हनुमत सेइ सर्ब", + "is_empty": false, + "start_ms": 465230, + "end_ms": 477200, + "duration_ms": 11970 + } + }, + { + "is_exact_match": false, + "verse_count": 38, + "caption_event_num": 190, + "similarity": 0.5499883949217763, + "verse": { + "count": 38, + "transliteration": "saṅkaṭa kaṭai miṭai saba pīrā .\n\njo sumirai hanumata balabīrā ..36..", + "text": "सङ्कट कटै मिटै सब पीरा ।\n\nजो सुमिरै हनुमत बलबीरा ॥३६॥", + "meaning": "All troubles cease for the one who remembers the powerful lord, Lord Hanuman and all his pains also come to an end." + }, + "caption": { + "event_num": 190, + "text": "दी रात संकट ते हनुमान", + "is_empty": false, + "start_ms": 350949, + "end_ms": 357099, + "duration_ms": 6150 + } + }, + { + "is_exact_match": false, + "verse_count": 39, + "caption_event_num": 252, + "similarity": 0.7765145304745155, + "verse": { + "count": 39, + "transliteration": "jaya jaya jaya hanumāna gosāīṃ .\n\nkṛpā karahu gurudeva kī nāīṃ ..37..", + "text": "जय जय जय हनुमान गोसाईं ।\n\nकृपा करहु गुरुदेव की नाईं ॥३७॥", + "meaning": "O Lord Hanuman! Praises and glory to you O mighty lord, please bestow your grace as our supreme guru." + }, + "caption": { + "event_num": 252, + "text": "जय जय", + "is_empty": false, + "start_ms": 484370, + "end_ms": 488510, + "duration_ms": 4140 + } + }, + { + "is_exact_match": false, + "verse_count": 40, + "caption_event_num": 260, + "similarity": 0.4501755023269898, + "verse": { + "count": 40, + "transliteration": "jo sata bāra pāṭha kara koī .\n\nchūṭahi bandi mahā sukha hoī ..38..", + "text": "जो सत बार पाठ कर कोई ।\n\nछूटहि बन्दि महा सुख होई ॥३८॥", + "meaning": "One who recites this Chalisa a hundred times is released from all bondages and will attain great bliss." + }, + "caption": { + "event_num": 260, + "text": "कर कोई छूटहि बंदि महा सुख होई जो यह", + "is_empty": false, + "start_ms": 497550, + "end_ms": 507410, + "duration_ms": 9860 + } + }, + { + "is_exact_match": false, + "verse_count": 41, + "caption_event_num": 264, + "similarity": 0.4112070550676187, + "verse": { + "count": 41, + "transliteration": "jo yaha par̤hai hanumāna cālīsā .\n\nhoya siddhi sākhī gaurīsā ..39..", + "text": "जो यह पढ़ै हनुमान चालीसा ।\n\nहोय सिद्धि साखी गौरीसा ॥३९॥", + "meaning": "One who reads and recites this Hanuman Chalisa, all his works get accomplished. Lord Shiva, himself, is the witness to it." + }, + "caption": { + "event_num": 264, + "text": "पढ़ै हनुमान चल", + "is_empty": false, + "start_ms": 511310, + "end_ms": 522440, + "duration_ms": 11130 + } + }, + { + "is_exact_match": false, + "verse_count": 42, + "caption_event_num": 268, + "similarity": 0.5797386715376658, + "verse": { + "count": 42, + "transliteration": "tulasīdāsa sadā hari cerā .\n\nkījai nātha hṛdaya maham̐ ḍerā ..40..", + "text": "तुलसीदास सदा हरि चेरा ।\n\nकीजै नाथ हृदय महँ डेरा ॥४०॥", + "meaning": "O Lord Hanuman, may I always remain a servant, a devotee to Lord Sri Ram, says Tulsidas. And, may you always reside in my heart." + }, + "caption": { + "event_num": 268, + "text": "तुलसीदास सदा हरि चेरा", + "is_empty": false, + "start_ms": 522440, + "end_ms": 534770, + "duration_ms": 12330 + } + }, + { + "is_exact_match": false, + "verse_count": 43, + "caption_event_num": 278, + "similarity": 0.22555487220684337, + "verse": { + "count": 43, + "transliteration": "pavanatanaya saṅkaṭa harana maṅgala mūrati rūpa .\n\nrāma lakhana sītā sahita hṛdaya basahu sura bhūpa ..", + "text": "॥दोहा॥\n\nपवनतनय सङ्कट हरन मङ्गल मूरति रूप ।\n\nराम लखन सीता सहित हृदय बसहु सुर भूप ॥", + "meaning": "O the Son of Wind, you are the destroyer of all sorrows. you are the embodiment of fortune and prosperity.\n\nWith Lord Rama, Laxmana and Mother Sita, dwell in my heart, always." + }, + "caption": { + "event_num": 278, + "text": "संकट हरण मंगल", + "is_empty": false, + "start_ms": 544520, + "end_ms": 551480, + "duration_ms": 6960 + } + } + ] +} \ No newline at end of file diff --git a/scripts/chalisa_scraped.json b/scripts/chalisa_scraped.json new file mode 100644 index 00000000..702b48e6 --- /dev/null +++ b/scripts/chalisa_scraped.json @@ -0,0 +1 @@ +{"verses":[{"verse_trans":"śrīguru carana saroja raja nija manu mukuru sudhāri .\n\nbaranaüm̐ raghubara bimala jasu jo dāyaku phala cāri ..","verse_sanskrit":"श्रीगुरु चरन सरोज रज निज मनु मुकुरु सुधारि ।\n\nबरनउँ रघुबर बिमल जसु जो दायकु फल चारि ॥","verse_meaning":"Having polished the mirror of my heart with the dust of my Guru’s lotus feet, I recite the divine fame of the greatest king of Raghukul dynasty, which bestows us with the fruit of all the four efforts.","count":1},{"verse_trans":"buddhihīna tanu jānike sumirauṃ pavana-kumāra .\n\nbala budhi bidyā dehu mohiṃ harahu kalesa bikāra ..","verse_sanskrit":"बुद्धिहीन तनु जानिके सुमिरौं पवन-कुमार ।\n\nबल बुधि बिद्या देहु मोहिं हरहु कलेस बिकार ॥","verse_meaning":"Knowing that this mind of mine has less intelligence, I remember the ‘Son of Wind’ who, granting me strength, wisdom and all kinds of knowledge, removes all my suffering and shortcomings.","count":2},{"verse_trans":"jaya hanumāna jñāna guna sāgara .\n\njaya kapīsa tihum̐ loka ujāgara ..1..","verse_sanskrit":"॥चौपाई॥\n\nजय हनुमान ज्ञान गुन सागर ।\n\nजय कपीस तिहुँ लोक उजागर ॥१॥","verse_meaning":"Victory to Lord Hanuman, the ocean of wisdom and virtue. Victory to the Lord who is supreme among the monkeys, illuminator of the three worlds.","count":3},{"verse_trans":"rāma dūta atulita bala dhāmā .\n\nañjani-putra pavanasuta nāmā ..2..","verse_sanskrit":"राम दूत अतुलित बल धामा ।\n\nअञ्जनि-पुत्र पवनसुत नामा ॥२॥","verse_meaning":"you are Lord Rama’s emissary,‌ the abode of matchless power, Mother Anjani’s son and also popular as the ‘Son of the Wind’.","count":4},{"verse_trans":"mahābīra bikrama bajaraṅgī .\n\nkumati nivāra sumati ke saṅgī ..3..","verse_sanskrit":"महाबीर बिक्रम बजरङ्गी ।\n\nकुमति निवार सुमति के सङ्गी ॥३॥","verse_meaning":"Great hero, you are as mighty as a thunderbolt. you remove evil intellect and are the companion of those having good ones.","count":5},{"verse_trans":"kañcana barana birāja subesā .\n\nkānana kuṇḍala kuñcita kesā ..4..","verse_sanskrit":"कञ्चन बरन बिराज सुबेसा ।\n\nकानन कुण्डल कुञ्चित केसा ॥४॥","verse_meaning":"your skin is golden in color and you are adorned with beautiful clothes. you have adorning earrings in your ears and your hair is curly and thick.","count":6},{"verse_trans":"hātha bajra au dhvajā birājai .\n\nkām̐dhe mūm̐ja janeu sājai ..5..","verse_sanskrit":"हाथ बज्र औ ध्वजा बिराजै ।\n\nकाँधे मूँज जनेउ साजै ॥५॥","verse_meaning":"In your hands, shine a mace and a flag of righteousness. A sacred thread adorns your right shoulder.","count":7},{"verse_trans":"saṅkara suvana kesarīnandana .\n\nteja pratāpa mahā jaga bandana ..6..","verse_sanskrit":"सङ्कर सुवन केसरीनन्दन ।\n\nतेज प्रताप महा जग बन्दन ॥६॥","verse_meaning":"You are the embodiment of Lord Shiva and vanar-raj Kesari’s son. There is no limit or end to your glory, your magnificence. The whole universe worships you.","count":8},{"verse_trans":"bidyāvāna gunī ati cātura .\n\nrāma kāja karibe ko ātura ..7..","verse_sanskrit":"बिद्यावान गुनी अति चातुर ।\n\nराम काज करिबे को आतुर ॥७॥","verse_meaning":"You are the wisest of the wise, virtuous and (morally) clever. You are always eager to do Lord Rama’s works.","count":9},{"verse_trans":"prabhu caritra sunibe ko rasiyā .\n\nrāma lakhana sītā mana basiyā ..8..","verse_sanskrit":"प्रभु चरित्र सुनिबे को रसिया ।\n\nराम लखन सीता मन बसिया ॥८॥","verse_meaning":"You feel extremely delighted in listening to Lord Rama’s doings and conduct. Lord Rama, Mother Sita, and Lord Laxmana dwell forever in your heart.","count":10},{"verse_trans":"sūkṣma rūpa dhari siyahiṃ dikhāvā .\n\nbikaṭa rūpa dhari laṅka jarāvā ..9..","verse_sanskrit":"सूक्ष्म रूप धरि सियहिं दिखावा ।\n\nबिकट रूप धरि लङ्क जरावा ॥९॥","verse_meaning":"Taking the subtle form, you appeared in front of Mother Sita. And, taking the formidable form, you burnt the Lanka (Ravana’s kingdom).","count":11},{"verse_trans":"bhīma rūpa dhari asura sam̐hāre .\n\nrāmacandra ke kāja sam̐vāre ..10..","verse_sanskrit":"भीम रूप धरि असुर सँहारे ।\n\nरामचन्द्र के काज सँवारे ॥१०॥","verse_meaning":"Taking the massive form (like that of Bheema), you slaughtered the demons. This is how, you completed Lord Rama’s tasks, successfully.","count":12},{"verse_trans":"lāya sañjīvana lakhana jiyāye .\n\nśrīraghubīra haraṣi ura lāye ..11..","verse_sanskrit":"लाय सञ्जीवन लखन जियाये ।\n\nश्रीरघुबीर हरषि उर लाये ॥११॥","verse_meaning":"Bringing the magic-herb (sanjivani), you revived Lord Laxmana.","count":13},{"verse_trans":"raghupati kīhnī bahuta bar̤āī .\n\ntuma mama priya bharatahi sama bhāī ..12..","verse_sanskrit":"रघुपति कीह्नी बहुत बड़ाई ।\n\nतुम मम प्रिय भरतहि सम भाई ॥१२॥","verse_meaning":"Raghupati, Lord Rama praised you greatly and overflowing in gratitude, said that you are a dear brother to him just as Bharat is.","count":14},{"verse_trans":"sahasa badana tuhmāro jasa gāvaiṃ .\n\nasa kahi śrīpati kaṇṭha lagāvaiṃ ..13..","verse_sanskrit":"सहस बदन तुह्मारो जस गावैं ।\n\nअस कहि श्रीपति कण्ठ लगावैं ॥१३॥","verse_meaning":"Saying this, Lord Rama drew you to himself and embraced you. Sages like Sanaka, Gods like Brahma and sages like Narada and even the thousand-mouthed serpent sing your fame!","count":15},{"verse_trans":"sanakādika brahmādi munīsā .\n\nnārada sārada sahita ahīsā ..14..","verse_sanskrit":"सनकादिक ब्रह्मादि मुनीसा ।\n\nनारद सारद सहित अहीसा ॥१४॥","verse_meaning":"Sanak, Sanandan and the other Rishis and great saints; Brahma – the god, Narada, Saraswati – the Mother Divine and the King of serpents sing your glory.","count":16},{"verse_trans":"jama kubera digapāla jahām̐ te .\n\nkabi kobida kahi sake kahām̐ te ..15..","verse_sanskrit":"जम कुबेर दिगपाल जहाँ ते ।\n\nकबि कोबिद कहि सके कहाँ ते ॥१५॥","verse_meaning":"Yama, Kubera and the guardians of the four quarters; poets and scholars – none can express your glory.","count":17},{"verse_trans":"tuma upakāra sugrīvahiṃ kīhnā .\n\nrāma milāya rāja pada dīhnā ..16..","verse_sanskrit":"तुम उपकार सुग्रीवहिं कीह्ना ।\n\nराम मिलाय राज पद दीह्ना ॥१६॥","verse_meaning":"You helped Sugriva by introducing him to Lord Rama and regaining his crown. Therefore, you gave him the Kingship (the dignity of being called a king).","count":18},{"verse_trans":"tuhmaro mantra bibhīṣana mānā .\n\nlaṅkesvara bhae saba jaga jānā ..17..","verse_sanskrit":"तुह्मरो मन्त्र बिभीषन माना ।\n\nलङ्केस्वर भए सब जग जाना ॥१७॥","verse_meaning":"Likewise, complying with your preachings, even Vibhishana became the King of Lanka.","count":19},{"verse_trans":"juga sahasra jojana para bhānu .\n\nlīlyo tāhi madhura phala jānū ..18..","verse_sanskrit":"जुग सहस्र जोजन पर भानु ।\n\nलील्यो ताहि मधुर फल जानू ॥१८॥","verse_meaning":"You swallowed the sun, located thousands of miles away, mistaking it to be a sweet, red fruit!","count":20},{"verse_trans":"prabhu mudrikā meli mukha māhīṃ .\n\njaladhi lām̐ghi gaye acaraja nāhīṃ ..19..","verse_sanskrit":"प्रभु मुद्रिका मेलि मुख माहीं ।\n\nजलधि लाँघि गये अचरज नाहीं ॥१९॥","verse_meaning":"Keeping the ring in your mouth, which was given to you by Lord Rama, you crossed over the ocean, to no astonishment, whatsoever.","count":21},{"verse_trans":"durgama kāja jagata ke jete .\n\nsugama anugraha tuhmare tete ..20..","verse_sanskrit":"दुर्गम काज जगत के जेते ।\n\nसुगम अनुग्रह तुह्मरे तेते ॥२०॥","verse_meaning":"All difficult tasks of this world become easy, with your grace.","count":22},{"verse_trans":"rāma duāre tuma rakhavāre .\n\nhota na ājñā binu paisāre ..21..","verse_sanskrit":"राम दुआरे तुम रखवारे ।\n\nहोत न आज्ञा बिनु पैसारे ॥२१॥","verse_meaning":"You are the guardian at Lord Rama’s door. Nobody can move forward without your permission which means that Lord Rama’s darshans (to get the sight of) are possible only with your blessings.","count":23},{"verse_trans":"saba sukha lahai tuhmārī saranā .\n\ntuma racchaka kāhū ko ḍara nā ..22..","verse_sanskrit":"सब सुख लहै तुह्मारी सरना ।\n\nतुम रच्छक काहू को डर ना ॥२२॥","verse_meaning":"Those who take refuge in you, find all the comforts and happiness. When we have a protector like you, we do not need to get scared of anybody or anything.","count":24},{"verse_trans":"āpana teja sahmāro āpai .\n\ntīnoṃ loka hām̐ka teṃ kām̐pai ..23..","verse_sanskrit":"आपन तेज सह्मारो आपै ।\n\nतीनों लोक हाँक तें काँपै ॥२३॥","verse_meaning":"You alone can withstand your magnificence. All the three worlds start trembling at one roar of yours.","count":25},{"verse_trans":"bhūta pisāca nikaṭa nahiṃ āvai .\n\nmahābīra jaba nāma sunāvai ..24..","verse_sanskrit":"भूत पिसाच निकट नहिं आवै ।\n\nमहाबीर जब नाम सुनावै ॥२४॥","verse_meaning":"O Mahaveer! No ghosts or evil spirits come near the ones who remember your name. Therefore, just remembering your name does everything!","count":26},{"verse_trans":"nāsai roga harai saba pīrā .\n\njapata nirantara hanumata bīrā ..25..","verse_sanskrit":"नासै रोग हरै सब पीरा ।\n\nजपत निरन्तर हनुमत बीरा ॥२५॥","verse_meaning":"O Hanuman! All diseases and all kinds of pain get eradicated when one recites or chants your name. Therefore, chanting your name regularly is considered to be very significant.","count":27},{"verse_trans":"saṅkaṭa teṃ hanumāna chur̤āvai .\n\nmana krama bacana dhyāna jo lāvai ..26..","verse_sanskrit":"सङ्कट तें हनुमान छुड़ावै ।\n\nमन क्रम बचन ध्यान जो लावै ॥२६॥","verse_meaning":"Whoever meditates upon or worships you with thought, word, and deed, gets freedom from all kinds of crisis and affliction.","count":28},{"verse_trans":"saba para rāma tapasvī rājā .\n\ntina ke kāja sakala tuma sājā ..27..","verse_sanskrit":"सब पर राम तपस्वी राजा ।\n\nतिन के काज सकल तुम साजा ॥२७॥","verse_meaning":"Lord Rama is the greatest ascetic amongst all the kings. But, it’s only you who carried out all the tasks of Lord Sri Rama.","count":29},{"verse_trans":"aura manoratha jo koī lāvai .\n\nsoī amita jīvana phala pāvai ..28..","verse_sanskrit":"और मनोरथ जो कोई लावै ।\n\nसोई अमित जीवन फल पावै ॥२८॥","verse_meaning":"One who comes to you with any longing or a sincere desire obtains the abundance of the manifested fruit, which remains undying throughout life.","count":30},{"verse_trans":"cāroṃ juga paratāpa tuhmārā .\n\nhai parasiddha jagata ujiyārā ..29..","verse_sanskrit":"चारों जुग परताप तुह्मारा ।\n\nहै परसिद्ध जगत उजियारा ॥२९॥","verse_meaning":"Your splendor fills all the four ages. And, your glory is renowned throughout the world.","count":31},{"verse_trans":"sādhu santa ke tuma rakhavāre .\n\nasura nikandana rāma dulāre ..30..","verse_sanskrit":"साधु सन्त के तुम रखवारे ।\n\nअसुर निकन्दन राम दुलारे ॥३०॥","verse_meaning":"You are the guardian of saints and sages; the destroyer of demons and adored by Lord Rama.","count":32},{"verse_trans":"aṣṭasiddhi nau nidhi ke dātā .\n\nasa bara dīna jānakī mātā ..31..","verse_sanskrit":"अष्टसिद्धि नौ निधि के दाता ।\n\nअस बर दीन जानकी माता ॥३१॥","verse_meaning":"You have been blessed by Mother Janaki to give boon further, to the deserving ones, wherein you can grant the siddhis (eight different powers) and the nidhis (nine different kinds of wealth).","count":33},{"verse_trans":"rāma rasāyana tuhmare pāsā .\n\nsadā raho raghupati ke dāsā ..32..","verse_sanskrit":"राम रसायन तुह्मरे पासा ।\n\nसदा रहो रघुपति के दासा ॥३२॥","verse_meaning":"You have the essence of Ram bhakti, may you always remain the humble and devoted servant of Raghupati.","count":34},{"verse_trans":"tuhmare bhajana rāma ko pāvai .\n\njanama janama ke dukha bisarāvai ..33..","verse_sanskrit":"तुह्मरे भजन राम को पावै ।\n\nजनम जनम के दुख बिसरावै ॥३३॥","verse_meaning":"When one sings your praise, your name, he gets to meet Lord Rama and finds relief from the sorrows of many lifetimes.","count":35},{"verse_trans":"anta kāla raghubara pura jāī .\n\njahām̐ janma haribhakta kahāī ..34..","verse_sanskrit":"अन्त काल रघुबर पुर जाई ।\n\nजहाँ जन्म हरिभक्त कहाई ॥३४॥","verse_meaning":"By your grace, one will go to the immortal abode of Lord Rama after death and remain devoted to him.","count":36},{"verse_trans":"aura devatā citta na dharaī .\n\nhanumata sei sarba sukha karaī ..35..","verse_sanskrit":"और देवता चित्त न धरई ।\n\nहनुमत सेइ सर्ब सुख करई ॥३५॥","verse_meaning":"It is not needed to serve any other deity or god. Service to Lord Hanuman gives all the comforts.","count":37},{"verse_trans":"saṅkaṭa kaṭai miṭai saba pīrā .\n\njo sumirai hanumata balabīrā ..36..","verse_sanskrit":"सङ्कट कटै मिटै सब पीरा ।\n\nजो सुमिरै हनुमत बलबीरा ॥३६॥","verse_meaning":"All troubles cease for the one who remembers the powerful lord, Lord Hanuman and all his pains also come to an end.","count":38},{"verse_trans":"jaya jaya jaya hanumāna gosāīṃ .\n\nkṛpā karahu gurudeva kī nāīṃ ..37..","verse_sanskrit":"जय जय जय हनुमान गोसाईं ।\n\nकृपा करहु गुरुदेव की नाईं ॥३७॥","verse_meaning":"O Lord Hanuman! Praises and glory to you O mighty lord, please bestow your grace as our supreme guru.","count":39},{"verse_trans":"jo sata bāra pāṭha kara koī .\n\nchūṭahi bandi mahā sukha hoī ..38..","verse_sanskrit":"जो सत बार पाठ कर कोई ।\n\nछूटहि बन्दि महा सुख होई ॥३८॥","verse_meaning":"One who recites this Chalisa a hundred times is released from all bondages and will attain great bliss.","count":40},{"verse_trans":"jo yaha par̤hai hanumāna cālīsā .\n\nhoya siddhi sākhī gaurīsā ..39..","verse_sanskrit":"जो यह पढ़ै हनुमान चालीसा ।\n\nहोय सिद्धि साखी गौरीसा ॥३९॥","verse_meaning":"One who reads and recites this Hanuman Chalisa, all his works get accomplished. Lord Shiva, himself, is the witness to it.","count":41},{"verse_trans":"tulasīdāsa sadā hari cerā .\n\nkījai nātha hṛdaya maham̐ ḍerā ..40..","verse_sanskrit":"तुलसीदास सदा हरि चेरा ।\n\nकीजै नाथ हृदय महँ डेरा ॥४०॥","verse_meaning":"O Lord Hanuman, may I always remain a servant, a devotee to Lord Sri Ram, says Tulsidas. And, may you always reside in my heart.","count":42},{"verse_trans":"pavanatanaya saṅkaṭa harana maṅgala mūrati rūpa .\n\nrāma lakhana sītā sahita hṛdaya basahu sura bhūpa ..","verse_sanskrit":"॥दोहा॥\n\nपवनतनय सङ्कट हरन मङ्गल मूरति रूप ।\n\nराम लखन सीता सहित हृदय बसहु सुर भूप ॥","verse_meaning":"O the Son of Wind, you are the destroyer of all sorrows. you are the embodiment of fortune and prosperity.\n\nWith Lord Rama, Laxmana and Mother Sita, dwell in my heart, always.","count":43}],"title":"Hanuman Chalisa","description":"Hanuman Chalisa is authored by 16th-century poet Tulsidas in the Awadhi language. It has 40 verses and every verse has 4 lines."} \ No newline at end of file diff --git a/scripts/genEventsYoutubePlayerBookmarklet.js b/scripts/genEventsYoutubePlayerBookmarklet.js new file mode 100644 index 00000000..62392a00 --- /dev/null +++ b/scripts/genEventsYoutubePlayerBookmarklet.js @@ -0,0 +1,176 @@ +javascript:(function() { + const timestamps = []; + const durations = [] + const overlay = createOverlay(); + document.body.appendChild(overlay); + + document.addEventListener('keydown', handleKeyPress); + + function createOverlay() { + const overlay = document.createElement('div'); + const overlayStyle = { + position: 'fixed', + top: '50px', + right: '0', + backgroundColor: 'rgba(255,0,0,0.66)', + padding: '10px', + zIndex: '1000', + } + for (const prop in overlayStyle) { + overlay.style[prop] = overlayStyle[prop]; + } + return overlay; + } + + function handleKeyPress(event) { + if (event.key === '=') { + captureTimestamp(); + } else if (event.key === '-') { + removeNearestDuration(); + } else if (event.key === 'Backspace') { + removeNearestTimestamp(); + } else if (event.key === '+') { + endTimestamp(); + } + + } + + function captureTimestamp() { + const currentTime = getCurrentTime(); + if (typeof(currentTime) === "number") { + const len = timestamps.length; + const PrevDurationEmpty = (len > 0) && (durations[len -1] == null); + timestamps.push(currentTime); + if (PrevDurationEmpty) { + // set prev duration + durations[len -1] = currentTime - timestamps[len -1] + } + updateOverlay(); + } + } + + function endTimestamp() { + const currentTime = getCurrentTime(); + console.log(currentTime) + if (typeof(currentTime) === "number") { + // find closest on the left time is > + const closestIndex = findClosestLeftTimestampIndex(currentTime); + durations[closestIndex] = currentTime - timestamps[closestIndex]; + updateOverlay(); + } + } + + function removeNearestTimestamp() { + const currentTime = getCurrentTime(); + if (typeof(currentTime) === "number") { + const closestIndex = findClosestTimestampIndex(currentTime); + const prevTime = timestamps[closestIndex] + timestamps.splice(closestIndex, 1); + durations[closestIndex] = null + if ( closestIndex > 0 && prevTime == (timestamps[closestIndex -1] + durations[closestIndex -1])){ + durations[closestIndex -1] = null} + console.log(durations) + + updateOverlay(); + } + } + + function removeNearestDuration() { + const currentTime = getCurrentTime(); + console.log(currentTime) + if (currentTime !== null) { + // find closest on the left time is > + const closestIndex = findClosestLeftTimestampIndex(currentTime); + durations[closestIndex] = null + updateOverlay(); + } + } + + function getCurrentTime() { + const player = document.getElementById('movie_player'); + return player ? player.getCurrentTime()*1000 : null; + } + + function getTotalTime() { + const player = document.getElementById('movie_player'); + return player ? player.getDuration()*1000 : null; + } + + function findClosestTimestampIndex(currentTime) { + return timestamps.reduce((prev, curr, index, array) => { + return (Math.abs(curr - currentTime) < Math.abs(array[prev] - currentTime) ? index : prev); + }, 0); + } + + // diff of curr < diff of prev and curr < currentTime + function findClosestLeftTimestampIndex(currentTime) { + return timestamps.reduce((prev, curr, index, array) => { + return ((Math.abs(curr - currentTime) <= Math.abs(array[prev] - currentTime)) && (curr <= currentTime) ? index : prev); + }, 0); + } + + function updateOverlay() { + overlay.innerHTML = ''; + timestamps.forEach((time, index) => { + const link = createTimestampLink(time, index); + overlay.appendChild(link); + overlay.appendChild(document.createElement('br')); + }); + + const copyButton = createCopyButton(); + overlay.appendChild(copyButton); + } + + function createTimestampLink(time, index) { + const link = document.createElement('a'); + link.href = '#'; + link.style.color = 'yellow' + link.textContent = `Event ${index + 1}: ${formatTime(time)} - ${formatTime(time + durations[index])} `; + link.onclick = () => { + const player = document.getElementById('movie_player'); + if (player) player.seekTo(time/1000); + return false; + }; + return link; + } + + function createCopyButton() { + const EventZip = timestamps.reduce((eventls, curr, i) => { + eventls[i] = {origin: curr, duration: duration[i] || timestamps[i+1] && (timestamps[i+1] - curr) || (getTotalTime() - curr)}; + return eventls; + }, {}); + const copyButton = document.createElement('button'); + copyButton.textContent = 'Copy Events'; + copyButton.onclick = () => { + const jsonTimestamps = JSON.stringify(EventZip); + copyToClipboard(jsonTimestamps); + }; + return copyButton; + } + + function formatTime(ms) { + const minutes = Math.floor(ms / 60000); + const remainingSeconds = ms % 60000; + console.log(remainingSeconds) + return `${minutes}:${remainingSeconds < 10000 ? '0' : ''}${String(remainingSeconds).substring(0,4) }`; + } + + function copyToClipboard(text) { + if (navigator.clipboard && window.isSecureContext) { + return navigator.clipboard.writeText(text); + } else { + const textarea = document.createElement("textarea"); + textarea.value = text; + textarea.style.position = "fixed"; + textarea.style.left = "-999999px"; + textarea.style.top = "-999999px"; + document.body.appendChild(textarea); + textarea.focus(); + textarea.select(); + return new Promise((resolve, reject) => { + document.execCommand("copy") ? resolve() : reject(); + textarea.remove(); + }); + } + } +})(); diff --git a/scripts/requirements.txt b/scripts/requirements.txt new file mode 100644 index 00000000..85c873dc --- /dev/null +++ b/scripts/requirements.txt @@ -0,0 +1,36 @@ +alabaster==0.7.16 +Babel==2.14.0 +certifi==2023.11.17 +charset-normalizer==3.3.2 +docutils==0.20.1 +idna==3.6 +imagesize==1.4.1 +indic-nlp-library==0.92 +Jinja2==3.1.3 +joblib==1.3.2 +MarkupSafe==2.1.4 +Morfessor==2.0.6 +numpy==1.26.3 +packaging==23.2 +pandas==2.2.0 +Pygments==2.17.2 +python-dateutil==2.8.2 +pytz==2023.3.post1 +requests==2.31.0 +scikit-learn==1.4.0 +scipy==1.11.4 +six==1.16.0 +snowballstemmer==2.2.0 +Sphinx==7.2.6 +sphinx-argparse==0.4.0 +sphinx-rtd-theme==2.0.0 +sphinxcontrib-applehelp==1.0.8 +sphinxcontrib-devhelp==1.0.6 +sphinxcontrib-htmlhelp==2.0.5 +sphinxcontrib-jquery==4.1 +sphinxcontrib-jsmath==1.0.1 +sphinxcontrib-qthelp==1.0.7 +sphinxcontrib-serializinghtml==1.1.10 +threadpoolctl==3.2.0 +tzdata==2023.4 +urllib3==2.1.0 diff --git a/scripts/video_ir.py b/scripts/video_ir.py new file mode 100755 index 00000000..3cd75f1b --- /dev/null +++ b/scripts/video_ir.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python3 +""" +Handles the creation of intermediate representation for video. + +Ref: https://github.com/ve1ld/vyasa/issues/21 +""" +import json +import math +import sys +from indicnlp.tokenize import indic_tokenize +from indicnlp.normalize.indic_normalize import IndicNormalizerFactory +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.metrics.pairwise import cosine_similarity + +remove_nuktas = False +normalizer_factory = IndicNormalizerFactory() +normalizer=normalizer_factory.get_normalizer("hi") # NB: documentation doesn't match up with usage here in the #params. Problem shall be ignored. + +def get_text_similarity(a, b): + normalized_a = normalizer.normalize(a) + normalized_b = normalizer.normalize(b) + tokens_a = indic_tokenize.trivial_tokenize(normalized_a) + tokens_b = indic_tokenize.trivial_tokenize(normalized_b) + + tokens_a = [token.lower() for token in tokens_a] + tokens_b = [token.lower() for token in tokens_b] + + stringified_tokens_a = " ".join(tokens_a) + stringified_tokens_b = " ".join(tokens_b) + + vectorizer = TfidfVectorizer().fit_transform([stringified_tokens_a, stringified_tokens_b]) + sim_score = cosine_similarity(vectorizer[0], vectorizer[1]) + return sim_score[0][0] + +def read_file(filename): + print(f">> Reading {filename} as a json file") + + with open(filename, 'r') as f: + data = json.load(f) + + return data + +def write_to_file(filename, content): + with open(filename, 'w') as file: + print(f"Writing to {filename}...") + file.write(content) + print(f"... Wrote to {filename}") + + + +class VideoCaptions: + """ + Observations about segments:: + 0. A negligible minority of the events won't have segments (only the first one it seems.) + 1. [the text has instrumentals] there are text-events that just say "[संगीत]", which means instruments. + I'm guessing that similar stuff will be there in other languages as well. If there's a need to filter these + commented parts out, then we should be able to do so by just filtering away whatever is within `[]` + 2. some events will overlap when displaying captions, that's why they are not chronologically unique segments. + """ + + def __init__(self, captions_data): + events = captions_data.get('events') + + self.caption_events = [Event(event, event_idx + 1) for event_idx, event in enumerate(events)] + + def create_srt_file(self, filename="captionsOutput.srt"): + content = "".join([str(event) for event in self.caption_events]) + write_to_file(filename, content) + +class Event: + def __init__(self, event_data, event_num): + self.event_num = event_num + extracted_text = self.extract_all_text_in_event(event_data) + self.event_text = extracted_text + self.is_empty_text = True if not extracted_text else False + self.event_start_time, self.event_end_time, self.event_duration = self.extract_timing_info(event_data) + self.event_data = event_data + + def to_dict(self): + payload = { + "event_num": self.event_num, + "text": self.event_text, + "is_empty": self.is_empty_text, + "start_ms": self.event_start_time, + "end_ms": self.event_end_time, + "duration_ms": self.event_duration, + } + + return payload + + + def get_text_similarity_score(self, other_text): + (is_one_arg_empty_and_not_same) = not(other_text == self.event_text) and (not other_text or not self.event_text) + if(is_one_arg_empty_and_not_same): + return -1 + + return get_text_similarity(self.event_text, other_text) + + def extract_all_text_in_event(self, event): + segs = event.get("segs", []) + text_in_segs = " ".join([seg.get("utf8", " ") for seg in segs]) + text_in_segs.strip() + + return text_in_segs + + def extract_timing_info(self,event): + start_time = event.get('tStartMs') + duration = event.get('dDurationMs', 0) + end_time = start_time + duration + + return [start_time, end_time, duration] + + def create_time_triplet(self, ms_timestring): + seconds = (ms_timestring // 1000) + hours = str(seconds // 3600).zfill(2) + seconds %= 3600 + minutes = str(seconds // 60).zfill(2) + seconds %= 60 + seconds = str(seconds).zfill(2) + milliseconds = str(ms_timestring % 1000).zfill(3) + + return f"{hours}:{minutes}:{seconds},{milliseconds}" + + + def __str__(self) -> str: + result = f"{self.event_num}\n" + TWO_HASH_ARROW_DELIM = "-"+"-"+">" + start_time = self.create_time_triplet(self.event_start_time) + end_time = self.create_time_triplet(self.event_end_time) + result += f"{start_time} {TWO_HASH_ARROW_DELIM} {end_time}\n" + result += f"{self.event_text}\n" + + return result + +class Verse: + def __init__(self, verse_data) -> None: + self.count = verse_data.get("count") + self.transliteration = verse_data.get("verse_trans") + self.sanskrit = verse_data.get("verse_sanskrit") + self.meaning = verse_data.get("verse_meaning") + + return + + def to_dict(self): + payload = { + "count": self.count, + "transliteration": self.transliteration, + "text": self.sanskrit, + "meaning": self.meaning, + } + + return payload + + def get_similarity_score_for_text(self, other_text): + if not other_text: + return 0 + + return get_text_similarity(other_text, self.sanskrit) + + def __repr__(self) -> str: + msg = f"{[self.count]}\n{self.sanskrit}\n" + return msg + +class ScrapedText: + def __init__(self, file_data) -> None: + self.title = file_data.get("title") + self.description = file_data.get("description") + self.verses = [Verse(verse_data) for verse_data in file_data.get("verses")] + + return + + +class Mapping: + + def __init__(self, scraped_text, video_captions): + self.text = scraped_text + self.captions = video_captions + self.matches = self.map_scraped_verses_to_captioned_events(scraped_text.verses, video_captions.caption_events) + + for match in self.matches: + print("======================") + print(match) + + def dump_mapping_json(self, filename="mapping_dump.json"): + payload = { + "text": "hanuman chalisa", + "mappings": [match.to_dict() for match in self.matches] + } + + stringified = json.dumps(payload, indent=4, ensure_ascii=False) + write_to_file(filename=filename, content=stringified) + + return + + def map_scraped_verses_to_captioned_events(self, scraped_verses, caption_events): + num_exact_matches = 0 + num_related_matches = 0 + num_non_matches = 0 + matches = [] + + for verse in scraped_verses: + best_candidate = None + candidates = [] + non_candidates = [] + best_sim_score = -math.inf + for caption_event in caption_events: + # disregard empty events: + if caption_event.is_empty_text: + non_candidates.append((-math.inf, caption_event)) + continue + + sim_score = verse.get_similarity_score_for_text(caption_event.event_text) + pair = (sim_score, caption_event) + best_sim_score = max(best_sim_score, sim_score) + + is_better = best_sim_score == sim_score + if (is_better): + best_candidate = caption_event + + if sim_score > 0: + candidates.append(pair) + else: + non_candidates.append(pair) + + match = self.Match(verse, best_candidate, best_sim_score) + + if (best_sim_score == 1): + num_exact_matches += 1 + match.is_exact_match = True + elif (best_sim_score > 0): + num_related_matches += 1 + else: + num_non_matches += 1 + + matches.append(match) + + print(f"After mapping, stats: \n\t#exact = {num_exact_matches} \n\t#related: {num_related_matches}\n\t#non-matches: {num_non_matches}") + + return matches + + class Match: + def __init__(self, verse, caption, score): + self.verse = verse + self.caption = caption + self.score = score + self.is_exact_match = False # default + + return + + def set_is_exact_match(self, is_exact_match): + self.is_exact_match = is_exact_match + + def __repr__(self) -> str: + res = f"Verse Count: {self.verse.count} Caption Event Num: {self.caption.event_num}. {self.caption.event_start_time} - {self.caption.event_end_time}\n" + res += f"### Verse:\n{self.verse}" + res += f"### Caption:\n{self.caption}" + + return res + + def to_dict(self): + payload = { + "is_exact_match": self.is_exact_match, + "verse_count": self.verse.count, + "caption_event_num": self.caption.event_num, + "similarity": self.score, + "verse": self.verse.to_dict(), + "caption": self.caption.to_dict(), + } + + return payload + + +def main(cfg={}): + num_cli_args = len(sys.argv) - 1 + caption_file_source = sys.argv[1] if num_cli_args > 0 else "chalisa.json" + verse_file_source = sys.argv[2] if num_cli_args > 1 else "chalisa_scraped.json" + + caption_data = read_file(cfg.get("caption_file_source", caption_file_source)) + scraped_data = read_file(cfg.get("verse_file_source", verse_file_source)) + + mapping = Mapping(ScrapedText(scraped_data), VideoCaptions(caption_data)) + mapping.dump_mapping_json("chalisa_mapping_v1.json") + + return + + +if __name__ == "__main__": + main() diff --git a/test/vyasa_web/controllers/error_html_test.exs b/test/vyasa_web/controllers/error_html_test.exs index 3ccd3160..070cbe29 100644 --- a/test/vyasa_web/controllers/error_html_test.exs +++ b/test/vyasa_web/controllers/error_html_test.exs @@ -5,10 +5,10 @@ defmodule VyasaWeb.ErrorHTMLTest do import Phoenix.Template test "renders 404.html" do - assert render_to_string(VyasaWeb.ErrorHTML, "404", "html", []) == "Not Found" + assert render_to_string(VyasaWeb.ErrorHTML, "404", "html", []) =~ "Not Found" end test "renders 500.html" do - assert render_to_string(VyasaWeb.ErrorHTML, "500", "html", []) == "Internal Server Error" + assert render_to_string(VyasaWeb.ErrorHTML, "500", "html", []) =~ "Internal Server Error" end end diff --git a/test/vyasa_web/live/text_live_test.exs b/test/vyasa_web/live/text_live_test.exs deleted file mode 100644 index 9340e955..00000000 --- a/test/vyasa_web/live/text_live_test.exs +++ /dev/null @@ -1,113 +0,0 @@ -defmodule VyasaWeb.TextLiveTest do - use VyasaWeb.ConnCase - - import Phoenix.LiveViewTest - import Vyasa.WrittenFixtures - - @create_attrs %{title: "some title"} - @update_attrs %{title: "some updated title"} - @invalid_attrs %{title: nil} - - defp create_text(_) do - text = text_fixture() - %{text: text} - end - - describe "Index" do - setup [:create_text] - - test "lists all texts", %{conn: conn, text: text} do - {:ok, _index_live, html} = live(conn, ~p"/texts") - - assert html =~ "Listing Texts" - assert html =~ text.title - end - - test "saves new text", %{conn: conn} do - {:ok, index_live, _html} = live(conn, ~p"/texts") - - assert index_live |> element("a", "New Text") |> render_click() =~ - "New Text" - - assert_patch(index_live, ~p"/texts/new") - - assert index_live - |> form("#text-form", text: @invalid_attrs) - |> render_change() =~ "can't be blank" - - assert index_live - |> form("#text-form", text: @create_attrs) - |> render_submit() - - assert_patch(index_live, ~p"/texts") - - html = render(index_live) - assert html =~ "Text created successfully" - assert html =~ "some title" - end - - test "updates text in listing", %{conn: conn, text: text} do - {:ok, index_live, _html} = live(conn, ~p"/texts") - - assert index_live |> element("#texts-#{text.id} a", "Edit") |> render_click() =~ - "Edit Text" - - assert_patch(index_live, ~p"/texts/#{text}/edit") - - assert index_live - |> form("#text-form", text: @invalid_attrs) - |> render_change() =~ "can't be blank" - - assert index_live - |> form("#text-form", text: @update_attrs) - |> render_submit() - - assert_patch(index_live, ~p"/texts") - - html = render(index_live) - assert html =~ "Text updated successfully" - assert html =~ "some updated title" - end - - test "deletes text in listing", %{conn: conn, text: text} do - {:ok, index_live, _html} = live(conn, ~p"/texts") - - assert index_live |> element("#texts-#{text.id} a", "Delete") |> render_click() - refute has_element?(index_live, "#texts-#{text.id}") - end - end - - describe "Show" do - setup [:create_text] - - test "displays text", %{conn: conn, text: text} do - {:ok, _show_live, html} = live(conn, ~p"/texts/#{text}") - - assert html =~ "Show Text" - assert html =~ text.title - end - - test "updates text within modal", %{conn: conn, text: text} do - {:ok, show_live, _html} = live(conn, ~p"/texts/#{text}") - - assert show_live |> element("a", "Edit") |> render_click() =~ - "Edit Text" - - assert_patch(show_live, ~p"/texts/#{text}/show/edit") - - assert show_live - |> form("#text-form", text: @invalid_attrs) - |> render_change() =~ "can't be blank" - - assert show_live - |> form("#text-form", text: @update_attrs) - |> render_submit() - - assert_patch(show_live, ~p"/texts/#{text}") - - html = render(show_live) - assert html =~ "Text updated successfully" - assert html =~ "some updated title" - end - end -end