From d1d46e9bdca6999c1ff48c2035a948c0d6f37792 Mon Sep 17 00:00:00 2001 From: JJ Allaire Date: Sun, 20 Mar 2016 16:59:08 +0000 Subject: [PATCH] version 0.4.2 --- DESCRIPTION | 22 + MD5 | 96 + NAMESPACE | 48 + R/accounts.R | 375 ++ R/applications.R | 305 ++ R/auth.R | 282 ++ R/bundle.R | 457 +++ R/client.R | 54 + R/config.R | 37 + R/configureApp.R | 190 + R/connect.R | 222 + R/dependencies.R | 109 + R/deployApp.R | 456 +++ R/deployDoc.R | 57 + R/deployments.R | 219 + R/http.R | 679 +++ R/ide.R | 143 + R/imports.R | 5 + R/lint-framework.R | 296 ++ R/lint-utils.R | 135 + R/linters.R | 138 + R/locale.R | 84 + R/lucid.R | 278 ++ R/restartApp.R | 34 + R/rmdindex.R | 120 + R/rpubs.R | 171 + R/rsa.R | 19 + R/rsconnect-package.R | 59 + R/servers.R | 210 + R/static-analysis.R | 0 R/tasks.R | 89 + R/terminateApp.R | 35 + R/usage.R | 149 + R/utils.R | 169 + README.md | 18 + inst/cert/cacert.pem | 3637 +++++++++++++++++ inst/examples/diamonds/server.R | 30 + inst/examples/diamonds/ui.R | 29 + inst/examples/sessioninfo/server.R | 27 + inst/examples/sessioninfo/ui.R | 12 + man/accountUsage.Rd | 34 + man/accounts.Rd | 38 + man/addAuthorizedUser.Rd | 36 + man/addLinter.Rd | 39 + man/appDependencies.Rd | 65 + man/applications.Rd | 49 + man/authorizedUsers.Rd | 16 + man/configureApp.Rd | 44 + man/connectUser.Rd | 30 + man/deployApp.Rd | 98 + man/deployDoc.Rd | 35 + man/deployments.Rd | 57 + man/lint.Rd | 22 + man/linter.Rd | 48 + man/makeLinterMessage.Rd | 20 + man/options.Rd | 49 + man/packages.Rd | 35 + man/proxies.Rd | 60 + man/removeAuthorizedUser.Rd | 33 + man/restartApp.Rd | 35 + man/rpubsUpload.Rd | 55 + man/rsconnect-package.Rd | 65 + man/servers.Rd | 68 + man/setAccountInfo.Rd | 30 + man/setProperty.Rd | 42 + man/showInvited.Rd | 31 + man/showLogs.Rd | 34 + man/showMetrics.Rd | 42 + man/showProperties.Rd | 24 + man/showUsage.Rd | 40 + man/showUsers.Rd | 31 + man/taskLog.Rd | 37 + man/tasks.Rd | 40 + man/terminateApp.Rd | 35 + man/unsetProperty.Rd | 38 + tests/testthat.R | 4 + tests/testthat/project-MASS/MASS.R | 1 + .../shiny-app-in-subdir/my-app/server.R | 0 .../testthat/shiny-app-in-subdir/my-app/ui.r | 0 tests/testthat/shiny-rmds/non-shiny-rmd.Rmd | 7 + .../testthat/shiny-rmds/shiny-rmd-dashes.Rmd | 7 + tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd | 9 + tests/testthat/shinyapp-appR/app.R | 12 + tests/testthat/shinyapp-simple/server.R | 8 + tests/testthat/shinyapp-simple/ui.R | 11 + tests/testthat/shinyapp-singleR/single.R | 12 + .../shinyapp-with-absolute-paths/College.txt | 0 .../ShinyDocument.Rmd | 55 + .../ShinyPresentation.Rmd | 50 + .../shinyapp-with-absolute-paths/server.R | 39 + .../subdir/Genetics.txt | 0 .../shinyapp-with-absolute-paths/ui.R | 33 + tests/testthat/test-bundle.R | 47 + tests/testthat/test-connect.R | 142 + tests/testthat/test-detection.R | 7 + tests/testthat/test-lint.R | 73 + .../test-shinyApp/test-shinyApp.tar.gz | Bin 0 -> 7088 bytes 97 files changed, 11467 insertions(+) create mode 100644 DESCRIPTION create mode 100644 MD5 create mode 100644 NAMESPACE create mode 100644 R/accounts.R create mode 100644 R/applications.R create mode 100644 R/auth.R create mode 100644 R/bundle.R create mode 100644 R/client.R create mode 100644 R/config.R create mode 100644 R/configureApp.R create mode 100644 R/connect.R create mode 100644 R/dependencies.R create mode 100644 R/deployApp.R create mode 100644 R/deployDoc.R create mode 100644 R/deployments.R create mode 100644 R/http.R create mode 100644 R/ide.R create mode 100644 R/imports.R create mode 100644 R/lint-framework.R create mode 100644 R/lint-utils.R create mode 100644 R/linters.R create mode 100644 R/locale.R create mode 100644 R/lucid.R create mode 100644 R/restartApp.R create mode 100644 R/rmdindex.R create mode 100644 R/rpubs.R create mode 100644 R/rsa.R create mode 100644 R/rsconnect-package.R create mode 100644 R/servers.R create mode 100644 R/static-analysis.R create mode 100644 R/tasks.R create mode 100644 R/terminateApp.R create mode 100644 R/usage.R create mode 100644 R/utils.R create mode 100644 README.md create mode 100644 inst/cert/cacert.pem create mode 100644 inst/examples/diamonds/server.R create mode 100644 inst/examples/diamonds/ui.R create mode 100644 inst/examples/sessioninfo/server.R create mode 100644 inst/examples/sessioninfo/ui.R create mode 100644 man/accountUsage.Rd create mode 100644 man/accounts.Rd create mode 100644 man/addAuthorizedUser.Rd create mode 100644 man/addLinter.Rd create mode 100644 man/appDependencies.Rd create mode 100644 man/applications.Rd create mode 100644 man/authorizedUsers.Rd create mode 100644 man/configureApp.Rd create mode 100644 man/connectUser.Rd create mode 100644 man/deployApp.Rd create mode 100644 man/deployDoc.Rd create mode 100644 man/deployments.Rd create mode 100644 man/lint.Rd create mode 100644 man/linter.Rd create mode 100644 man/makeLinterMessage.Rd create mode 100644 man/options.Rd create mode 100644 man/packages.Rd create mode 100644 man/proxies.Rd create mode 100644 man/removeAuthorizedUser.Rd create mode 100644 man/restartApp.Rd create mode 100644 man/rpubsUpload.Rd create mode 100644 man/rsconnect-package.Rd create mode 100644 man/servers.Rd create mode 100644 man/setAccountInfo.Rd create mode 100644 man/setProperty.Rd create mode 100644 man/showInvited.Rd create mode 100644 man/showLogs.Rd create mode 100644 man/showMetrics.Rd create mode 100644 man/showProperties.Rd create mode 100644 man/showUsage.Rd create mode 100644 man/showUsers.Rd create mode 100644 man/taskLog.Rd create mode 100644 man/tasks.Rd create mode 100644 man/terminateApp.Rd create mode 100644 man/unsetProperty.Rd create mode 100644 tests/testthat.R create mode 100644 tests/testthat/project-MASS/MASS.R create mode 100644 tests/testthat/shiny-app-in-subdir/my-app/server.R create mode 100644 tests/testthat/shiny-app-in-subdir/my-app/ui.r create mode 100644 tests/testthat/shiny-rmds/non-shiny-rmd.Rmd create mode 100644 tests/testthat/shiny-rmds/shiny-rmd-dashes.Rmd create mode 100644 tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd create mode 100644 tests/testthat/shinyapp-appR/app.R create mode 100644 tests/testthat/shinyapp-simple/server.R create mode 100644 tests/testthat/shinyapp-simple/ui.R create mode 100644 tests/testthat/shinyapp-singleR/single.R create mode 100644 tests/testthat/shinyapp-with-absolute-paths/College.txt create mode 100644 tests/testthat/shinyapp-with-absolute-paths/ShinyDocument.Rmd create mode 100644 tests/testthat/shinyapp-with-absolute-paths/ShinyPresentation.Rmd create mode 100644 tests/testthat/shinyapp-with-absolute-paths/server.R create mode 100644 tests/testthat/shinyapp-with-absolute-paths/subdir/Genetics.txt create mode 100644 tests/testthat/shinyapp-with-absolute-paths/ui.R create mode 100644 tests/testthat/test-bundle.R create mode 100644 tests/testthat/test-connect.R create mode 100644 tests/testthat/test-detection.R create mode 100644 tests/testthat/test-lint.R create mode 100644 tests/testthat/test-shinyApp/test-shinyApp.tar.gz diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..661c6d6 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,22 @@ +Package: rsconnect +Type: Package +Title: Deployment Interface for R Markdown Documents and Shiny + Applications +Version: 0.4.2 +Date: 2016-03-18 +Author: JJ Allaire +Maintainer: JJ Allaire +Description: Programmatic deployment interface for 'RPubs', 'shinyapps.io', and + 'RStudio Connect'. Supported content types include R Markdown documents, + Shiny applications, plots, and static web content. +Depends: R (>= 3.0.0) +Imports: digest, PKI, RCurl, RJSONIO, packrat (>= 0.4.7), yaml (>= + 2.1.5), rstudioapi (>= 0.5) +Suggests: scrypt, knitr, testthat, rmarkdown (>= 0.9.2) +Enhances: BiocInstaller +License: GPL-2 +RoxygenNote: 5.0.1 +NeedsCompilation: no +Packaged: 2016-03-20 11:36:26 UTC; jjallaire +Repository: CRAN +Date/Publication: 2016-03-20 16:59:08 diff --git a/MD5 b/MD5 new file mode 100644 index 0000000..80659ab --- /dev/null +++ b/MD5 @@ -0,0 +1,96 @@ +fcbe159bea1fde5beef0edc20a381c67 *DESCRIPTION +427ab7ac2e0ca67217ed4749bf25c172 *NAMESPACE +cff8534ef22c0bdb95c6037fcea5bc74 *R/accounts.R +d13ae61a61a925efa7d63e84638ee345 *R/applications.R +8424bebb2a0beee59ea679dd51a46c0d *R/auth.R +ae5084d59d938a071eae68a37ebb9a15 *R/bundle.R +b14c2412d4590c93553bdc9cd50cf521 *R/client.R +6a982c846156bed0d76db4f3ad1b2e07 *R/config.R +b52dfe336f8c1864ef4360dfc7a0ca16 *R/configureApp.R +9e773a9576ff568df9cf505744c797fe *R/connect.R +90ee6bd083f9362889cf2bf359cbf387 *R/dependencies.R +b70e625c201908d5e44a9ff830a518a7 *R/deployApp.R +7fca9a6e4f4aba40b8c24fe77061a040 *R/deployDoc.R +d8988fe18c53f0a75ac0bfc916d638ed *R/deployments.R +944ed36c2f9d4030253d26ea486ab278 *R/http.R +67cdbb9d22b484f86dda633a799cde52 *R/ide.R +94893857b5214d2d6f3302cfdabe25de *R/imports.R +193235456c17d12529d6a8d7e5aa5a53 *R/lint-framework.R +656b8c97713c1a6ef464624ad2ea4580 *R/lint-utils.R +5c33c426bc1e45459b531dae01662b02 *R/linters.R +2887d129be2b23082bb3adb769a1ed1f *R/locale.R +00c4103c25ebee3806c23e157240f1fa *R/lucid.R +06602a17899439afadcb22d1f3545b23 *R/restartApp.R +d74faa72d6f53434a620351194da59c6 *R/rmdindex.R +ad4749ec2c7e2e3c6d1b04d346537b9b *R/rpubs.R +2c0b66b672fd3d7bff870d60f5c93842 *R/rsa.R +8eeb03c9fe3b67ed009e51bd2d8ad8ca *R/rsconnect-package.R +dbdd6927115468561a57862525ae43a3 *R/servers.R +d41d8cd98f00b204e9800998ecf8427e *R/static-analysis.R +6eeefcee42e784a78a3636f6901cf8c9 *R/tasks.R +e2f0ce632a64c36f55578c1c1b7a9996 *R/terminateApp.R +d304e24ae2cacf2e86c933c4a92d893e *R/usage.R +d001133841e767d6020fd403307a4171 *R/utils.R +5cce34889f56dce293f6864a48357e0c *README.md +489f971dab5501dc695fb7a6ee19a374 *inst/cert/cacert.pem +0e676d39107e483449f030931e762249 *inst/examples/diamonds/server.R +ff0dcf5b346392cd5fd6cccede09ee46 *inst/examples/diamonds/ui.R +07f348f5f8043e8826edb7716519edd0 *inst/examples/sessioninfo/server.R +9802743e31c9f275a609b2346d5f9444 *inst/examples/sessioninfo/ui.R +ea4e6c8a514ad0d52b861e8007d81449 *man/accountUsage.Rd +09c29a0a772094dacd9a36ca2f53f977 *man/accounts.Rd +e4feaaff9e9c9f7e453d578434789c47 *man/addAuthorizedUser.Rd +fa01b42fc2c963a8015843b995122bca *man/addLinter.Rd +e224b0ad5d4690fcb42a6d40774e9231 *man/appDependencies.Rd +1d89a76d4083ac835e2a58b83de22313 *man/applications.Rd +028703e29901f5ab20b85d7a8af27a56 *man/authorizedUsers.Rd +9ec2509d69ec08566952581931051b4c *man/configureApp.Rd +94956d4347e48e58d1c946077a7a26b7 *man/connectUser.Rd +617f0a7632346c204d639f439263ee3a *man/deployApp.Rd +81e4a73ac89f4368c3d86d3f6c0f61f7 *man/deployDoc.Rd +fd650d746beacaff226a7164db44d9c3 *man/deployments.Rd +f41ec397391215d328db9afc28bb051b *man/lint.Rd +bf0eb6b87c38b2bb8aa11a3bc562433d *man/linter.Rd +846a2554ba89618a5a4aee9e65721f66 *man/makeLinterMessage.Rd +d4297f272e0653b826ad6b2adb701214 *man/options.Rd +775faea4c583e994d1b7f82b64ec8fed *man/packages.Rd +baa794ec9d4c543f6e278f3818beb426 *man/proxies.Rd +1ad302fa4208bbfd9118b06edf8d7af5 *man/removeAuthorizedUser.Rd +9192073096ba044bf98accc6c86652e6 *man/restartApp.Rd +fb18f9ac05972441dcb6ade14abc7173 *man/rpubsUpload.Rd +a0dd7cc000a99c2e8f65ff21238a5bb4 *man/rsconnect-package.Rd +2fc15d27581c40fafd44b6ee843cb92c *man/servers.Rd +0f21865a54759aa9c2b55e45bb015b30 *man/setAccountInfo.Rd +50e91bdb4c26a5b2812adaec60fdcc3c *man/setProperty.Rd +199bea2ee455344c422e21422241a7dc *man/showInvited.Rd +6a96442cedb8308fa4117423ab00cc1b *man/showLogs.Rd +c6c14f2069f7884718481a44417e14f5 *man/showMetrics.Rd +7f1819f31e6f79fb67aa73a0a20e13f9 *man/showProperties.Rd +cd5d4d62c7704de13819216945b0b14a *man/showUsage.Rd +35aa7acc04899a301e95a96820671a67 *man/showUsers.Rd +987d3125aaeb8ecb00420255da34130d *man/taskLog.Rd +4602b4505e0794b6e373995a0574b4b8 *man/tasks.Rd +35a08ed7259188dd994bd979550a67b5 *man/terminateApp.Rd +f6debf5db12ff88cc485537488135012 *man/unsetProperty.Rd +51818524b66214f5b677fbb82f38af31 *tests/testthat.R +7cec49988744201b8587102340e23b16 *tests/testthat/project-MASS/MASS.R +d41d8cd98f00b204e9800998ecf8427e *tests/testthat/shiny-app-in-subdir/my-app/server.R +d41d8cd98f00b204e9800998ecf8427e *tests/testthat/shiny-app-in-subdir/my-app/ui.r +0ac9325362678856ae8cee30cfbcff6d *tests/testthat/shiny-rmds/non-shiny-rmd.Rmd +9985f91dc258e78419eca67dbe710c6a *tests/testthat/shiny-rmds/shiny-rmd-dashes.Rmd +15e53373a9b8d9de81cc74eaef9816b3 *tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd +5abf3e3f4a270eb0703eaadda9d422cf *tests/testthat/shinyapp-appR/app.R +0ef204e32d59f05adf1c2285c343193b *tests/testthat/shinyapp-simple/server.R +6c56aafc35413ea21878610ff30f170d *tests/testthat/shinyapp-simple/ui.R +5abf3e3f4a270eb0703eaadda9d422cf *tests/testthat/shinyapp-singleR/single.R +d41d8cd98f00b204e9800998ecf8427e *tests/testthat/shinyapp-with-absolute-paths/College.txt +0ffc6a3d50599e2c44f3c395fd11659d *tests/testthat/shinyapp-with-absolute-paths/ShinyDocument.Rmd +b76cecaa26a1fb5b2415bf59aa4f39f5 *tests/testthat/shinyapp-with-absolute-paths/ShinyPresentation.Rmd +017c0042e5680c479933ea8c1e8af5b2 *tests/testthat/shinyapp-with-absolute-paths/server.R +d41d8cd98f00b204e9800998ecf8427e *tests/testthat/shinyapp-with-absolute-paths/subdir/Genetics.txt +e98f61892e82da15198be70b682f7ffb *tests/testthat/shinyapp-with-absolute-paths/ui.R +21e767b15663b1126344a49efb1e4c67 *tests/testthat/test-bundle.R +7b29497cc88324d6995e57bf6494ca18 *tests/testthat/test-connect.R +8367e7d98f152dcebd18d01138d4bf17 *tests/testthat/test-detection.R +a155158b81acfd6af4fd25f913869d97 *tests/testthat/test-lint.R +3d03aed29a634daf1098730366428231 *tests/testthat/test-shinyApp/test-shinyApp.tar.gz diff --git a/NAMESPACE b/NAMESPACE new file mode 100644 index 0000000..116c747 --- /dev/null +++ b/NAMESPACE @@ -0,0 +1,48 @@ +# Generated by roxygen2: do not edit by hand + +export(accountInfo) +export(accountUsage) +export(accounts) +export(addAuthorizedUser) +export(addConnectServer) +export(addLinter) +export(addServer) +export(appDependencies) +export(applications) +export(authorizedUsers) +export(configureApp) +export(connectUser) +export(deployApp) +export(deployDoc) +export(deployments) +export(discoverServers) +export(lint) +export(linter) +export(removeAccount) +export(removeAuthorizedUser) +export(removeServer) +export(restartApp) +export(rpubsUpload) +export(serverInfo) +export(servers) +export(setAccountInfo) +export(setProperty) +export(showInvited) +export(showLogs) +export(showMetrics) +export(showProperties) +export(showUsage) +export(showUsers) +export(taskLog) +export(tasks) +export(terminateApp) +export(unsetProperty) +importFrom(stats,na.omit) +importFrom(stats,setNames) +importFrom(utils,available.packages) +importFrom(utils,contrib.url) +importFrom(utils,formatUL) +importFrom(utils,getFromNamespace) +importFrom(utils,glob2rx) +importFrom(utils,packageVersion) +importFrom(utils,read.csv) diff --git a/R/accounts.R b/R/accounts.R new file mode 100644 index 0000000..43d407c --- /dev/null +++ b/R/accounts.R @@ -0,0 +1,375 @@ +#' Account Management Functions +#' +#' Functions to enumerate and remove accounts on the local system. Prior to +#' deploying applications you need to register your account on the local system. +#' +#' You register an account using the \code{\link{setAccountInfo}} function (for +#' ShinyApps) or \code{\link{connectUser}} function (for other servers). You can +#' subsequently remove the account using the \code{removeAccount} function. +#' +#' The \code{accounts} and \code{accountInfo} functions are provided for viewing +#' previously registered accounts. +#' +#' @param name Name of account +#' @param server Name of the server on which the account is registered +#' (optional; see \code{\link{servers}}) +#' +#' @return \code{accounts} returns a data frame with the names of all accounts +#' registered on the system and the servers on which they reside. +#' \code{accountInfo} returns a list with account details. +#' +#' @rdname accounts +#' @export +accounts <- function(server = NULL) { + path <- accountsConfigDir() + if (!is.null(server)) + path <- file.path(path, server) + + # get a raw list of accounts + accountnames <- tools::file_path_sans_ext(list.files(path, + pattern=glob2rx("*.dcf"), recursive = TRUE)) + + if (length(accountnames) == 0) { + return(NULL) + } + + # convert to a data frame + servers <- dirname(accountnames) + servers[servers == "."] <- "shinyapps.io" + names <- fileLeaf(accountnames) + data.frame(name = names, server = servers, stringsAsFactors = FALSE) +} + +#' Connect User Account +#' +#' Connect a user account to the package so that it can be used to deploy and +#' manage applications on behalf of the account. +#' +#' @param account A name for the account to connect. Optional. +#' @param server The server to connect to. Optional if there is only one server +#' registered. +#' @param quiet Whether or not to show messages and prompts while connecting the +#' account. +#' +#' @details When this function is invoked, a web browser will be opened to a +#' page on the target server where you will be prompted to enter your +#' credentials. Upon successful authentication, your local installation of +#' \pkg{rsconnect} and your server account will be paired, and you'll +#' be able to deploy and manage applications using the package without further +#' prompts for credentials. +#' +#' @export +connectUser <- function(account = NULL, server = NULL, quiet = FALSE) { + # if server isn't specified, look up the default + if (is.null(server)) { + target <- getDefaultServer(local = TRUE) + } else { + target <- serverInfo(server) + } + + if (is.null(target)) { + stop("You must specify a server to connect to.") + } + + # if account is specified and we already know about the account, get the User + # ID so we can prefill authentication fields + userId <- 0 + userAccounts <- accounts(target$name) + if (!is.null(account) && !is.null(userAccounts)) { + if (account %in% userAccounts[,"name"]) { + accountDetails <- accountInfo(account, target$name) + userId <- accountDetails$accountId + if (!quiet) { + message("The account '", account, "' is already registered; ", + "attempting to reconnect it.") + } + } + } + + # generate a token and send it to the server + token <- getAuthToken(target$name) + if (!quiet) { + message("A browser window should open; if it doesn't, you may authenticate ", + "manually by visiting ", token$claim_url, ".") + message("Waiting for authentication...") + } + utils::browseURL(token$claim_url) + + # keep trying to authenticate until we're successful + repeat { + Sys.sleep(1) + user <- getUserFromRawToken(target$url, token$token, token$private_key) + if (!is.null(user)) + break + } + + # populate the username if there wasn't one set on the server + if (nchar(user$username) == 0) { + if (!is.null(account)) + user$username <- account + else + user$username <- tolower(paste0(substr(user$first_name, 1, 1), + user$last_name)) + + # in interactive mode, prompt for a username before accepting defaults + if (!quiet && interactive() && is.null(account)) { + input <- readline(paste0("Choose a nickname for this account (default '", + user$username, "'): ")) + if (nchar(input) > 0) + user$username <- input + } + } + + # write the user info + registerUserToken(serverName = target$name, + accountName = user$username, + userId = user$id, + token = token$token, + privateKey = token$private_key) + + if (!quiet) { + message("Account registered successfully: ", user$first_name, " ", + user$last_name, " (", user$username, ")") + } +} + +#' Set ShinyApps Account Info +#' +#' Configure a ShinyApps account for publishing from this system. +#' +#' @param name Name of account to save or remove +#' @param token User token for the account +#' @param secret User secret for the account +#' +#' @examples +#' \dontrun{ +#' +#' # register an account +#' setAccountInfo("user", "token", "secret") +#' +#' # remove the same account +#' removeAccount("user") +#' } +#' +#' @export +setAccountInfo <- function(name, token, secret) { + + if (!isStringParam(name)) + stop(stringParamErrorMessage("name")) + + if (!isStringParam(token)) + stop(stringParamErrorMessage("token")) + + if (!isStringParam(secret)) + stop(stringParamErrorMessage("secret")) + + # create connect client + authInfo <- list(token = token, secret = secret) + serverInfo <- shinyappsServerInfo() + lucid <- lucidClient(serverInfo$url, authInfo) + + # get user Id + userId <- lucid$currentUser()$id + + # get account id + accountId <- NULL + accounts <- lucid$accountsForUser(userId) + for (account in accounts) { + if (identical(account$name, name)) { + accountId <- account$id + break + } + } + if (is.null(accountId)) + stop("Unable to determine account id for account named '", name, "'") + + # get the path to the config file + configFile <- accountConfigFile(name, serverInfo$name) + dir.create(dirname(configFile), recursive = TRUE, showWarnings = FALSE) + + # write the user info + write.dcf(list(name = name, + userId = userId, + accountId = accountId, + token = token, + secret = secret, + server = serverInfo$name), + configFile, + width = 100) + + # set restrictive permissions on it if possible + if (identical(.Platform$OS.type, "unix")) + Sys.chmod(configFile, mode="0600") +} + +#' @rdname accounts +#' @export +accountInfo <- function(name, server = NULL) { + + if (!isStringParam(name)) + stop(stringParamErrorMessage("name")) + + configFile <- accountConfigFile(name, server) + if (length(configFile) > 1) + stopWithMultipleAccounts(name) + if (length(configFile) == 0 || !file.exists(configFile)) + stop(missingAccountErrorMessage(name)) + + accountDcf <- readDcf(configFile, all = TRUE) + info <- as.list(accountDcf) + # remove all whitespace from private key + if (!is.null(info$private_key)) { + info$private_key <- gsub("[[:space:]]","",info$private_key) + } + info +} + +#' @rdname accounts +#' @export +removeAccount <- function(name, server = NULL) { + + if (!isStringParam(name)) + stop(stringParamErrorMessage("name")) + + configFile <- accountConfigFile(name, server) + if (!file.exists(configFile)) + stop(missingAccountErrorMessage(name)) + + file.remove(configFile) + + invisible(NULL) +} + +# given the name of a registered server, does the following: +# 1) generates a public/private key pair and token ID +# 2) pushes the public side of the key pair to the server, and obtains +# from the server a URL at which the token can be claimed +# 3) returns the token ID, private key, and claim URL +getAuthToken <- function(server, userId = 0) { + if (missing(server) || is.null(server)) { + stop("You must specify a server to connect to.") + } + target <- serverInfo(server) + + # generate a token and push it to the server + token <- generateToken() + connect <- connectClient(service = target$url, authInfo = list()) + response <- connect$addToken(list(token = token$token, + public_key = token$public_key, + user_id = as.integer(userId))) + + # return the generated token and the information needed to claim it + list( + token = token$token, + private_key = token$private_key, + claim_url = response$token_claim_url) +} + +# given a server URL and raw information about an auth token, return the user +# who owns the token, if it's claimed, and NULL if the token is unclaimed. +# raises an error on any other HTTP error. +getUserFromRawToken <- function(serverUrl, token, privateKey) { + # form a temporary client from the raw token + connect <- connectClient(service = serverUrl, authInfo = + list(token = token, + private_key = as.character(privateKey))) + + # attempt to fetch the user + user <- NULL + tryCatch({ + user <- connect$currentUser() + }, error = function(e) { + if (length(grep("HTTP 500", e$message)) == 0) { + stop(e) + } + }) + + # return the user we found + user +} + +registerUserToken <- function(serverName, accountName, userId, token, + privateKey) { + # write the user info + configFile <- accountConfigFile(accountName, serverName) + dir.create(dirname(configFile), recursive = TRUE, showWarnings = FALSE) + write.dcf(list(username = accountName, + accountId = userId, + token = token, + server = serverName, + private_key = as.character(privateKey)), + configFile) + + # set restrictive permissions on it if possible + if (identical(.Platform$OS.type, "unix")) + Sys.chmod(configFile, mode="0600") +} + +accountConfigFile <- function(name, server = NULL) { + # if no server is specified, try to find an account with the given name + # associated with any server + if (is.null(server)) { + return(list.files(accountsConfigDir(), pattern = paste0(name, ".dcf"), + recursive = TRUE, full.names = TRUE)) + } + normalizePath(file.path(accountsConfigDir(), server, + paste(name, ".dcf", sep="")), + mustWork = FALSE) +} + +accountsConfigDir <- function() { + rsconnectConfigDir("accounts") +} + +missingAccountErrorMessage <- function(name) { + paste("account named '", name, "' does not exist", sep="") +} + +resolveAccount <- function(account, server = NULL) { + + # get existing accounts + accounts <- accounts(server)[,"name"] + if (length(accounts) == 0) + stopWithNoAccount() + + # if no account was specified see if we can resolve the account to a default + if (is.null(account)) { + if (length(accounts) == 1) + accounts[[1]] + else + stopWithSpecifyAccount() + } + # account explicitly specified, confirm it exists + else { + count <- sum(accounts == account) + if (count == 0) + stopWithMissingAccount(account) + else if (count == 1) + account + else + stopWithMultipleAccounts(account) + } +} + +isShinyapps <- function(accountInfo) { + identical(accountInfo$server, "shinyapps.io") +} + +stopWithNoAccount <- function() { + stop("You must register an account using setAccountInfo prior to ", + "proceeding.", call. = FALSE) +} + +stopWithSpecifyAccount <- function() { + stop("Please specify the account name (there is more than one ", + "account registered on this system)", call. = FALSE) +} + +stopWithMissingAccount <- function(account) { + stop(missingAccountErrorMessage(account), call. = FALSE) +} + +stopWithMultipleAccounts <- function(account) { + stop("Multiple accounts with the name '", account, "' exist. Please specify ", + "the server of the account you wish to use.", call. = FALSE) +} diff --git a/R/applications.R b/R/applications.R new file mode 100644 index 0000000..17961ad --- /dev/null +++ b/R/applications.R @@ -0,0 +1,305 @@ + +#' List Deployed Applications +#' +#' List all applications currently deployed for a given account. +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @return +#' Returns a data frame with the following columns: +#' \tabular{ll}{ +#' \code{name} \tab Name of application \cr +#' \code{url} \tab URL where application can be accessed\cr +#' \code{config_url} \tab URL where application can be configured\cr +#' \code{status} \tab Current status of application. Valid values are +#' \code{pending}, \code{deploying}, \code{running}, \code{terminating}, and +#' \code{terminated}. +#' } +#' @note To register an account you call the \link{setAccountInfo} function. +#' @examples +#' \dontrun{ +#' +#' # list all applications for the default account +#' applications() +#' +#' # list all applications for a specific account +#' applications("myaccount") +#' +#' # view the list of applications in the data viewer +#' View(applications()) +#' } +#' @seealso \code{\link{deployApp}}, \code{\link{terminateApp}} +#' @export +applications <- function(account = NULL, server = NULL) { + + # resolve account and create connect client + accountDetails <- accountInfo(resolveAccount(account, server), server) + serverDetails <- serverInfo(accountDetails$server) + client <- clientForAccount(accountDetails) + + # retreive applications + apps <- client$listApplications(accountDetails$accountId) + + # extract the subset of fields we're interested in + res <- lapply(apps, `[`, c('id', 'name', 'url', 'status', 'created_time', + 'updated_time', 'deployment')) + + # promote the size and instance data to first-level fields + res <- lapply(res, function(x) { + if (! is.null(x$deployment)) { + x$size <- x$deployment$properties$application.instances.template + x$instances <- x$deployment$properties$application.instances.count + if (is.null(x$instances)) + x$instances <- NA + } else { + x$size <- NA + x$instances <- NA + } + x$deployment <- NULL + + # this may be provided by the server at some point, but for now infer it + # from the account type + x$config_url <- if (isShinyapps(accountDetails)) + paste("https://www.shinyapps.io/admin/#/application", x$id, sep = "/") + else + sub("/__api__", paste("/connect/#/apps", x$id, sep = "/"), + serverDetails$url) + + return(x) + }) + + # convert to data frame + res <- do.call(rbind, res) + + as.data.frame(res, stringsAsFactors = FALSE) +} + +resolveApplication <- function(accountDetails, appName) { + client <- clientForAccount(accountDetails) + apps <- client$listApplications(accountDetails$accountId) + for (app in apps) { + if (identical(app$name, appName)) + return (app) + } + + stopWithApplicationNotFound(appName) +} + +stopWithApplicationNotFound <- function(appName) { + stop(paste("No application named '", appName, "' is currently deployed", + sep=""), call. = FALSE) +} + +applicationTask <- function(taskDef, appName, account, server, quiet) { + + # get status function and display initial status + displayStatus <- displayStatus(quiet) + displayStatus(paste(taskDef$beginStatus, "...\n", sep="")) + + # resolve target account and application + accountDetails <- accountInfo(resolveAccount(account, server), server) + application <- resolveApplication(accountDetails, appName) + + # perform the action + client <- clientForAccount(accountDetails) + task <- taskDef$action(client, application) + client$waitForTask(task$task_id, quiet) + displayStatus(paste(taskDef$endStatus, "\n", sep = "")) + + invisible(NULL) +} + +#' Show Application Logs +#' +#' Show the logs for a deployed ShinyApps application. +#' +#' @param appPath The path to the directory or file that was deployed. +#' @param appFile The path to the R source file that contains the application +#' (for single file applications). +#' @param appName The name of the application to show logs for. May be omitted +#' if only one application deployment was made from \code{appPath}. +#' @param account The account under which the application was deployed. May be +#' omitted if only one account is registered on the system. +#' @param entries The number of log entries to show. Defaults to 50 entries. +#' @param streaming Whether to stream the logs. If \code{TRUE}, then the +#' function does not return; instead, log entries are written to the console +#' as they are made, until R is interrupted. Defaults to \code{FALSE}. +#' +#' @note This function works only for ShinyApps servers. +#' +#' @export +showLogs <- function(appPath = getwd(), appFile = NULL, appName = NULL, + account = NULL, entries = 50, streaming = FALSE) { + + # determine the log target and target account info + target <- deploymentTarget(appPath, appName, account) + accountDetails <- accountInfo(target$account) + client <- lucidClient(shinyappsServerInfo()$url, accountDetails) + application <- getAppByName(client, accountDetails, target$appName) + if (is.null(application)) + stop("No application found. Specify the application's directory, name, ", + "and/or associated account.") + + # check for streaming log compatibility + if (streaming) { + httpType <- getOption("rsconnect.http", "rcurl") + if (!identical("rcurl", httpType)) { + stop("RCurl is required to show streaming logs. Install RCurl and set ", + "rsconnect.http to 'rcurl', or call showLogs with streaming = ", + "FALSE to show a log snapshot.") + } + } + if (streaming) { + # if streaming, fork a new R process to do the blocking operation + rPath <- file.path(R.home("bin"), "R") + killfile <- tempfile() + outfile <- tempfile() + + # remove the output filewhen done. don't remove the killfile; wait for the + # forked process to do that when it's finished (happens async after we + # exit) + on.exit(unlink(outfile), add = TRUE) + + # form the command. we need to double-escape backslashes in file names, as + # they will get collapsed twice before being resolved. + cmd <- paste0("rsconnect:::showStreamingLogs(", + "account = '", target$account, "', ", + "applicationId = '", application$id, "', ", + "entries = ", entries, ", ", + "outfile = '", gsub("\\", "\\\\", outfile, fixed = TRUE), "', ", + "killfile = '", gsub("\\", "\\\\", killfile, fixed = TRUE), "')") + args <- paste("--vanilla", "--slave", paste0("-e \"", cmd, "\"")) + + # execute the command, then wait for the file to which output will be + # written to exist + system2(command = rPath, args = args, stdout = NULL, stderr = NULL, + wait = FALSE) + tries <- 0 + repeat { + tryCatch({ + Sys.sleep(0.1) + tries <- tries + 1 + logReader <- file(outfile, open = "rt", blocking = FALSE) + break + }, + error = function(e, ...) { + # if we can't open the file, keep trying until we can, or until we've + # exhausted our maximum retries (~5s). + if (tries > 500) { + stop("Failed to start log listener.") + } + }, + warning = function (...) {}) + } + + # once the file is open, close it when finished + on.exit(close(logReader), add = TRUE) + + # read from the output file until interrupted + repeat { + tryCatch({ + if (file.exists(killfile)) + break + writeLines(readLines(con = logReader, warn = FALSE)) + Sys.sleep(0.1) + }, + interrupt = function(...) { + # when R is interrupted, write out the killfile so the async process + # won't hang around listening for logs + close(file(killfile, open="wt")) + }, + error = function(e, ...) { + print(e$message) + }) + } + } else { + # if not streaming, poll for the entries directly + logs <- client$getLogs(application$id, entries, FALSE, NULL) + cat(logs) + } +} + +# blocks for network traffic--should be run in a child process +showStreamingLogs <- function(account, applicationId, entries, outfile, + killfile) { + # get account information + accountInfo <- accountInfo(account) + client <- clientForAccount(accountInfo) + + # remove the killfile when we're done + on.exit(unlink(killfile), add = TRUE) + + conn <- file(outfile, open = "wt", blocking = FALSE) + + # the server may time out the request after a few minutes--keep asking for it + # until interrupted by the presence of the killfile + skip <- 0 + repeat { + tryCatch({ + client$getLogs(applicationId, entries, TRUE, + writeLogMessage(conn, killfile, skip)) + if (file.exists(killfile)) + break + # after the first fetch, we've seen all recent entries, so show + # only new entries. unfortunately /logs/ doesn't support getting 0 + # entries, so get one and don't log it. + entries <- 1 + skip <- 1 + }, + error = function(e) { + # if the server times out, ignore the error; otherwise, let it + # bubble through + if (!identical(e$message, + "transfer closed with outstanding read data remaining")) { + stop(e) + } + }) + } +} + +writeLogMessage <- function(conn, killfile, skip) { + update = function(data) { + # write incoming log data to the console + if (skip > 0) { + skip <<- skip - 1 + } else { + cat(data, file = conn) + } + nchar(data, "bytes") + } + value = function() { + # log data is written to the console, but not returned + return("") + } + reset = function() {} + # dummy progress meter--exists to allow us to cancel requests when R is + # interrupted + progress <- function(down, up) { + tryCatch((function() { + # leave event loop for a moment to give interrupt a chance to arrive + Sys.sleep(0.01); cat("") + # check for the existance of the killfile--if it exists, abort the process + if (file.exists(killfile)) + 1L + else + 0L + })(), + # when an error or interrupt occurs, write the killfile and tell RCurl to + # abort the request + error = function(e, ...) { + close(file(killfile, open="wt")) + 1L + }, + interrupt = function(...) { + close(file(killfile, open="wt")) + 1L + } + ) + } + writer = list(update = update, value = value, reset = reset, + progress = progress) + class(writer) <- c("RCurlTextHandler", "RCurlCallbackFunction") + return(writer) +} + diff --git a/R/auth.R b/R/auth.R new file mode 100644 index 0000000..192053b --- /dev/null +++ b/R/auth.R @@ -0,0 +1,282 @@ +cleanupPasswordFile <- function(appDir) { + + # normalize appDir path and ensure it exists + appDir <- normalizePath(appDir, mustWork = FALSE) + if (!file.exists(appDir) || !file.info(appDir)$isdir) + stop(appDir, " is not a valid directory", call. = FALSE) + + # get data dir from appDir + dataDir <- file.path(appDir, "shinyapps") + + # get password file + passwordFile <- file.path(dataDir, paste("passwords", ".txt", sep="")) + + # check if password file exists + if (file.exists(passwordFile)) { + message("WARNING: Password file found! This application is configured to use scrypt ", + "authentication, which is no longer supported.\nIf you choose to proceed, ", + "all existing users of this application will be removed, ", + "and will NOT be recoverable.\nFor for more information please visit: ", + "http://shiny.rstudio.com/articles/migration.html") + response <- readline("Do you want to proceed? [Y/n]: ") + if (tolower(substring(response, 1, 1)) != "y") { + stop("Cancelled", call. = FALSE) + } else { + # remove old password file + file.remove(passwordFile) + } + } + + invisible(TRUE) +} + +#' Add authorized user to application +#' +#' @param email Email address of user to add. +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param appName Name of application. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @param sendEmail Send an email letting the user know the application +#' has been shared with them. +#' @seealso \code{\link{removeAuthorizedUser}} and \code{\link{showUsers}} +#' @note This function works only for ShinyApps servers. +#' @export +addAuthorizedUser <- function(email, appDir=getwd(), appName=NULL, + account = NULL, server=NULL, sendEmail=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # check for and remove password file + cleanupPasswordFile(appDir) + + # fetch authoriztion list + api <- clientForAccount(accountDetails) + api$inviteApplicationUser(application$id, validateEmail(email), sendEmail) + + message(paste("Added:", email, "to application", sep=" ")) + + invisible(TRUE) +} + +#' Remove authorized user from an application +#' +#' @param user The user to remove. Can be id or email address. +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param appName Name of application. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @seealso \code{\link{addAuthorizedUser}} and \code{\link{showUsers}} +#' @note This function works only for ShinyApps servers. +#' @export +removeAuthorizedUser <- function(user, appDir=getwd(), appName=NULL, + account = NULL, server=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # check and remove password file + cleanupPasswordFile(appDir) + + # get users + users <- showUsers(appDir, appName, account, server) + + if (is.numeric(user)) { + # lookup by id + if (user %in% users$id) { + user = users[users$id==user, ] + } else { + stop("User ", user, " not found", call. = FALSE) + } + } else { + # lookup by email + if (user %in% users$email) { + user = users[users$email==user, ] + } else { + stop("User \"", user, "\" not found", call. = FALSE) + } + } + + # remove user + api <- clientForAccount(accountDetails) + api$removeApplicationUser(application$id, user$id) + + message(paste("Removed:", user$email, "from application", sep=" ")) + + invisible(TRUE) +} + +#' List authorized users for an application +#' +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param appName Name of application. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @seealso \code{\link{addAuthorizedUser}} and \code{\link{showInvited}} +#' @note This function works only for ShinyApps servers. +#' @export +showUsers <- function(appDir=getwd(), appName=NULL, account = NULL, + server=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # fetch authoriztion list + api <- clientForAccount(accountDetails) + res <- api$listApplicationAuthoization(application$id) + + # get interesting fields + users <- lapply(res, function(x) { + a = list() + a$id = x$user$id + a$email = x$user$email + if (!is.null(x$account)) { + a$account <- x$account + } else { + a$account <- NA + } + return(a) + }) + + # convert to data frame + users <- do.call(rbind, users) + df <- as.data.frame(users, stringsAsFactors = FALSE) + return(df) +} + +#' List invited users for an application +#' +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param appName Name of application. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @seealso \code{\link{addAuthorizedUser}} and \code{\link{showUsers}} +#' @note This function works only for ShinyApps servers. +#' @export +showInvited <- function(appDir=getwd(), appName=NULL, account = NULL, + server=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # fetch invitation list + api <- clientForAccount(accountDetails) + res <- api$listApplicationInvitations(application$id) + + # get intersting fields + users <- lapply(res, function(x) { + a = list() + a$id = x$id + a$email = x$email + a$link = x$link + return(a) + }) + + # convert to data frame + users <- do.call(rbind, users) + df <- as.data.frame(users, stringsAsFactors = FALSE) + return(df) +} + +#' (Deprecated) List authorized users for an application +#' +#' @param appDir Directory containing application. Defaults to current working +#' directory. +#' @export +authorizedUsers <- function(appDir = getwd()) { + .Deprecated("showUsers") + + # read password file + path <- getPasswordFile(appDir) + if (file.exists(path)) { + passwords <- readPasswordFile(path) + } else { + passwords <- NULL + } + + return(passwords) +} + +validateEmail <- function(email) { + + if (is.null(email) || !grepl(".+\\@.+\\..+", email)) { + stop("Invalid email address.", call. = FALSE) + } + + invisible(email) +} + +getPasswordFile <- function(appDir) { + if (!isStringParam(appDir)) + stop(stringParamErrorMessage("appDir")) + + # normalize appDir path and ensure it exists + appDir <- normalizePath(appDir, mustWork = FALSE) + if (!file.exists(appDir) || !file.info(appDir)$isdir) + stop(appDir, " is not a valid directory", call. = FALSE) + + file.path(appDir, "shinyapps", "passwords.txt") +} + +readPasswordFile <- function(path) { + # open and read file + lines <- readLines(path) + + # extract fields + fields <- do.call(rbind, strsplit(lines, ":")) + users <- fields[,1] + hashes <- fields[,2] + + # convert to data frame + df <- data.frame(user=users, hash=hashes, stringsAsFactors=FALSE) + + # return data frame + return(df) +} + +writePasswordFile <- function(path, passwords) { + + # open and file + f = file(path, open="w") + on.exit(close(f), add = TRUE) + + # write passwords + apply(passwords, 1, function(r) { + l <- paste(r[1], ":", r[2], "\n", sep="") + cat(l, file=f, sep="") + }) + message("Password file updated. You must deploy your application for these changes to take effect.") +} diff --git a/R/bundle.R b/R/bundle.R new file mode 100644 index 0000000..1e2a4ed --- /dev/null +++ b/R/bundle.R @@ -0,0 +1,457 @@ +bundleAppDir <- function(appDir, appFiles, appPrimaryDoc = NULL) { + # create a directory to stage the application bundle in + bundleDir <- tempfile() + dir.create(bundleDir, recursive = TRUE) + on.exit(unlink(bundleDir), add = TRUE) + + # copy the files into the bundle dir + for (file in appFiles) { + from <- file.path(appDir, file) + to <- file.path(bundleDir, file) + # if deploying a single-file Shiny application, name it "app.R" so it can + # be run as an ordinary Shiny application + if (is.character(appPrimaryDoc) && + tolower(tools::file_ext(appPrimaryDoc)) == "r" && + file == appPrimaryDoc) { + to <- file.path(bundleDir, "app.R") + } + if (!file.exists(dirname(to))) + dir.create(dirname(to), recursive = TRUE) + file.copy(from, to) + } + bundleDir +} + +bundleFiles <- function(appDir) { + # determine the files that will be in the bundle (exclude rsconnect dir + # as well as common hidden files) + files <- list.files(appDir, recursive = TRUE, all.files = TRUE, + full.names = FALSE) + files <- files[!grepl(glob2rx("rsconnect/*"), files)] + files <- files[!grepl(glob2rx(".svn/*"), files)] + files <- files[!grepl(glob2rx(".git/*"), files)] + files <- files[!grepl(glob2rx(".Rproj.user/*"), files)] + files <- files[!grepl(glob2rx("*.Rproj"), files)] + files <- files[!grepl(glob2rx(".DS_Store"), files)] + files <- files[!grepl(glob2rx(".gitignore"), files)] + files <- files[!grepl(glob2rx("packrat/*"), files)] + files +} + +bundleApp <- function(appName, appDir, appFiles, appPrimaryDoc, assetTypeName, + contentCategory) { + + # infer the mode of the application from its layout + appMode <- inferAppMode(appDir, appPrimaryDoc, appFiles) + hasParameters <- appHasParameters(appDir, appFiles) + + # copy files to bundle dir to stage + bundleDir <- bundleAppDir(appDir, appFiles, appPrimaryDoc) + + # get application users (for non-document deployments) + users <- NULL + if (is.null(appPrimaryDoc)) { + users <- suppressWarnings(authorizedUsers(appDir)) + } + + # generate the manifest and write it into the bundle dir + manifestJson <- enc2utf8(createAppManifest(bundleDir, appMode, + contentCategory, hasParameters, + appPrimaryDoc, + assetTypeName, users)) + writeLines(manifestJson, file.path(bundleDir, "manifest.json"), + useBytes = TRUE) + + # if necessary write an index.htm for shinydoc deployments + indexFiles <- writeRmdIndex(appName, bundleDir) + on.exit(unlink(indexFiles), add = TRUE) + + # create the bundle and return its path + prevDir <- setwd(bundleDir) + on.exit(setwd(prevDir), add = TRUE) + bundlePath <- tempfile("rsconnect-bundle", fileext = ".tar.gz") + utils::tar(bundlePath, files = ".", compression = "gzip") + bundlePath +} + +yamlFromRmd <- function(filename) { + lines <- readLines(filename, warn = FALSE, encoding = "UTF-8") + delim <- grep("^(---|\\.\\.\\.)\\s*$", lines) + if (length(delim) >= 2) { + # If at least two --- or ... lines were found... + if (delim[[1]] == 1 || all(grepl("^\\s*$", lines[1:delim[[1]]]))) { + # and the first is a --- + if(grepl("^---\\s*$", lines[delim[[1]]])) { + # ...and the first --- line is not preceded by non-whitespace... + if (diff(delim[1:2]) > 1) { + # ...and there is actually something between the two --- lines... + yamlData <- paste(lines[(delim[[1]] + 1):(delim[[2]] - 1)], + collapse = "\n") + return(yaml::yaml.load(yamlData)) + } + } + } + } + return(NULL) +} + +appHasParameters <- function(appDir, files) { + rmdFiles <- grep("^[^/\\\\]+\\.rmd$", files, ignore.case = TRUE, perl = TRUE, + value = TRUE) + if (length(rmdFiles) > 0) { + for (rmdFile in rmdFiles) { + filename <- file.path(appDir, rmdFile) + yaml <- yamlFromRmd(filename) + if (!is.null(yaml)) { + params <- yaml[["params"]] + # We don't care about deep parameter processing, only that they exist. + return(!is.null(params) && length(params) > 0) + } + } + } + FALSE +} + +isShinyRmd <- function(filename) { + yaml <- yamlFromRmd(filename) + if (!is.null(yaml)) { + runtime <- yaml[["runtime"]] + if (!is.null(runtime) && identical(runtime, "shiny")) { + # ...and "runtime: shiny", then it's a dynamic Rmd. + return(TRUE) + } + } + return(FALSE) +} + +inferAppMode <- function(appDir, appPrimaryDoc, files) { + # single-file Shiny application + if (!is.null(appPrimaryDoc) && + tolower(tools::file_ext(appPrimaryDoc)) == "r") { + return("shiny") + } + + # shiny directory + shinyFiles <- grep("^(server|app).r$", files, ignore.case = TRUE, perl = TRUE) + if (length(shinyFiles) > 0) { + return("shiny") + } + + rmdFiles <- grep("^[^/\\\\]+\\.rmd$", files, ignore.case = TRUE, perl = TRUE, + value = TRUE) + + # if there are one or more R Markdown documents, use the Shiny app mode if any + # are Shiny documents + if (length(rmdFiles) > 0) { + for (rmdFile in rmdFiles) { + if (isShinyRmd(file.path(appDir, rmdFile))) { + return("rmd-shiny") + } + } + return("rmd-static") + } + + # no renderable content here; if there's at least one file, we can just serve + # it as static content + if (length(files) > 0) { + return("static") + } + + # there doesn't appear to be any content here we can use + return(NA) +} + +## check for extra dependencies congruent to application mode +inferDependencies <- function(appMode, hasParameters) { + deps <- c() + if (grepl("\\brmd\\b", appMode)) { + if (hasParameters) { + # An Rmd with parameters needs shiny to run the customization app. + deps <- c(deps, "shiny") + } + deps <- c(deps, "rmarkdown") + } + if (grepl("\\bshiny\\b", appMode)) { + deps <- c(deps, "shiny") + } + unique(deps) +} + +createAppManifest <- function(appDir, appMode, contentCategory, hasParameters, + appPrimaryDoc, assetTypeName, users) { + + # provide package entries for all dependencies + packages <- list() + # potential error messages + msg <- NULL + + # get package dependencies for non-static content deployment + if (!identical(appMode, "static")) { + + # detect dependencies including inferred dependences + deps = snapshotDependencies(appDir, inferDependencies(appMode, hasParameters)) + + # construct package list from dependencies + for (i in seq.int(nrow(deps))) { + name <- deps[i, "Package"] + + # get package info + info <- as.list(deps[i, c('Source', + 'Repository')]) + + # include github package info + info <- c(info, as.list(deps[i, grep('Github', colnames(deps), perl = TRUE, value = TRUE)])) + + # get package description + # TODO: should we get description from packrat/desc folder? + info$description = suppressWarnings(utils::packageDescription(name)) + + # if description is NA, application dependency may not be installed + if (is.na(info$description[1])) { + msg <- c(msg, paste0(capitalize(assetTypeName), " depends on package \"", + name, "\" but it is not installed. Please resolve ", + "before continuing.")) + next + } + + # validate package source (returns an error message if there is a problem) + msg <- c(msg, validatePackageSource(deps[i, ])) + + # good to go + packages[[name]] <- info + } + } + if (length(msg)) stop(paste(formatUL(msg, '\n*'), collapse = '\n'), call. = FALSE) + + # build the list of files to checksum + files <- list.files(appDir, recursive = TRUE, all.files = TRUE, + full.names = FALSE) + + # provide checksums for all files + filelist <- list() + for (file in files) { + checksum <- list(checksum = digest::digest(file.path(appDir, file), + algo = "md5", file = TRUE)) + filelist[[file]] <- I(checksum) + } + + # if deploying an R Markdown app or static content, infer a primary document + # if not already specified + if ((grepl("rmd", appMode, fixed = TRUE) || appMode == "static") + && is.null(appPrimaryDoc)) { + # determine expected primary document extension + ext <- ifelse(appMode == "static", "html?", "Rmd") + + # use index file if it exists + primary <- which(grepl(paste0("^index\\.", ext, "$"), files, fixed = FALSE, + ignore.case = TRUE)) + if (length(primary) == 0) { + # no index file found, so pick the first one we find + primary <- which(grepl(paste0("^.*\\.", ext, "$"), files, fixed = FALSE, + ignore.case = TRUE)) + if (length(primary) == 0) { + stop("Application mode ", appMode, " requires at least one document.") + } + } + # if we have multiple matches, pick the first + if (length(primary) > 1) + primary <- primary[[1]] + appPrimaryDoc <- files[[primary]] + } + + # create userlist + userlist <- list() + if (!is.null(users) && length(users) > 0) { + for (i in 1:nrow(users)) { + user <- users[i, "user"] + hash <- users[i, "hash"] + userinfo <- list() + userinfo$hash <- hash + userlist[[user]] <- userinfo + } + } + + # create the manifest + manifest <- list() + manifest$version <- 1 + manifest$locale <- getOption('rsconnect.locale', detectLocale()) + manifest$platform <- paste(R.Version()$major, R.Version()$minor, sep = ".") + + metadata <- list(appmode = appMode) + + # emit appropriate primary document information + primaryDoc <- ifelse(is.null(appPrimaryDoc) || + tolower(tools::file_ext(appPrimaryDoc)) == "r", + NA, appPrimaryDoc) + metadata$primary_rmd <- ifelse(grepl("\\brmd\\b", appMode), primaryDoc, NA) + metadata$primary_html <- ifelse(appMode == "static", primaryDoc, NA) + + # emit content category (plots, etc) + metadata$content_category <- ifelse(!is.null(contentCategory), + contentCategory, NA) + metadata$has_parameters <- hasParameters + + # add metadata + manifest$metadata <- metadata + + # if there are no packages set manifes$packages to NA (json null) + if (length(packages) > 0) { + manifest$packages <- I(packages) + } else { + manifest$packages <- NA + } + # if there are no files, set manifest$files to NA (json null) + if (length(files) > 0) { + manifest$files <- I(filelist) + } else { + manifest$files <- NA + } + # if there are no users set manifest$users to NA (json null) + if (length(users) > 0) { + manifest$users <- I(userlist) + } else { + manifest$users <- NA + } + + # return it as json + RJSONIO::toJSON(manifest, pretty = TRUE) +} + +validatePackageSource <- function(pkg) { + msg <- NULL + if (!(pkg$Source %in% c("CRAN", "Bioconductor", "github"))) { + if (is.null(pkg$Repository)) { + msg <- paste("The package was installed from an unsupported ", + "source '", pkg$Source, "'.", sep = "") + } + } + if (is.null(msg)) return() + msg <- paste("Unable to deploy package dependency '", pkg$Package, + "'\n\n", msg, " ", sep = "") + msg +} + +hasRequiredDevtools <- function() { + "devtools" %in% .packages(all.available = TRUE) && + packageVersion("devtools") > "1.3" +} + +snapshotLockFile <- function(appDir) { + file.path(appDir, "packrat", "packrat.lock") +} + +addPackratSnapshot <- function(bundleDir, implicit_dependencies = c()) { + # if we discovered any extra dependencies, write them to a file for packrat to + # discover when it creates the snapshot + tempDependencyFile <- file.path(bundleDir, "__rsconnect_deps.R") + if (length(implicit_dependencies) > 0) { + extraPkgDeps <- paste0(lapply(implicit_dependencies, + function(dep) { + paste0("library(", dep, ")\n") + }), + collapse="") + # emit dependencies to file + writeLines(extraPkgDeps, tempDependencyFile) + + # ensure temp file is cleaned up even if there's an error + on.exit({ + if (file.exists(tempDependencyFile)) + unlink(tempDependencyFile) + }, add = TRUE) + } + + # ensure we have an up-to-date packrat lockfile + packratVersion <- packageVersion("packrat") + requiredVersion <- "0.4.6" + if (packratVersion < requiredVersion) { + stop("rsconnect requires version '", requiredVersion, "' of Packrat; ", + "you have version '", packratVersion, "' installed.\n", + "Please install the latest version of Packrat from CRAN with:\n- ", + "install.packages('packrat', type = 'source')") + } + + # generate the packrat snapshot + performPackratSnapshot(bundleDir) + + # if we emitted a temporary dependency file for packrat's benefit, remove it + # now so it isn't included in the bundle sent to the server + if (file.exists(tempDependencyFile)) { + unlink(tempDependencyFile) + } + + # Copy all the DESCRIPTION files we're relying on into packrat/desc. + # That directory will contain one file for each package, e.g. + # packrat/desc/shiny will be the shiny package's DESCRIPTION. + # + # The server will use this to calculate package hashes. We don't want + # to rely on hashes calculated by our version of packrat, because the + # server may be running a different version. + lockFilePath <- snapshotLockFile(bundleDir) + descDir <- file.path(bundleDir, "packrat", "desc") + tryCatch({ + dir.create(descDir) + packages <- na.omit(read.dcf(lockFilePath)[,"Package"]) + lapply(packages, function(pkgName) { + descFile <- system.file("DESCRIPTION", package = pkgName) + if (!file.exists(descFile)) { + stop("Couldn't find DESCRIPTION file for ", pkgName) + } + file.copy(descFile, file.path(descDir, pkgName)) + }) + }, error = function(e) { + warning("Unable to package DESCRIPTION files: ", conditionMessage(e), call. = FALSE) + if (dirExists(descDir)) { + unlink(descDir, recursive = TRUE) + } + }) + + invisible() +} + + +# given a list of mixed files and directories, explodes the directories +# recursively into their constituent files, and returns just a list of files +explodeFiles <- function(dir, files) { + exploded <- c() + for (f in files) { + target <- file.path(dir, f) + info <- file.info(target) + if (is.na(info$isdir)) { + # don't return this file; it doesn't appear to exist + next + } else if (isTRUE(info$isdir)) { + # a directory; explode it + contents <- list.files(target, full.names = FALSE, recursive = TRUE, + include.dirs = FALSE) + exploded <- c(exploded, file.path(f, contents)) + } else { + # not a directory; an ordinary file + exploded <- c(exploded, f) + } + } + exploded +} + +performPackratSnapshot <- function(bundleDir) { + + # move to the bundle directory + owd <- getwd() + on.exit(setwd(owd), add = TRUE) + setwd(bundleDir) + + # ensure we snapshot recommended packages + srp <- packrat::opts$snapshot.recommended.packages() + packrat::opts$snapshot.recommended.packages(TRUE, persist = FALSE) + on.exit(packrat::opts$snapshot.recommended.packages(srp, persist = FALSE), + add = TRUE) + + # generate a snapshot + suppressMessages( + packrat::.snapshotImpl(project = bundleDir, + snapshot.sources = FALSE, + verbose = FALSE) + ) + + # TRUE just to indicate success + TRUE +} diff --git a/R/client.R b/R/client.R new file mode 100644 index 0000000..1af592c --- /dev/null +++ b/R/client.R @@ -0,0 +1,54 @@ +handleResponse <- function(response, jsonFilter = NULL) { + + # function to report errors + reportError <- function(msg) { + stop("HTTP ", response$status, "\n", + response$req$method, " ", response$req$protocol, "://", + response$req$host, response$req$port, response$req$path, "\n", + msg, call. = FALSE) + } + + # json responses + if (isContentType(response, "application/json")) { + + json <- RJSONIO::fromJSON(response$content, simplify = FALSE) + + if (response$status %in% 200:399) + if (!is.null(jsonFilter)) + jsonFilter(json) + else + json + else if (!is.null(json$error)) + reportError(json$error) + else + reportError(paste("Unexpected json response:", response$content)) + } + + # for html responses we can attempt to extract the body + else if (isContentType(response, "text/html")) { + + body <- regexExtract(".*?(.*?).*", response$content) + if (response$status >= 200 && response$status < 400){ + # Good response, return the body if we have one, or the content if not + if (!is.null(body)){ + body + } else{ + response$content + } + } else { + # Error response + if (!is.null(body)) + reportError(body) + else + reportError(response$content) + } + } + + # otherwise just dump the whole thing + else { + if (response$status %in% 200:399) + response$content + else + reportError(response$content) + } +} diff --git a/R/config.R b/R/config.R new file mode 100644 index 0000000..2f5b75f --- /dev/null +++ b/R/config.R @@ -0,0 +1,37 @@ + + +rsconnectConfigDir <- function(subDir = NULL) { + applicationConfigDir("connect", subDir) +} + +applicationConfigDir <- function(appName, subDir = NULL) { + + # get the home directory from the operating system (in case + # the user has redefined the meaning of ~) but fault back + # to ~ if there is no HOME variable defined + homeDir <- Sys.getenv("HOME", unset="~") + + # determine application config dir (platform specific) + sysName <- Sys.info()[['sysname']] + if (identical(sysName, "Windows")) + configDir <- Sys.getenv("APPDATA") + else if (identical(sysName, "Darwin")) + configDir <- file.path(homeDir, "Library/Application Support") + else + configDir <- Sys.getenv("XDG_CONFIG_HOME", file.path(homeDir, ".config")) + + # append the application name and optional subdir + configDir <- file.path(configDir, "R", appName) + if (!is.null(subDir)) + configDir <- file.path(configDir, subDir) + + # normalize path + configDir <- normalizePath(configDir, mustWork=FALSE) + + # ensure that it exists + if (!file.exists(configDir)) + dir.create(configDir, recursive=TRUE) + + # return it + configDir +} diff --git a/R/configureApp.R b/R/configureApp.R new file mode 100644 index 0000000..0478dec --- /dev/null +++ b/R/configureApp.R @@ -0,0 +1,190 @@ +#' Configure an Application +#' +#' Configure an application running on a remote server. +#' +#' @param appName Name of application to configure +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers (see \code{\link{servers}}) +#' @param redeploy Re-deploy application after its been configured. +#' @param size Configure application instance size +#' @param instances Configure number of application instances +#' @param quiet Request that no status information be printed to the console +#' during the deployment. +#' @examples +#' \dontrun{ +#' +#' # set instance size for an application +#' configureApp("myapp", size="xlarge") +#' } +#' @seealso \code{\link{applications}}, \code{\link{deployApp}} +#' @export +configureApp <- function(appName, appDir=getwd(), account = NULL, server = NULL, + redeploy = TRUE, size = NULL, + instances = NULL, quiet = FALSE) { + + # resolve target account and application + accountDetails <- accountInfo(resolveAccount(account, server), server) + application <- resolveApplication(accountDetails, appName) + + displayStatus <- displayStatus(quiet) + + # some properties may required a rebuild to take effect + rebuildRequired = FALSE + + # get a list of properties to set + properties <- list() + if (! is.null(size) ) { + properties[[ "application.instances.template" ]] = size + } + if (! is.null(instances) ) { + properties[[ "application.instances.count" ]] = instances + } + + # set application properties + serverDetails <- serverInfo(accountDetails$server) + lucid <- lucidClient(serverDetails$url, accountDetails) + + client <- clientForAccount(accountDetails) + for (i in names(properties)) { + propertyName <- i + propertyValue <- properties[[i]] + if (identical(client, lucid)) + lucid$setApplicationProperty(application$id, propertyName, propertyValue) + else + client$configureApplication(application$id, propertyName, propertyValue) + } + + # redeploy application if requested + if (redeploy) { + if (length(properties) > 0) { + deployApp(appDir=appDir, appName=appName, account=account, quiet=quiet, upload=rebuildRequired) + } + else + { + displayStatus("No configuration changes to deploy") + } + } +} + +#' Set Application property +#' +#' Set a property on currently deployed ShinyApps application. +#' +#' @param propertyName Name of property to set +#' @param propertyValue Nalue to set property to +#' @param appName Name of application +#' @param appPath Directory or file that was deployed. Defaults to current +#' working directory. +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param force Forcibly set the property +#' +#' @note This function only works for ShinyApps servers. +#' +#' @examples +#' \dontrun{ +#' +#' # set instance size for an application +#' setProperty("application.instances.count", 1) +#' +#' # disable application package cache +#' setProperty("application.package.cache", FALSE) +#' +#' } +#' @export +setProperty <- function(propertyName, propertyValue, appPath = getwd(), + appName = NULL, account = NULL, force = FALSE) { + + # resolve the application target and target account info + target <- deploymentTarget(appPath, appName, account) + accountDetails <- accountInfo(target$account) + serverDetails <- serverInfo(accountDetails$server) + lucid <- lucidClient(serverDetails$url, accountDetails) + application <- getAppByName(lucid, accountDetails, target$appName) + if (is.null(application)) + stop("No application found. Specify the application's directory, name, ", + "and/or associated account.") + + invisible(lucid$setApplicationProperty(application$id, + propertyName, + propertyValue, + force)) +} + +#' Unset Application property +#' +#' Unset a property on currently deployed ShinyApps application (restoring to +#' its default value) +#' +#' @param propertyName Name of property to unset +#' @param appName Name of application +#' @param appPath Directory or file that was deployed. Defaults to current +#' working directory. +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param force Forcibly unset the property +#' +#' @note This function only works for ShinyApps servers. +#' +#' @examples +#' \dontrun{ +#' +#' # unset application package cache property to revert to default +#' unsetProperty("application.package.cache") +#' +#' } +#' @export +unsetProperty <- function(propertyName, appPath = getwd(), appName=NULL, + account = NULL, force=FALSE) { + + # resolve the application target and target account info + target <- deploymentTarget(appPath, appName, account) + accountDetails <- accountInfo(target$account) + serverDetails <- serverInfo(accountDetails$server) + lucid <- lucidClient(serverDetails$url, accountDetails) + application <- getAppByName(lucid, accountInfo, target$appName) + if (is.null(application)) + stop("No application found. Specify the application's directory, name, ", + "and/or associated account.") + + invisible(lucid$unsetApplicationProperty(application$id, + propertyName, + force)) +} + + +#' Show Application property +#' +#' Show propreties of an application deployed to ShinyApps. +#' +#' @param appName Name of application +#' @param appPath Directory or file that was deployed. Defaults to current +#' working directory. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' +#' @note This function works only for ShinyApps servers. +#' +#' @export +showProperties <- function(appPath = getwd(), appName = NULL, account = NULL) { + + # determine the log target and target account info + target <- deploymentTarget(appPath, appName, account) + accountDetails <- accountInfo(target$account) + serverDetails <- serverInfo(accountDetails$server) + lucid <- lucidClient(serverDetails$url, accountDetails) + application <- getAppByName(lucid, accountDetails, target$appName) + if (is.null(application)) + stop("No application found. Specify the application's directory, name, ", + "and/or associated account.") + + # convert to data frame + res <- do.call(rbind, application$deployment$properties) + df <- as.data.frame(res, stringsAsFactors = FALSE) + names(df) <- c("value") + return(df) +} diff --git a/R/connect.R b/R/connect.R new file mode 100644 index 0000000..bcadab5 --- /dev/null +++ b/R/connect.R @@ -0,0 +1,222 @@ +userRecord <- function(email, username, first_name, last_name, password) { + list( + email = email, + username = username, + first_name = first_name, + last_name = last_name, + password = password + ) +} + +prettyPasteFields <- function(message, fields) { + header <- paste(message, ":\n- ", sep = "") + body <- paste(strwrap(paste(shQuote(fields), collapse = ", ")), + collapse = "\n") + paste(header, body, sep = "") +} + +validateUserRecord <- function(record) { + requiredFields <- c("email", "username", "first_name", "last_name", "password") + missingFields <- setdiff(requiredFields, names(record)) + extraFields <- setdiff(names(record), requiredFields) + + ## Construct error message if necessary + msg <- NULL + if (length(missingFields)) { + msg <- prettyPasteFields("The following required fields are missing", + missingFields) + } + if (length(extraFields)) { + msg <- paste(msg, prettyPasteFields("The following extraneous fields were found", + extraFields)) + } + + if (!is.null(msg)) { + stop(msg) + } + record +} + +# return a list of functions that can be used to interact with connect +connectClient <- function(service, authInfo) { + service <- parseHttpUrl(service) + + list( + + ## User API + + addUser = function(userRecord) { + userRecord <- validateUserRecord(userRecord) + handleResponse(POST_JSON(service, + authInfo, + "/users", + userRecord)) + }, + + getUser = function(userId) { + handleResponse(GET(service, authInfo, + file.path("/users", userId))) + }, + + currentUser = function() { + handleResponse(GET(service, authInfo, "/users/current/")) + }, + + ## Tokens API + + addToken = function(token) { + handleResponse(POST_JSON(service, + authInfo, + "/tokens", + token)) + }, + + getToken = function(tokenId) { + handleResponse(GET(service, authInfo, + file.path("/tokens", tokenId))) + }, + + ## Applications API + + listApplications = function(accountId, filters = NULL) { + if (is.null(filters)) { + filters <- vector() + } + path <- "/applications/" + query <- paste(filterQuery( + c("account_id", names(filters)), + c(accountId, unname(filters)) + ), collapse = "&") + listRequest(service, authInfo, path, query, "applications") + }, + + createApplication = function(name, template, accountId) { + # RSC doesn't currently use the template or account ID + # parameters; they exist for compatibility with lucid. + handleResponse(POST_JSON(service, + authInfo, + "/applications", + list(name = name))) + }, + + terminateApplication = function(applicationId) { + path <- paste("/applications/", applicationId, "/terminate", sep="") + handleResponse(POST_JSON(service, authInfo, path, list())) + }, + + uploadApplication = function(appId, bundlePath) { + path <- file.path("/applications", appId, "upload") + handleResponse(POST(service, authInfo, path, + contentType="application/x-gzip", + file=bundlePath)) + }, + + deployApplication = function(applicationId, bundleId=NULL) { + path <- paste("/applications/", applicationId, "/deploy", sep="") + json <- list() + json$bundle <- as.numeric(bundleId) + handleResponse(POST_JSON(service, authInfo, path, json)) + }, + + configureApplication = function(applicationId) { + handleResponse(GET(service, authInfo, paste( + "/applications/", applicationId, "/config", sep=""))) + }, + + getApplication = function(applicationId) { + handleResponse(GET(service, authInfo, paste0("/applications/", + applicationId))) + }, + + ## Tasks API + + listTasks = function() { + path <- "/tasks" + handleResponse(GET(service, + authInfo, + path)) + }, + + getTask = function(taskId) { + path <- file.path("/tasks", taskId) + handleResponse(GET(service, + authInfo, + path)) + }, + + killTask = function(taskId) { + path <- file.path("/tasks", taskId, "kill") + handleResponse(POST_JSON(service, + authInfo, + path, + list())) + }, + + waitForTask = function(taskId, quiet) { + start <- 0 + while (TRUE) { + path <- paste0(file.path("/tasks", taskId), "?first_status=", start) + response <- handleResponse(GET(service, authInfo, path)) + if (length(response$status) > 0) { + lapply(response$status, message) + start <- response$last_status + } + if (response$finished) { + return(response) + } + Sys.sleep(1) + } + } + + ) + +} + +listRequest = function(service, authInfo, path, query, listName, page = 100, + max=NULL) { + + # accumulate multiple pages of results + offset <- 0 + results <- list() + + while(TRUE) { + + # add query params + pathWithQuery <- paste(path, "?", query, + "&count=", page, + "&offset=", offset, + sep="") + + # make request and append the results + response <- handleResponse(GET(service, authInfo, pathWithQuery)) + results <- append(results, response[[listName]]) + + # update the offset + offset <- offset + response$count + + # get all results if no max was specified + if (is.null(max)) { + max = response$total + } + + # exit if we've got them all + if (length(results) >= response$total || length(results) >= max) + break + } + + return(results) +} + +filterQuery <- function(param, value, operator = NULL) { + if (is.null(operator)) { + op <- ":" + } else { + op <- paste(":", operator, ":", sep="") + } + q <- paste("filter=", param, op, value, sep="") + return(q) +} + +isContentType <- function(response, contentType) { + grepl(contentType, response$contentType, fixed = TRUE) +} diff --git a/R/dependencies.R b/R/dependencies.R new file mode 100644 index 0000000..fb863ab --- /dev/null +++ b/R/dependencies.R @@ -0,0 +1,109 @@ +#' Detect Application Dependencies +#' +#' Recursively detect all package dependencies for an application. This function +#' parses all .R files in the applicaition directory to determine what packages +#' the application depends on; and for each of those packages what other +#' packages they depend on. +#' @inheritParams deployApp +#' @param appDir Directory containing application. Defaults to current working +#' directory. +#' @return Returns a data frame listing the package +#' dependencies detected for the application: \tabular{ll}{ \code{package} +#' \tab Name of package \cr \code{version} \tab Version of package\cr } +#' @details Dependencies are determined by parsing application source code and +#' looking for calls to \code{library}, \code{require}, \code{::}, and +#' \code{:::}. +#' +#' Recursive dependencies are detected by examining the \code{Depends}, +#' \code{Imports}, and \code{LinkingTo} fields of the packages immediately +#' dependend on by the application. +#' +#' @note Since the \code{Suggests} field is not included when determining +#' recursive dependencies of packages, it's possible that not every package +#' required to run your application will be detected. +#' +#' In this case, you can force a package to be included dependency by +#' inserting call(s) to \code{require} within your source directory. This code +#' need not actually execute, for example you could create a standalone file +#' named \code{dependencies.R} with the following code: \cr \cr +#' \code{require(xts)} \cr \code{require(colorspace)} \cr +#' +#' This will force the \code{xts} and \code{colorspace} packages to be +#' installed along with the rest of your application when it is deployed. +#' @examples +#' \dontrun{ +#' +#' # dependencies for the app in the current working dir +#' appDependencies() +#' +#' # dependencies for an app in another directory +#' appDependencies("~/projects/shiny/app1") +#' } +#' @seealso \link[rsconnect:rsconnectPackages]{Using Packages with rsconnect} +#' @export +appDependencies <- function(appDir = getwd(), appFiles=NULL) { + # if the list of files wasn't specified, generate it + if (is.null(appFiles)) { + appFiles <- bundleFiles(appDir) + } + bundleDir <- bundleAppDir(appDir, appFiles) + deps <- snapshotDependencies(bundleDir) + data.frame(package = deps[,"Package"], + version = deps[,"Version"], + source = deps[,"Source"], + row.names = c(1:length(deps[,"Package"])), + stringsAsFactors=FALSE) +} + +snapshotDependencies <- function(appDir, implicit_dependencies=c()) { + + # create a packrat "snapshot" + addPackratSnapshot(appDir, implicit_dependencies) + + # TODO: should we care about lockfile version or packrat version? + lockFilePath <- snapshotLockFile(appDir) + df <- as.data.frame(read.dcf(lockFilePath), stringsAsFactors = FALSE) + + # get repos defined in the lockfile + repos <- gsub("[\r\n]", " ", df[1, 'Repos']) + repos <- strsplit(unlist(strsplit(repos, "\\s*,\\s*", perl = TRUE)), "=", fixed = TRUE) + repos <- setNames( + sapply(repos, "[[", 2), + sapply(repos, "[[", 1) + ) + + # get Bioconductor repos if any + biocRepos = repos[grep('BioC', names(repos), perl=TRUE, value=TRUE)] + if (length(biocRepos) > 0) { + biocPackages = available.packages(contriburl=contrib.url(biocRepos, type="source")) + } else { + biocPackages = c() + } + + # get packages records defined in the lockfile + records <- utils::tail(df, -1) + + # if the package is in a named CRAN-like repository capture it + tmp <- sapply(seq.int(nrow(records)), function(i) { + pkg <- records[i, "Package"] + source <- records[i, "Source"] + repository <- NA + # capture Bioconcutor repository + if (identical(source, "Bioconductor")) { + if (pkg %in% biocPackages) { + repository <- biocPackages[pkg, 'Repository'] + } + } else { + # capture CRAN-like repository + repository <- if (source %in% names(repos)) repos[[source]] else NA + } + repository + }) + records[, "Repository"] <- tmp + return(records) +} + +# get source packages from CRAN +availableCRANSourcePackages <- function() { + available.packages("https://cran.rstudio.com/src/contrib", type = "source") +} diff --git a/R/deployApp.R b/R/deployApp.R new file mode 100644 index 0000000..6f2956f --- /dev/null +++ b/R/deployApp.R @@ -0,0 +1,456 @@ +#' Deploy an Application +#' +#' Deploy a \link[shiny:shiny-package]{shiny} application, an R Markdown +#' document, or HTML content to a server. +#' +#' @param appDir Directory containing application. Defaults to current working +#' directory. +#' @param appFiles The files and directories to bundle and deploy (only if +#' \code{upload = TRUE}). Can be \code{NULL}, in which case all the files in +#' the directory containing the application are bundled. Takes precedence over +#' \code{appFileManifest} if both are supplied. +#' @param appFileManifest An alternate way to specify the files to be deployed; +#' a file containing the names of the files, one per line, relative to the +#' \code{appDir}. +#' @param appPrimaryDoc If the application contains more than one document, this +#' parameter indicates the primary one, as a path relative to \code{appDir}. +#' Can be \code{NULL}, in which case the primary document is inferred from the +#' contents being deployed. +#' @param appSourceDoc If the application is composed of static files (e.g +#' HTML), this parameter indicates the source document, if any, as a fully +#' qualified path. Deployment information returned by +#' \code{\link{deployments}} is associated with the source document. +#' @param appName Name of application (names must be unique within an +#' account). Defaults to the base name of the specified \code{appDir}. +#' @param contentCategory Optional; the kind of content being deployed (e.g. +#' \code{"plot"}, \code{"document"}, or \code{"application"}). +#' @param account Account to deploy application to. This +#' parameter is only required for the initial deployment of an application +#' when there are multiple accounts configured on the system (see +#' \link{accounts}). +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @param upload If \code{TRUE} (the default) then the application is uploaded +#' from the local system prior to deployment. If \code{FALSE} then it is +#' re-deployed using the last version that was uploaded. +#' @param launch.browser If true, the system's default web browser will be +#' launched automatically after the app is started. Defaults to \code{TRUE} in +#' interactive sessions only. +#' @param quiet Request that no status information be printed to the console +#' during the deployment. +#' @param lint Lint the project before initiating deployment, to identify +#' potentially problematic code? +#' @param metadata Additional metadata fields to save with the deployment +#' record. These fields will be returned on subsequent calls to +#' \code{\link{deployments}}. +#' @examples +#' \dontrun{ +#' +#' # deploy the application in the current working dir +#' deployApp() +#' +#' # deploy an application in another directory +#' deployApp("~/projects/shiny/app1") +#' +#' # deploy using an alternative application name +#' deployApp("~/projects/shiny/app1", appName = "myapp") +#' +#' # deploy specifying an explicit account name, then +#' # redeploy with no arguments (will automatically use +#' # the previously specified account) +#' deployApp(account = "jsmith") +#' deployApp() +#' +#' # deploy but don't launch a browser when completed +#' deployApp(launch.browser = FALSE) +#' } +#' @seealso \code{\link{applications}}, \code{\link{terminateApp}}, and +#' \code{\link{restartApp}} +#' @export +deployApp <- function(appDir = getwd(), + appFiles = NULL, + appFileManifest = NULL, + appPrimaryDoc = NULL, + appSourceDoc = NULL, + appName = NULL, + contentCategory = NULL, + account = NULL, + server = NULL, + upload = TRUE, + launch.browser = getOption("rsconnect.launch.browser", + interactive()), + quiet = FALSE, + lint = TRUE, + metadata = list()) { + + if (!isStringParam(appDir)) + stop(stringParamErrorMessage("appDir")) + + # normalize appDir path and ensure it exists + appDir <- normalizePath(appDir, mustWork = FALSE) + if (!file.exists(appDir)) { + stop(appDir, " does not exist") + } + + # create the full path that we'll deploy (append document if requested) + appPath <- appDir + if (!is.null(appSourceDoc) && nchar(appSourceDoc) > 0) { + appPath <- appSourceDoc + } else if (!is.null(appPrimaryDoc) && nchar(appPrimaryDoc) > 0) { + appPath <- file.path(appPath, appPrimaryDoc) + if (!file.exists(appPath)) { + stop(appPath, " does not exist") + } + } + + # if a specific file is named, make sure it's an Rmd or HTML, and just deploy + # a single document in this case (this will call back to deployApp with a list + # of supporting documents) + rmdFile <- "" + if (!file.info(appDir)$isdir) { + if (grepl("\\.Rmd$", appDir, ignore.case = TRUE) || + grepl("\\.html?$", appDir, ignore.case = TRUE)) { + return(deployDoc(appDir, appName = appName, account = account, + server = server, upload = upload, + launch.browser = launch.browser, quiet = quiet, + lint = lint)) + } else { + stop(appDir, " must be a directory, an R Markdown document, or an HTML ", + "document.") + } + } + + # figure out what kind of thing we're deploying + if (!is.null(contentCategory)) { + assetTypeName <- contentCategory + } else if (!is.null(appPrimaryDoc)) { + assetTypeName <- "document" + } else { + assetTypeName <- "application" + } + + # build the list of files to deploy -- implicitly (directory contents), + # explicitly via list, or explicitly via manifest + if (is.null(appFiles)) { + if (is.null(appFileManifest)) { + # no files supplied at all, just bundle the whole directory + appFiles <- bundleFiles(appDir) + } else { + # manifest file provided, read it and apply + if (!isStringParam(appFileManifest)) + stop(stringParamErrorMessage("appFileManifest")) + if (!file.exists(appFileManifest)) + stop(appFileManifest, " was specified as a file manifest, but does not", + "exist.") + + # read the filenames from the file + manifestLines <- readLines(appFileManifest, warn = FALSE) + + # remove empty/comment lines and explode remaining + manifestLines <- manifestLines[nzchar(manifestLines)] + manifestLines <- manifestLines[!grepl("^#", manifestLines)] + appFiles <- explodeFiles(appDir, manifestLines) + } + } else { + # file list provided directly + appFiles <- explodeFiles(appDir, appFiles) + } + + if (isTRUE(lint)) { + lintResults <- lint(appDir, appFiles, appPrimaryDoc) + + if (hasLint(lintResults)) { + + if (interactive()) { + # if enabled, show warnings in friendly marker tab in addition to + # printing to console + if (getOption("rsconnect.rstudio_source_markers", TRUE) && + rstudioapi::hasFun("sourceMarkers")) + { + showRstudioSourceMarkers(appDir, lintResults) + } + message("The following potential problems were identified in the project files:\n") + printLinterResults(lintResults) + response <- readline("Do you want to proceed with deployment? [Y/n]: ") + if (tolower(substring(response, 1, 1)) != "y") { + message("Cancelling deployment.") + return(invisible(lintResults)) + } + } else { + message("The linter has identified potential problems in the project:\n") + printLinterResults(lintResults) +# message( +# "\nIf you believe these errors are spurious, run:\n\n", +# "\tdeployApp(lint = FALSE)\n\n", +# "to disable linting." +# ) + message("If your ", assetTypeName, " fails to run post-deployment, ", + "please double-check these messages.") + } + + } + + } + + if (!is.null(appName) && !isStringParam(appName)) + stop(stringParamErrorMessage("appName")) + + # try to detect encoding from the RStudio project file + .globals$encoding <- rstudioEncoding(appDir) + on.exit(.globals$encoding <- NULL, add = TRUE) + + # functions to show status (respects quiet param) + displayStatus <- displayStatus(quiet) + withStatus <- withStatus(quiet) + + # initialize connect client + + # determine the deployment target and target account info + target <- deploymentTarget(appPath, appName, account, server) + accountDetails <- accountInfo(target$account, target$server) + client <- clientForAccount(accountDetails) + + # get the application to deploy (creates a new app on demand) + withStatus(paste0("Preparing to deploy ", assetTypeName), { + application <- applicationForTarget(client, accountDetails, target) + }) + + if (upload) { + # create, and upload the bundle + withStatus(paste0("Uploading bundle for ", assetTypeName, ": ", + application$id), { + bundlePath <- bundleApp(target$appName, appDir, appFiles, + appPrimaryDoc, assetTypeName, contentCategory) + bundle <- client$uploadApplication(application$id, bundlePath) + }) + } else { + # redeploy current bundle + bundle <- application$deployment$bundle + } + + # save the deployment info for subsequent updates--we do this before + # attempting the deployment itself to make retry easy on failure + saveDeployment(appPath, + target$appName, + target$account, + accountDetails$server, + application$id, + bundle$id, + application$url, + metadata) + + # wait for the deployment to complete (will raise an error if it can't) + displayStatus(paste0("Deploying bundle: ", bundle$id, + " for ", assetTypeName, ": ", application$id, + " ...\n", sep="")) + task <- client$deployApplication(application$id, bundle$id) + taskId <- if (is.null(task$task_id)) task$id else task$task_id + response <- client$waitForTask(taskId, quiet) + + # wait 1/10th of a second for any queued output get picked by RStudio + # before emitting the final status, to ensure it's the last line the user sees + Sys.sleep(0.10) + + deploymentSucceeded <- if (is.null(response$code) || response$code == 0) { + displayStatus(paste0(capitalize(assetTypeName), " successfully deployed ", + "to ", application$url, "\n")) + # function to browse to a URL using user-supplied browser (config or final) + showURL <- function(url) { + if (isTRUE(launch.browser)) + utils::browseURL(url) + else if (is.function(launch.browser)) + launch.browser(url) + } + + # if this client supports config, see if the app needs it + if (!quiet && !is.null(client$configureApplication)) { + config <- client$configureApplication(application$id) + if (config$needs_config) { + # app needs config, finish deployment on the server + showURL(config$config_url) + return(invisible(TRUE)) + } + } + + # launch the browser if requested + showURL(application$url) + + TRUE + } else { + displayStatus(paste0(capitalize(assetTypeName), " deployment failed ", + "with error: ", response$error, "\n")) + FALSE + } + + invisible(deploymentSucceeded) +} + +# calculate the deployment target based on the passed parameters and +# any saved deployments that we have +deploymentTarget <- function(appPath, appName, account, server = NULL) { + + # read existing accounts + accounts <- accounts(server)[,"name"] + if (length(accounts) == 0) + stopWithNoAccount() + + # validate account if provided + if (!is.null(account)) { + if (!account %in% accounts) + stop(paste("Unknown account name '", account, "' (you can use the ", + "setAccountInfo function to add a new account)", sep = ""), + call. = FALSE) + } + + # read existing deployments + appDeployments <- deployments(appPath = appPath) + + # function to create a deployment target list (checks whether the target + # is an update and adds that field) + createDeploymentTarget <- function(appName, account, server) { + + # check to see whether this is an update + existingDeployment <- deployments(appPath, + nameFilter = appName, + accountFilter = account, + serverFilter = server) + isUpdate <- nrow(existingDeployment) == 1 + + list(appName = appName, account = account, isUpdate = isUpdate, + server = server) + } + + + # both appName and account explicitly specified + if (!is.null(appName) && !is.null(account)) { + + createDeploymentTarget(appName, account, server) + + } + + # just appName specified + else if (!is.null(appName)) { + + # find any existing deployments of this application + appDeployments <- deployments(appPath, + nameFilter = appName) + + # if there are none then we can create it if there is a single account + # registered that we can default to + if (nrow(appDeployments) == 0) { + if (length(accounts) == 1) { + # read the server associated with the account + accountDetails <- accountInfo(accounts, server) + createDeploymentTarget(appName, accounts, accountDetails$server) + } else { + stopWithSpecifyAccount() + } + } + + # single existing deployment + else if (nrow(appDeployments) == 1) { + createDeploymentTarget(appName, appDeployments$account, + appDeployments$server) + } + + # multiple existing deployments + else if (nrow(appDeployments) > 1) { + stop(paste("Please specify the account you want to deploy '", appName, + "' to (you have previously deployed this application to ", + "more than one account).", sep = ""), call. = FALSE) + } + + } + + # just account/server specified, that's fine we just default the app name + # based on the basename of the application directory + else if (!is.null(account) || !is.null(server)) { + if (is.null(account)) { + account <- accounts(server)[,"name"] + if (length(account) > 1) { + stopWithSpecifyAccount() + } + } + accountDetails <- accountInfo(account, server) + createDeploymentTarget( + tools::file_path_sans_ext(basename(appPath)), + account, accountDetails$server) + } + + # neither specified but a single existing deployment + else if (nrow(appDeployments) == 1) { + + createDeploymentTarget(appDeployments$name, + appDeployments$account, + appDeployments$server) + + } + + # neither specified and no existing deployments + else if (nrow(appDeployments) == 0) { + + # single account we can default to + if (length(accounts) == 1) { + accountDetails <- accountInfo(accounts) + createDeploymentTarget( + tools::file_path_sans_ext(basename(appPath)), + accounts, accountDetails$server) + } + else + stop("Please specify the account and server to which you want to deploy ", + "the application (there is more than one account registered ", + "on this system).", call. = FALSE) + + } + + # neither specified and multiple existing deployments + else { + + stop("Unable to deploy using default arguments (multiple existing ", + "deployments from this application directory already exist). ", + "Please specify appName and/or account name explicitly.", + call. = FALSE) + + } +} + +# get the record for the application of the given name in the given account, or +# NULL if no application exists by that name +getAppByName <- function(client, accountInfo, name) { + # NOTE: returns a list with 0 or 1 elements + app <- client$listApplications(accountInfo$accountId, filters = list(name = name)) + if (length(app)) app[[1]] else NULL +} + +# get the record for the application with the given ID in the given account +getAppById <- function(id, account = NULL, server = NULL) { + accountDetails <- accountInfo(resolveAccount(account, server), server) + client <- clientForAccount(accountDetails) + client$getApplication(id) +} + +applicationForTarget <- function(client, accountInfo, target) { + + # list the existing applications for this account and see if we + # need to create a new application + app <- getAppByName(client, accountInfo, target$appName) + + # if there is no record of deploying this application locally however there + # is an application of that name already deployed then confirm + if (!target$isUpdate && !is.null(app) && interactive()) { + prompt <- paste("Update application currently deployed at\n", app$url, + "? [Y/n] ", sep="") + input <- readline(prompt) + if (nzchar(input) && !identical(input, "y") && !identical(input, "Y")) + stop("Application deployment cancelled", call. = FALSE) + } + + # create the application if we need to + if (is.null(app)) { + app <- client$createApplication(target$appName, "shiny", + accountInfo$accountId) + } + + # return the application + app +} diff --git a/R/deployDoc.R b/R/deployDoc.R new file mode 100644 index 0000000..c3cf2dc --- /dev/null +++ b/R/deployDoc.R @@ -0,0 +1,57 @@ +#' Deploy a Document +#' +#' Deploys an application consisting of a single R Markdown document or other +#' single file (such as an HTML or PDF document). +#' +#' @param doc Path to the document to deploy. +#' @param ... Additional arguments to \code{\link{deployApp}}. Do not supply +#' \code{appDir}, \code{appFiles}, or \code{appPrimaryDoc}; +#' these three parameters are automatically generated by \code{deployDoc} from +#' the document. +#' +#' @details When deploying an R Markdown document, any files which are +#' required to render and display the file must be deployed. +#' +#' This method discovers these additional files using +#' \code{\link[rmarkdown:find_external_resources]{find_external_resources}} +#' from \pkg{rmarkdown}. +#' +#' If you find that the document is missing dependencies, either specify the +#' dependencies explicitly in the document (the documentation for +#' \code{\link[rmarkdown:find_external_resources]{find_external_resources}} +#' explains how to do this), or call \code{\link{deployApp}} directly and +#' specify your own file list in the \code{appFiles} parameter. +#' +#' @export +deployDoc <- function(doc, ...) { + # validate inputs + if (!file.exists(doc)) { + stop("The document '", doc, "' does not exist.") + } + if (!requireNamespace("rmarkdown") || + packageVersion("rmarkdown") < "0.5.2") { + stop("Version 0.5.2 or later of the rmarkdown package is required to ", + "deploy individual R Markdown documents.") + } + + # default to deploying just the single file specified + qualified_doc <- normalizePath(doc, winslash = "/") + app_files <- basename(qualified_doc) + + # if this document's type supports automated resource discovery, do that now, + # and add the discovered files to the deployment list + ext <- tolower(tools::file_ext(doc)) + if (ext %in% c("rmd", "html", "htm")) { + message("Discovering document dependencies... ", appendLF = FALSE) + res <- rmarkdown::find_external_resources(qualified_doc) + message("OK") + app_files <- c(app_files, res$path) + } + + # deploy the document with the discovered dependencies + deployApp(appDir = dirname(qualified_doc), + appFiles = app_files, + appPrimaryDoc = basename(qualified_doc), + ...) +} + diff --git a/R/deployments.R b/R/deployments.R new file mode 100644 index 0000000..df03847 --- /dev/null +++ b/R/deployments.R @@ -0,0 +1,219 @@ + + +saveDeployment <- function(appPath, name, account, server, appId, bundleId, url, + metadata) { + + # create the record to write to disk + deployment <- deploymentRecord(name, account, server, appId, bundleId, url, + when = as.numeric(Sys.time()), + metadata) + + # use a long width so URLs don't line-wrap + write.dcf(deployment, deploymentFile(appPath, name, account, server), + width = 4096) + + # also save to global history + addToDeploymentHistory(appPath, deployment) + + invisible(NULL) +} + +#' List Application Deployments +#' +#' List deployment records for a given application. +#' @param appPath The path to the content that was deployed, either a directory +#' or an individual document. +#' @param nameFilter Return only deployments matching the given name (optional) +#' @param accountFilter Return only deployments matching the given account +#' (optional) +#' @param serverFilter Return only deployments matching the given server +#' (optional) +#' @param excludeOrphaned If \code{TRUE} (the default), return only deployments +#' made by a currently registered account. Deployments made from accounts that +#' are no longer registered (via e.g.\code{\link{removeAccount}}) will not be +#' returned. +#' @return +#' Returns a data frame with at least following columns: +#' \tabular{ll}{ +#' \code{name} \tab Name of deployed application\cr +#' \code{account} \tab Account owning deployed application\cr +#' \code{bundleId} \tab Identifier of deployed application's bundle\cr +#' \code{url} \tab URL of deployed application\cr +#' \code{when} \tab When the application was deployed (in seconds since the +#' epoch)\cr +#' } +#' +#' If additional metadata has been saved with the deployment record using the +#' \code{metadata} argument to \code{\link{deployApp}}, the frame will include +#' additional columns. +#' +#' @examples +#' \dontrun{ +#' +#' # Return all deployments of the ~/r/myapp directory made with the 'abc' +#' # account +#' deployments("~/r/myapp", accountFilter="abc") +#' } +#' @seealso \code{\link{applications}} to get a list of deployments from the +#' server, and \code{\link{deployApp}} to create a new deployment. +#' @export +deployments <- function(appPath, nameFilter = NULL, accountFilter = NULL, + serverFilter = NULL, excludeOrphaned = TRUE) { + + # calculate rsconnect dir + rsconnectDir <- rsconnectRootPath(appPath) + + # calculate migration dir--all shinyapps deployment records go into the root + # folder since it wasn't possible to deploy individual docs using the + # shinyapps package + migrateRoot <- if (isDocumentPath(appPath)) dirname(appPath) else appPath + + # migrate shinyapps package created records if necessary + shinyappsDir <- file.path(migrateRoot, "shinyapps") + if (file.exists(shinyappsDir)) { + migrateDir <- file.path(migrateRoot, "rsconnect") + for (shinyappsFile in list.files(shinyappsDir, glob2rx("*.dcf"), + recursive = TRUE)) { + # read deployment record + shinyappsDCF <- file.path(shinyappsDir, shinyappsFile) + deployment <- as.data.frame(readDcf(shinyappsDCF), + stringsAsFactors = FALSE) + deployment$server <- "shinyapps.io" + + # write the new record + rsconnectDCF <- file.path(migrateDir, "shinyapps.io", shinyappsFile) + dir.create(dirname(rsconnectDCF), showWarnings = FALSE, recursive = TRUE) + write.dcf(deployment, rsconnectDCF) + + # remove old DCF + file.remove(shinyappsDCF) + } + + # remove shinyapps dir if it's completely empty + remainingFiles <- list.files(shinyappsDir, + recursive = TRUE, + all.files = TRUE) + if (length(remainingFiles) == 0) + unlink(shinyappsDir, recursive = TRUE) + } + + # get list of active accounts + activeAccounts <- accounts() + + # build list of deployment records + deploymentRecs <- deploymentRecord(name = character(), + account = character(), + server = character(), + appId = character(), + bundleId = character(), + url = character(), + when = numeric()) + for (deploymentFile in list.files(rsconnectDir, glob2rx("*.dcf"), + recursive = TRUE)) { + + # derive account and server name from deployment record location + account <- basename(dirname(deploymentFile)) + server <- basename(dirname(dirname(deploymentFile))) + + # apply optional server filter + if (!is.null(serverFilter) && !identical(serverFilter, server)) + next + + # apply optional account filter + if (!is.null(accountFilter) && !identical(accountFilter, account)) + next + + # apply optional name filter + name <- tools::file_path_sans_ext(basename(deploymentFile)) + if (!is.null(nameFilter) && !identical(nameFilter, name)) + next + + # exclude orphaned if requested (note that the virtual server "rpubs.com" + # is always considered to be registered) + if (excludeOrphaned && server != "rpubs.com") { + # filter by account name and then by server + matchingAccounts <- activeAccounts[activeAccounts[["name"]] == account,] + matchingAccounts <- + matchingAccounts[matchingAccounts[["server"]] == server,] + + # if there's no account with the given name and server, consider this + # record to be an orphan + if (nrow(matchingAccounts) == 0) + next + } + + # parse file + deployment <- as.data.frame(readDcf(file.path(rsconnectDir, deploymentFile)), + stringsAsFactors = FALSE) + + # fill in any columns missing in this record + missingCols <- setdiff(colnames(deploymentRecs), colnames(deployment)) + if (length(missingCols) > 0) { + deployment[,missingCols] <- NA + } + + # if this record contains any columns that aren't present everywhere, add + # them + extraCols <- setdiff(colnames(deployment), colnames(deploymentRecs)) + if (length(extraCols) > 0 && nrow(deploymentRecs) > 0) { + deploymentRecs[,extraCols] <- NA + } + + # append to record set to return + deploymentRecs <- rbind(deploymentRecs, deployment) + } + + deploymentRecs +} + +deploymentFile <- function(appPath, name, account, server) { + accountDir <- file.path(rsconnectRootPath(appPath), server, account) + if (!file.exists(accountDir)) + dir.create(accountDir, recursive = TRUE) + file.path(accountDir, paste0(name, ".dcf")) +} + +deploymentRecord <- function(name, account, server, appId, bundleId, url, when, + metadata = list()) { + # compose the standard set of fields and append any requested + as.data.frame(c( + list(name = name, + account = account, + server = server, + appId = appId, + bundleId = bundleId, + url = url, + when = when), + metadata), + stringsAsFactors = FALSE) +} + + +deploymentHistoryDir <- function() { + rsconnectConfigDir("deployments") +} + +addToDeploymentHistory <- function(appPath, deploymentRecord) { + + # path to deployments files + history <- file.path(deploymentHistoryDir(), "history.dcf") + newHistory <- file.path(deploymentHistoryDir(), "history.new.dcf") + + # add the appPath to the deploymentRecord + deploymentRecord$appPath <- appPath + + # write new history file + write.dcf(deploymentRecord, newHistory, width = 4096) + cat("\n", file = newHistory, append = TRUE) + + # append existing history to new history + if (file.exists(history)) + file.append(newHistory, history) + + # overwrite with new history + file.rename(newHistory, history) +} + + + + diff --git a/R/http.R b/R/http.R new file mode 100644 index 0000000..94c7857 --- /dev/null +++ b/R/http.R @@ -0,0 +1,679 @@ +userAgent <- function() { + paste("rsconnect", packageVersion("rsconnect"), sep="/") +} + +parseHttpUrl <- function(urlText) { + + matches <- regexec("(http|https)://([^:/#?]+)(?::(\\d+))?(.*)", urlText) + components <- regmatches(urlText, matches)[[1]] + if (length(components) == 0) + stop("Invalid url: ", urlText) + + url <- list() + url$protocol <- components[[2]] + url$host <- components[[3]] + url$port <- components[[4]] + url$path <- components[[5]] + url +} + +parseHttpHeader <- function(header) { + split <- strsplit(header, ": ")[[1]] + if (length(split) == 2) + return (list(name = split[1], value = split[2])) + else + return (NULL) +} + +parseHttpStatusCode <- function(statusLine) { + statusCode <- regexExtract("HTTP/[0-9]+\\.[0-9]+ ([0-9]+).*", statusLine) + if (is.null(statusCode)) + return (-1) + else + return (as.integer(statusCode)) +} + +readHttpResponse <- function(request, conn) { + # read status code + resp <- readLines(conn, 1) + statusCode <- parseHttpStatusCode(resp[1]) + + # read response headers + contentLength <- NULL + location <- NULL + repeat { + resp <- readLines(conn, 1) + if (nzchar(resp) == 0) + break() + + header <- parseHttpHeader(resp) + if (!is.null(header)) + { + if (identical(header$name, "Content-Type")) + contentType <- header$value + if (identical(header$name, "Content-Length")) + contentLength <- as.integer(header$value) + if (identical(header$name, "Location")) + location <- header$value + } + } + + # read the response content + content <- rawToChar(readBin(conn, what = 'raw', n=contentLength)) + + # emit JSON trace if requested + if (httpTraceJson() && identical(contentType, "application/json")) + cat(paste0(">> ", content, "\n")) + + # return list + list(req = request, + status = statusCode, + location = location, + contentType = contentType, + content = content) +} + + +# internal sockets implementation of upload +httpInternal <- function(protocol, + host, + port, + method, + path, + headers, + contentType = NULL, + file = NULL, + writer = NULL, + timeout = NULL) { + + if (!is.null(file) && is.null(contentType)) + stop("You must specify a contentType for the specified file") + + # default port to 80 if necessary + if (!nzchar(port)) + port <- "80" + + # read file in binary mode + if (!is.null(file)) { + fileLength <- file.info(file)$size + fileContents <- readBin(file, what="raw", n=fileLength) + } + + # build http request + request <- NULL + request <- c(request, paste(method, " ", path, " HTTP/1.1\r\n", sep="")) + request <- c(request, "User-Agent: ", userAgent(), "\r\n") + request <- c(request, "Host: ", host, "\r\n", sep="") + request <- c(request, "Accept: */*\r\n") + if (!is.null(file)) { + request <- c(request, paste("Content-Type: ", + contentType, + "\r\n", + sep="")) + request <- c(request, paste("Content-Length: ", + fileLength, + "\r\n", + sep="")) + } + for (name in names(headers)) + { + request <- c(request, + paste(name, ": ", headers[[name]], "\r\n", sep="")) + } + request <- c(request, "\r\n") + + # output request if in verbose mode + if (httpVerbose()) + cat(request) + + # use timeout if supplied, default timeout if not (matches parameter behavior + # for socketConnection) + timeout <- if (is.null(timeout)) getOption("timeout") else timeout + + # open socket connection + time <- system.time(gcFirst=FALSE, { + conn <- socketConnection(host = host, + port = as.integer(port), + open = "w+b", + blocking = TRUE, + timeout = timeout) + on.exit(close(conn)) + + # write the request header and file payload + writeBin(charToRaw(paste(request,collapse="")), conn, size=1) + if (!is.null(file)) { + writeBin(fileContents, conn, size=1) + } + + # read the response + response <- readHttpResponse(list( + protocol = protocol, + host = host, + port = port, + method = method, + path = path), conn) + }) + httpTrace(method, path, time) + + # print if in verbose mode + if (httpVerbose()) + print(response) + + # output JSON if requested + if (httpTraceJson() && identical(contentType, "application/json")) + cat(paste0("<< ", rawToChar(fileContents), "\n")) + + # return it + response +} + +httpCurl <- function(protocol, + host, + port, + method, + path, + headers, + contentType = NULL, + file = NULL, + writer = NULL, + timeout = NULL) { + + if (!is.null(file) && is.null(contentType)) + stop("You must specify a contentType for the specified file") + + if (!is.null(file)) + fileLength <- file.info(file)$size + + extraHeaders <- character() + for (header in names(headers)) + { + extraHeaders <- paste(extraHeaders, "--header") + extraHeaders <- paste(extraHeaders, + paste('"', header,": ",headers[[header]], '"', sep="")) + } + + outputFile <- tempfile() + + command <- paste("curl", + "-i", + "-X", + method); + + if (httpVerbose()) + command <- paste(command, "-v") + + if (!is.null(timeout)) + command <- paste(command, "--connect-timeout", timeout) + + if (!is.null(file)) { + command <- paste(command, + "--data-binary", + shQuote(paste("@", file, sep="")), + "--header", paste('"' ,"Content-Type: ",contentType, '"', sep=""), + "--header", paste('"', "Content-Length: ", fileLength, '"', sep="")) + } + + # add prefix to port if necessary + if (nzchar(port)) + port <- paste(":", port, sep="") + + command <- paste(command, + extraHeaders, + "--header", "Expect:", + "--user-agent", userAgent(), + "--silent", + "--show-error", + "-o", shQuote(outputFile), + paste(protocol, "://", host, port, path, sep="")) + + result <- NULL + time <- system.time(gcFirst = FALSE, { + result <- system(command) + }) + httpTrace(method, path, time) + + # emit JSON trace if requested + if (!is.null(file) && httpTraceJson() && + identical(contentType, "application/json")) + { + fileLength <- file.info(file)$size + fileContents <- readBin(file, what="raw", n=fileLength) + cat(paste0("<< ", rawToChar(fileContents), "\n")) + } + + if (result == 0) { + fileConn <- file(outputFile, "rb") + on.exit(close(fileConn)) + readHttpResponse(list( + protocol = protocol, + host = host, + port = port, + method = method, + path = path), fileConn) + } else { + stop(paste("Curl request failed (curl error", result, "occurred)")) + } +} + +httpRCurl <- function(protocol, + host, + port, + method, + path, + headers, + contentType = NULL, + file = NULL, + writer = NULL, + timeout = NULL) { + + if (!is.null(file) && is.null(contentType)) + stop("You must specify a contentType for the specified file") + + # add prefix to port if necessary + if (!is.null(port) && nzchar(port)) + port <- paste(":", port, sep="") + + # build url + url <- paste(protocol, "://", host, port, path, sep="") + + # read file in binary mode + if (!is.null(file)) { + fileLength <- file.info(file)$size + fileContents <- readBin(file, what="raw", n=fileLength) + headers$`Content-Type` <- contentType + } + + # establish options + options <- RCurl::curlOptions(url) + options$useragent <- userAgent() + options$ssl.verifypeer <- TRUE + # Cert from: http://curl.haxx.se/docs/caextract.html + options$cainfo <- system.file("cert/cacert.pem", package = "rsconnect") + headerGatherer <- RCurl::basicHeaderGatherer() + options$headerfunction <- headerGatherer$update + + # the text processing done by .mapUnicode has the unfortunate side effect + # of turning escaped backslashes into ordinary backslashes but leaving + # ordinary backslashes alone, which can create malformed JSON. + textGatherer <- if (is.null(writer)) + RCurl::basicTextGatherer(.mapUnicode = FALSE) + else + writer + + # when using a custom output writer, add a progress check so we can + # propagate interrupts, and wait a long time (for streaming) + if (!is.null(writer)) { + options$noprogress <- FALSE + options$progressfunction <- writer$progress + options$timeout <- 9999999 + } + + # use timeout if supplied + if (!is.null(timeout)) { + options$timeout <- timeout + } + + # verbose if requested + if (httpVerbose()) + options$verbose <- TRUE + + # add extra headers + extraHeaders <- as.character(headers) + names(extraHeaders) <- names(headers) + options$httpheader <- extraHeaders + + # make the request + time <- system.time(gcFirst = FALSE, tryCatch({ + if (!is.null(file)) { + RCurl::curlPerform(url = url, + .opts = options, + customrequest = method, + readfunction = fileContents, + infilesize = fileLength, + writefunction = textGatherer$update, + upload = TRUE) + } else if (method == "DELETE") { + RCurl::curlPerform(url = url, + .opts = options, + customrequest = method) + + } else { + if (identical(method, "GET")) { + RCurl::getURL(url, + .opts = options, + write = textGatherer) + } else { + RCurl::curlPerform(url = url, + .opts = options, + customrequest = method, + writefunction = textGatherer$update) + } + }}, + error = function(e, ...) { + # ignore errors resulting from timeout or user abort + if (identical(e$message, "Callback aborted") || + identical(e$message, "transfer closed with outstanding read data remaining")) + return + # bubble remaining errors through + else + stop(e) + })) + httpTrace(method, path, time) + + # emit JSON trace if requested + if (!is.null(file) && httpTraceJson() && + identical(contentType, "application/json")) + cat(paste0("<< ", rawToChar(fileContents), "\n")) + + # return list + headers <- headerGatherer$value() + if ("Location" %in% names(headers)) + location <- headers[["Location"]] + else + location <- NULL + # presume a plain text response unless specified otherwise + contentType <- if ("Content-Type" %in% names(headers)) { + headers[["Content-Type"]] + } else { + "text/plain" + } + + contentValue <- textGatherer$value() + + # emit JSON trace if requested + if (httpTraceJson() && identical(contentType, "application/json")) + cat(paste0(">> ", contentValue, "\n")) + + list(req = list(protocol = protocol, + host = host, + port = port, + method = method, + path = path), + status = as.integer(headers[["status"]]), + location = location, + contentType = contentType, + content = contentValue) +} + +httpVerbose <- function() { + getOption("rsconnect.http.verbose", FALSE) +} + +httpTraceJson <- function() { + getOption("rsconnect.http.trace.json", FALSE) +} + +httpTrace <- function(method, path, time) { + if (getOption("rsconnect.http.trace", FALSE)) { + cat(method, " ", path, " ", as.integer(time[['elapsed']]*1000), "ms\n", + sep="") + } +} + +httpFunction <- function() { + httpType <- getOption("rsconnect.http", "rcurl") + if (identical("rcurl", httpType)) + httpRCurl + else if (identical("curl", httpType)) + httpCurl + else if (identical("internal", httpType)) + httpInternal + else + stop(paste("Invalid http option specified:",httpType, + ". Valid values are rcurl, curl, and internal")) +} + +POST_JSON <- function(service, + authInfo, + path, + json, + query = NULL, + headers = list()) { + POST(service, + authInfo, + path, + query, + "application/json", + content = RJSONIO::toJSON(json, pretty = TRUE, digits=30), + headers = headers) +} + +PUT_JSON <- function(service, + authInfo, + path, + json, + query = NULL, + headers = list()) { + PUT(service, + authInfo, + path, + query, + "application/json", + content = RJSONIO::toJSON(json, pretty = TRUE, digits=30), + headers = headers) +} + +POST <- function(service, + authInfo, + path, + query = NULL, + contentType = NULL, + file = NULL, + content = NULL, + headers = list()) { + httpRequestWithBody(service, authInfo, "POST", path, query, contentType, file, content, headers) +} + +PUT <- function(service, + authInfo, + path, + query = NULL, + contentType = NULL, + file = NULL, + content = NULL, + headers = list()) { + httpRequestWithBody(service, authInfo, "PUT", path, query, contentType, file, content, headers) +} + +GET <- function(service, + authInfo, + path, + query = NULL, + headers = list(), + writer = NULL, + timeout = NULL) { + httpRequest(service, authInfo, "GET", path, query, headers, writer, timeout) +} + +DELETE <- function(service, + authInfo, + path, + query = NULL, + headers = list(), + writer = NULL) { + httpRequest(service, authInfo, "DELETE", path, query, headers, writer) +} + +httpRequestWithBody <- function(service, + authInfo, + method, + path, + query = NULL, + contentType = NULL, + file = NULL, + content = NULL, + headers = list()) { + + if ((is.null(file) && is.null(content))) + stop("You must specify either the file or content parameter.") + if ((!is.null(file) && !is.null(content))) + stop("You must specify either the file or content parameter but not both.") + + # prepend the service path + url <- paste(service$path, path, sep="") + + # append the query + if (!is.null(query)) { + # URL encode query args + query <- utils::URLencode(query) + url <- paste(url, "?", query, sep="") + } + + # if we have content then write it to a temp file before posting + if (!is.null(content)) { + file <- tempfile() + writeChar(content, file, eos = NULL, useBytes=TRUE) + } + + # if this request is to be authenticated, sign it + if (length(authInfo) > 0) { + sigHeaders <- signatureHeaders(authInfo, method, url, file) + headers <- append(headers, sigHeaders) + } + + # perform request + http <- httpFunction() + http(service$protocol, + service$host, + service$port, + method, + url, + headers, + contentType, + file) +} + +httpRequest <- function(service, + authInfo, + method, + path, + query, + headers = list(), + writer = NULL, + timeout = NULL) { + + # prepend the service path + url <- paste(service$path, path, sep="") + + # append the query + if (!is.null(query)) { + # URL encode query args + query <- utils::URLencode(query) + url <- paste(url, "?", query, sep="") + } + + # if this request is to be authenticated, sign it + if (length(authInfo) > 0) { + sigHeaders <- signatureHeaders(authInfo, method, url, NULL) + headers <- append(headers, sigHeaders) + } + + # perform GET + http <- httpFunction() + http(service$protocol, + service$host, + service$port, + method, + url, + headers, + writer = writer, + timeout = timeout) +} + +rfc2616Date <- function(time = Sys.time()) { + + # capure current locale + loc <- Sys.getlocale('LC_TIME') + + # set locale to POSIX/C to ensure ASCII date + Sys.setlocale("LC_TIME", "C") + + # generate date + date <- strftime(Sys.time(), "%a, %d %b %Y %H:%M:%S GMT", tz = "GMT") + + # restore locale + Sys.setlocale("LC_TIME", loc) + + return(date) +} + +urlDecode <- function(x) { + RCurl::curlUnescape(x) +} + +urlEncode <- function(x) { + if (inherits(x, "AsIs")) return(x) + RCurl::curlEscape(x) +} + +queryString <- function (elements) { + stopifnot(is.list(elements)) + elements <- elements[!sapply(elements, is.null)] + + names <- RCurl::curlEscape(names(elements)) + values <- vapply(elements, urlEncode, character(1)) + if (length(elements) > 0) { + result <- paste0(names, "=", values, collapse = "&") + } else { + result <- "" + } + return(result) +} + +signatureHeaders <- function(authInfo, method, path, file) { + # headers to return + headers <- list() + + # remove query string from path if necessary + path <- strsplit(path, "?", fixed = TRUE)[[1]][[1]] + + # generate date + date <- rfc2616Date() + + if (!is.null(authInfo$secret)) { + # generate contents hash + if (!is.null(file)) + md5 <- digest::digest(file, algo="md5", file=TRUE) + else + md5 <- digest::digest("", algo="md5", serialize=FALSE) + + # build canonical request + canonicalRequest <- paste(method, path, date, md5, sep="\n") + + # sign request using shared secret + decodedSecret <- RCurl::base64Decode(authInfo$secret, mode="raw") + hmac <- digest::hmac(decodedSecret, canonicalRequest, algo="sha256") + signature <- paste(RCurl::base64Encode(hmac), "; version=1", sep="") + } else if (!is.null(authInfo$private_key)) { + # generate contents hash (this is done slightly differently for private key + # auth since we use base64 throughout) + if (!is.null(file)) + md5 <- digest::digest(file, algo="md5", file = TRUE, raw = TRUE) + else + md5 <- digest::digest("", algo="md5", serialize = FALSE, raw = TRUE) + md5 <- RCurl::base64Encode(md5) + + # build canonical request + canonicalRequest <- paste(method, path, date, md5, sep="\n") + + # sign request using local private key + private_key <- structure( + RCurl::base64Decode(authInfo$private_key, mode="raw"), + class="private.key.DER") + private_key <- PKI::PKI.load.key(what = private_key, format = "DER", + private = TRUE) + hashed <- digest::digest(object = canonicalRequest, algo = "sha1", + serialize = FALSE, raw = TRUE) + signature <- RCurl::base64Encode( + PKI::PKI.sign(key = private_key, digest = hashed)) + } else { + stop("can't sign request: no shared secret or private key") + } + + # return headers + headers$Date <- date + headers$`X-Auth-Token` <- authInfo$token + headers$`X-Auth-Signature` <- signature + headers$`X-Content-Checksum` <- md5 + headers +} diff --git a/R/ide.R b/R/ide.R new file mode 100644 index 0000000..c3b2340 --- /dev/null +++ b/R/ide.R @@ -0,0 +1,143 @@ + +# These functions are intended to be called primarily by the RStudio IDE. + +# attempts to validate a server URL by hitting a known configuration endpoint +# (which does not require authentication). returns a list containing (valid = +# TRUE) and server settings, or a list containing (valid = FALSE) and an error +# message. +# +# the URL may be specified with or without the protocol and port; this function +# will try both http and https and follow any redirects given by the server. +validateServerUrl <- function(url) { + tryAllProtocols <- TRUE + + if (!grepl("://", url, fixed = TRUE)) + { + if (grepl(":3939", url, fixed = TRUE)) { + # assume http for default (local) connect installations + url <- paste0("http://", url) + } else { + # assume https elsewhere + url <- paste0("https://", url) + } + } + + # if the URL ends with a port number, don't try http/https on the same port + if (grepl(":\\d+/?$", url)) { + tryAllProtocols <- FALSE + } + + settingsEndpoint <- "/server_settings" + url <- ensureConnectServerUrl(url) + + # begin trying URLs to discover the correct one + response <- NULL + errMessage <- "" + retry <- TRUE + while (retry) { + tryCatch({ + # this shouldn't take more than 5 seconds since it does no work (i.e we + # should just be waiting for the network), so timeout quickly to avoid + # hanging when the server doesn't accept the connection + httpResponse <- GET(parseHttpUrl(url), NULL, settingsEndpoint, + timeout = 5) + + # check for redirect + if (httpResponse$status == 307 && + !is.null(httpResponse$location)) { + + # we were served a redirect; try again with the new URL + url <- httpResponse$location + if (substring(url, (nchar(url) - nchar(settingsEndpoint)) + 1) == + settingsEndpoint) { + # chop /server_settings from the redirect path to get the raw API path + url <- substring(url, 1, nchar(url) - nchar(settingsEndpoint)) + } + next + } + response <- handleResponse(httpResponse) + + # got a real response; stop trying now + retry <- FALSE + }, error = function(e) { + if (inherits(e, "OPERATION_TIMEDOUT") && tryAllProtocols) { + # if the operation timed out on one protocol, try the other one (note + # that we don't do this if a port is specified) + if (substring(url, 1, 7) == "http://") { + url <<- paste0("https://", substring(url, 8)) + } else if (substring(url, 1, 8) == "https://") { + url <<- paste0("http://", substring(url, 9)) + } + tryAllProtocols <<- FALSE + return() + } + errMessage <<- e$message + retry <<- FALSE + }) + } + if (is.null(response)) { + list( + valid = FALSE, + message = errMessage) + } else { + c(list(valid = TRUE, + url = url, + name = findLocalServer(url)), + response) + } +} + +# given a server URL, returns that server's short name. if the server is not +# currently registered, the server is registered and the short name of the newly +# registered server is returned. +findLocalServer <- function(url) { + # make sure the url has the current API suffix + url <- ensureConnectServerUrl(url) + + # helper to find a server given its URL + findServerByUrl <- function(name) { + allServers <- as.data.frame(rsconnect::servers(local = TRUE)) + match <- allServers[allServers$url == url, , drop = FALSE] + if (nrow(match) == 0) + NULL + else + as.character(match[1,"name"]) + } + + # if there are no local servers with the given URL, add one and return its + # name + name <- findServerByUrl(url) + if (is.null(name)) { + addConnectServer(url, NULL, TRUE) + findServerByUrl(url) + } else { + name + } +} + +# generate the markers +showRstudioSourceMarkers <- function(basePath, lint) { + markers <- list() + applied <- lapply(lint, function(file) { + lapply(file, function(linter) { + lapply(linter$indices, function(index) { + marker <- list() + marker$type <- "warning" + marker$file <- file.path(basePath, linter$file) + marker$line <- index + marker$column <- 1 + marker$message <- linter$suggestion + markers <<- c(markers, list(marker)) + marker + }) + }) + }) + + rstudioapi::callFun("sourceMarkers", + name = "Publish Content Issues", + markers = markers, + basePath = basePath, + autoSelect = "first") +} + + diff --git a/R/imports.R b/R/imports.R new file mode 100644 index 0000000..fa241bd --- /dev/null +++ b/R/imports.R @@ -0,0 +1,5 @@ + + +#' @importFrom stats na.omit setNames +#' @importFrom utils available.packages contrib.url formatUL getFromNamespace glob2rx packageVersion read.csv +NULL diff --git a/R/lint-framework.R b/R/lint-framework.R new file mode 100644 index 0000000..8ffc436 --- /dev/null +++ b/R/lint-framework.R @@ -0,0 +1,296 @@ +.__LINTERS__. <- new.env(parent = emptyenv()) + +##' Add a Linter +##' +##' Add a linter, to be used in subsequent calls to \code{\link{lint}}. +##' +##' @param name The name of the linter, as a string. +##' @param linter A \code{\link{linter}}. +##' @export +##' @example examples/example-linter.R +addLinter <- function(name, linter) { + assign(name, linter, envir = .__LINTERS__.) +} + + +##' Create a Linter +##' +##' Generate a linter, which can identify errors or problematic regions in a +##' project. +##' +##' @param apply Function that, given the content of a file, returns the indices +##' at which problems were found. +##' @param takes Function that, given a set of paths, returns the subset of +##' paths that this linter uses. +##' @param message Function that, given content and lines, returns an +##' informative message for the user. Typically generated with +##' \code{\link{makeLinterMessage}}. +##' @param suggestion String giving a prescribed fix for the linted problem. +##' @export +##' @example examples/example-linter.R +linter <- function(apply, takes, message, suggestion) { + result <- list( + apply = apply, + takes = takes, + message = message, + suggestion = suggestion + ) + class(result) <- "linter" + result +} + +getLinterApplicableFiles <- function(linter, files) { + result <- linter$takes(files) + if (is.numeric(result) || is.logical(result)) { + files[result] + } else { + result + } +} + +applyLinter <- function(linter, ...) { + result <- linter$apply(...) + if (is.logical(result)) { + output <- which(result) + } else { + output <- as.numeric(result) + } + attributes(output) <- attributes(result) + output +} + +##' Lint a Project +##' +##' Takes the set of active linters (see \code{\link{addLinter}}), and applies +##' them to all files within a project. +##' +##' @param project Path to a project directory. +##' @param files Specific files to lint. Can be NULL, in which case all +##' the files in the directory will be linted. +##' @param appPrimaryDoc The primary file in the project directory. Can be NULL, +##' in which case it's inferred (if possible) from the directory contents. +##' @export +lint <- function(project, files = NULL, appPrimaryDoc = NULL) { + + if (!file.exists(project)) + stop("No directory at path '", project, "'") + + if (file.exists(project) && !isTRUE(file.info(project)$isdir)) + stop("Path '", project, "' is not a directory") + + project <- normalizePath(project, mustWork = TRUE, winslash = "/") + + # Perform actions within the project directory (so relative paths are easily used) + owd <- getwd() + on.exit(setwd(owd)) + setwd(project) + + # If the set of files wasn't specified, generate it + if (is.null(files)) { + files <- bundleFiles(project) + } + + # List the files that will be bundled + projectFiles <- file.path(project, files) %relativeTo% project + projectFiles <- gsub("^\\./", "", projectFiles) + names(projectFiles) <- projectFiles + + # collect files + appFilesBase <- tolower(list.files()) + wwwFiles <- tolower(list.files("www/")) + + # check for single-file app collision + if (!is.null(appPrimaryDoc) && + tolower(tools::file_ext(appPrimaryDoc)) == "r" && + "app.r" %in% appFilesBase) { + stop("The project contains both a single-file Shiny application and a ", + "file named app.R; it must contain only one of these.") + } + + # Do some checks for a valid application structure + satisfiedLayouts <- c( + shinyAndUi = all(c("server.r", "ui.r") %in% appFilesBase), + shinyAndIndex = "server.r" %in% appFilesBase && "index.html" %in% wwwFiles, + app = any("app.r" %in% appFilesBase, + !is.null(appPrimaryDoc) && + tolower(tools::file_ext(appPrimaryDoc)) == "r"), + Rmd = any(grepl(glob2rx("*.rmd"), appFilesBase)), + static = any(grepl("^.*\\.html?$", appFilesBase)) + ) + + if (!any(satisfiedLayouts)) { + msg <- "Cancelling deployment: invalid project layout. + The project should have one of the following layouts: + 1. 'shiny.R' and 'ui.R' in the application base directory, + 2. 'shiny.R' and 'www/index.html' in the application base directory, + 3. 'app.R' or a single-file Shiny .R file, + 4. An R Markdown (.Rmd) document, + 5. A static HTML (.html) document." + + # strip leading whitespace from the above + msg <- paste(collapse = "\n", + gsub("^ *", "", unlist(strsplit(msg, "\n", fixed = TRUE)))) + + stop(msg) + } + + linters <- mget(objects(.__LINTERS__.), envir = .__LINTERS__.) + + # Identify all files that will be read in by one or more linters + projectFilesToLint <- Reduce(union, lapply(linters, function(linter) { + getLinterApplicableFiles(linter, projectFiles) + })) + + # Read in the files + # TODO: perform this task more lazily? + projectContent <- suppressWarnings(lapply(projectFilesToLint, readLines)) + names(projectContent) <- projectFilesToLint + lintResults <- vector("list", length(linters)) + names(lintResults) <- names(linters) + + ## Apply each linter + for (i in seq_along(linters)) { + linter <- linters[[i]] + applicableFiles <- getLinterApplicableFiles(linter, projectFilesToLint) + lintIndices <- vector("list", length(applicableFiles)) + names(lintIndices) <- applicableFiles + + ## Apply linter to each file + for (j in seq_along(applicableFiles)) { + file <- applicableFiles[[j]] + tryCatch( + expr = { + lintIndices[[j]] <- applyLinter(linter, + projectContent[[file]], + project = project, + path = file, + files = projectFiles) + }, + error = function(e) { + message("Failed to lint file '", file, "'") + message("The linter failed with message:\n") + message(e$message) + lintIndices[[j]] <- numeric(0) + } + ) + } + + ## Get the messages associated with each lint + lintMessages <- enumerate(lintIndices, function(x, i) { + if (length(x)) { + message <- linter$message + if (is.function(message)) { + linter$message(projectContent[[names(lintIndices)[i]]], x) + } else { + makeLinterMessage(message, projectContent[[names(lintIndices)[i]]], x) + } + } else { + character() + } + }) + + ## Assign the result + lintResults[[i]] <- list( + files = applicableFiles, + indices = lintIndices, + message = lintMessages, + suggestion = linter$suggestion + ) + + } + + ## Get all of the linted files, and transform the results into a by-file format + lintedFiles <- Reduce(union, lapply(lintResults, function(x) { + names(x$indices) + })) + + lintFields <- c("indices", "message") + fileResults <- lapply(lintedFiles, function(file) { + result <- lapply(lintResults, function(result) { + subResult <- lapply(lintFields, function(field) { + result[[field]][[file]] + }) + names(subResult) <- lintFields + subResult$suggestion <- result$suggestion + subResult$file <- file + class(subResult) <- "lint" + subResult + }) + class(result) <- "lintList" + result + }) + names(fileResults) <- lintedFiles + class(fileResults) <- "linterResults" + invisible(fileResults) +} + +printLintHeader <- function(x) { + if (!length(x$message)) return(invisible(NULL)) + dashSep <- paste(rep("-", nchar(x$file)), collapse = "") + header <- paste(dashSep, "\n", + x$file, "\n", + dashSep, "\n", sep = "") + message(paste(header, collapse = "\n"), appendLF = FALSE) + invisible(x) +} + +printLintBody <- function(x, ...) { + message(paste(x$message, collapse = "\n"), appendLF = FALSE) + invisible(x) +} + +printLintFooter <- function(x, ...) { + message(paste(collectSuggestions(x), collapse = "\n")) + invisible(x) +} + +printLinterResults <- function(x, ...) { + lapply(x, printLintList, ...) + printLintFooter(x) + invisible(x) +} + +printLintList <- function(x, ...) { + printLintHeader(x[[1]]) + lapply(x, printLintBody, ...) + invisible(x) +} + +printLint <- function(x, ...) { + printLintHeader(x) + printLintBody(x, ...) + invisible(x) +} + +collectSuggestions <- function(fileResults) { + suggestions <- lapply(fileResults, function(fileResult) { + unlist(lapply(fileResult, function(lintInfo) { + if (length(lintInfo$indices) > 0) { + paste(as.character(lintInfo$suggestion), collapse = "\n") + } + })) + }) + Reduce(union, suggestions) +} + +`%relativeTo%` <- function(paths, directory) { + + nd <- nchar(directory) + + unlist(lapply(paths, function(path) { + np <- nchar(path) + if (nd > np) { + warning("'", path, "' is not a subdirectory of '", directory, "'") + return(path) + } + + if (substring(path, 1, nd) != directory) { + warning("'", path, "' is not a subdirectory of '", directory, "'") + return(path) + } + + offset <- if (substring(directory, nd, nd) == "/") 1 else 2 + substring(path, nd + offset, np) + })) + +} diff --git a/R/lint-utils.R b/R/lint-utils.R new file mode 100644 index 0000000..fba57ee --- /dev/null +++ b/R/lint-utils.R @@ -0,0 +1,135 @@ + +stripComments <- function(content) { + gsub("#.*", "", content, perl = TRUE) +} + +hasAbsolutePaths <- function(content) { + + regex <- c( + "\\[(.*?)\\]\\(\\s*[a-zA-Z]:/[^\"\']", ## windows-style markdown references [Some image](C:/...) + "\\[(.*?)\\]\\(\\s*/[^/]", ## unix-style markdown references [Some image](/Users/...) + NULL ## so we don't worry about commas above + ) + + regexResults <- as.logical(Reduce(`+`, lapply(regex, function(rex) { + grepl(rex, content, perl = TRUE) + }))) + + # Strip out all strings in the document, and check to see if any of them + # resolve to absolute paths on the system. + sQuoteRegex <- "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + dQuoteRegex <- '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + + extractedStrings <- lapply(c(sQuoteRegex, dQuoteRegex), function(regex) { + matches <- gregexpr(regex, content, perl = TRUE) + lapply(seq_along(matches), function(i) { + match <- matches[[i]] + if (c(match[[1]]) == -1L) return(character()) + starts <- as.integer(match) + 1 + ends <- starts + attr(match, "match.length") - 3 + substring(content[[i]], starts, ends) + }) + }) + + strings <- vector("list", length(extractedStrings[[1]])) + for (i in seq_along(extractedStrings[[1]])) { + strings[[i]] <- unique(c(extractedStrings[[1]][[i]], extractedStrings[[2]][[i]])) + strings[[i]] <- strings[[i]][nchar(strings[[i]]) >= 5] + } + + lineHasAbsolutePath <- unlist(lapply(strings, function(x) { + any( + grepl("^/|^[a-zA-Z]:/|^~", x, perl = TRUE) & + file.exists(x) & + file.info(x)$isdir %in% FALSE & + vapply(gregexpr("[~/]", x, perl = TRUE), USE.NAMES = FALSE, FUN.VALUE = numeric(1), length) >= 3 + ) + })) + + as.logical(lineHasAbsolutePath + regexResults) + +} + +noMatch <- function(x) { + identical(attr(x, "match.length"), -1L) +} + +badRelativePaths <- function(content, project, path, ...) { + + ## Figure out how deeply the path of the file is nested + ## (it is relative to the project root) + slashMatches <- gregexpr("/", path) + nestLevel <- if (noMatch(slashMatches)) 0 else length(slashMatches[[1]]) + + ## Identify occurrences of "../" + regexResults <- gregexpr("../", content, fixed = TRUE) + + ## Figure out sequential runs of `../` + runs <- lapply(regexResults, function(x) { + if (noMatch(x)) return(NULL) + rle <- rle(as.integer(x) - seq(0, by = 3, length.out = length(x))) + rle$lengths + }) + + badPaths <- vapply(runs, function(x) { + any(x > nestLevel) + }, logical(1)) + + badPaths +} + +enumerate <- function(X, FUN, ...) { + FUN <- match.fun(FUN) + result <- vector("list", length(X)) + for (i in seq_along(X)) { + result[[i]] <- FUN(X[[i]], i, ...) + } + names(result) <- names(X) + result +} + +#' Construct a Linter Message +#' +#' Pretty-prints a linter message. Primarily used as a helper +#' for constructing linter messages with \code{\link{linter}}. +#' +#' @param header A header message describing the linter. +#' @param content The content of the file that was linted. +#' @param lines The line numbers from \code{content} that contain lint. +makeLinterMessage <- function(header, content, lines) { + + lint <- attr(lines, "lint") + + c( + paste0(header, ":"), + paste(lines, ": ", + content[lines], + if (!is.null(lint)) paste(" ", lint, sep = ""), + sep = ""), + "\n" + ) +} + +hasLint <- function(x) { + any(unlist(lapply(x, function(x) { + lapply(x, function(x) { + length(x$indices) > 0 + }) + }))) +} + +isRCodeFile <- function(path) { + grepl("\\.[rR]$|\\.[rR]md$|\\.[rR]nw$", path) +} + +transposeList <- function(list) { + unname(as.list( + as.data.frame( + t( + as.matrix( + as.data.frame(list, stringsAsFactors = FALSE) + ) + ), stringsAsFactors = FALSE) + )) +} + diff --git a/R/linters.R b/R/linters.R new file mode 100644 index 0000000..996f047 --- /dev/null +++ b/R/linters.R @@ -0,0 +1,138 @@ +addLinter("absolute.paths", linter( + + apply = function(content, ...) { + content <- stripComments(content) + which(hasAbsolutePaths(content)) + }, + + takes = isRCodeFile, + + message = function(content, lines) { + makeLinterMessage("The following lines contain absolute paths", + content, + lines) + }, + + suggestion = "Paths should be to files within the project directory." + +)) + +addLinter("invalid.relative.paths", linter( + + apply = function(content, ...) { + content <- stripComments(content) + badRelativePaths(content, ...) + }, + + takes = isRCodeFile, + + message = function(content, lines) { + makeLinterMessage("The following lines contain invalid relative paths (resolved outside of project directory)", + content, + lines) + }, + + suggestion = "Paths should be to files within the project directory." + +)) + +addLinter("filepath.capitalization", linter( + + apply = function(content, project, path, files) { + + content <- stripComments(content) + + # Inferred files within source documents (really, we just + # extract everything between two quotes) + regexes <- c("(?!\\\\)\'", "(?!\\\\)\"") + inferredFiles <- lapply(regexes, function(regex) { + matches <- gregexpr(regex, content, perl = TRUE) + results <- vector("list", length(content)) + for (i in seq_along(matches)) { + x <- matches[[i]] + if (x[[1]] == -1L || length(x) %% 2 != 0) next + starts <- x[seq(1, length(x), by = 2)] + ends <- x[seq(2, length(x), by = 2)] + results[[i]] <- character(length(starts)) + for (j in seq_along(starts)) { + results[[i]][[j]] <- substring(content[i], starts[j] + 1, ends[j] - 1) + } + } + results + }) + names(inferredFiles) <- c("single.quotes", "double.quotes") + + ## Replace '\' with '/' in filepaths for consistency in comparisons + inferredFiles <- lapply(inferredFiles, function(x) { + lapply(x, function(xx) { + gsub("\\\\", "/", xx, perl = TRUE) + }) + }) + + # Compare in case sensitive, case insensitive fashion + projectFiles <- files + projectFilesLower <- tolower(files) + + badLines <- lapply(inferredFiles, function(regex) { + lapply(regex, function(x) { + + which( + (tolower(x) %in% projectFilesLower) & + (!(x %in% projectFiles)) + ) + + }) + }) + + indices <- Reduce(union, lapply(badLines, function(x) { + which(sapply(x, length) > 0) + })) + + if (!length(indices)) return(integer()) + + from <- lapply(inferredFiles, function(x) x[indices]) + to <- lapply(from, function(x) { + lapply(x, function(xx) { + projectFiles[tolower(xx) == projectFilesLower] + }) + }) + + messages <- lapply(seq_along(from), function(regex) { + lapply(seq_along(regex), function(i) { + if (length(from[[regex]][[i]])) + paste(collapse = ", ", + paste("[", + shQuote(from[[regex]][[i]]), + " -> ", + shQuote(to[[regex]][[i]]), + "]", sep = "") + ) + else + "" + }) + }) + + transposed <- transposeList(messages) + lint <- sapply(transposed, function(x) { + paste(x[x != ""], collapse = ", ") + }) + + indices <- as.numeric(indices) + attr(indices, "lint") <- lint + indices + + }, + + takes = isRCodeFile, + + message = function(content, lines) { + makeLinterMessage( + "The following lines contain paths to files not matching in case sensitivity", + content, + lines + ) + }, + + suggestion = "Filepaths are case-sensitive on deployment server." + +)) diff --git a/R/locale.R b/R/locale.R new file mode 100644 index 0000000..aa0ee2c --- /dev/null +++ b/R/locale.R @@ -0,0 +1,84 @@ +overrideWindowsLocale <- function(locale) { + map <- list() + map[['el_EL']] <- "el_GR" + if (locale %in% names(map)) { + locale <- map[[locale]] + } + return(locale) +} + +detectLocale <- function () { + sysName <- Sys.info()[['sysname']] + if (identical(sysName, "Windows")) { + locale <- detectLocale.Windows() + } else { + locale <- detectLocale.Unix() + } + return(locale) +} + +detectLocale.Unix <- function () { + unlist(strsplit(Sys.getlocale("LC_CTYPE"), ".", fixed=TRUE))[1] +} + +detectLocale.Windows <- function (useCache = + getOption('rsconnect.locale.cache', TRUE)) { + + # default locale + locale <- 'en_US' + + cacheFile <- localeCacheFile() + if (file.exists(cacheFile) && useCache) { + + # get chached + cache <- as.list(readDcf(cacheFile, all=TRUE)) + + locale <- unlist(cache$locale) + + } else { + + tryCatch({ + + # get system locale + locale <- systemLocale() + + # write the user info + write.dcf(list(locale = locale), + cacheFile, + width = 100) + + }, error=function(e) { + warning(paste0("Error detecting locale: ", e, + " (Using default: ", locale, ")"), call.=FALSE) + }) + } + return(overrideWindowsLocale(locale)) +} + +localeCacheFile <- function() { + normalizePath(file.path(rsconnectConfigDir(), "locale.dcf"), mustWork = FALSE) +} + +systemLocale <- function() { + message("Detecting system locale ... ", appendLF = FALSE) + + # get system locale + info <- systemInfo() + raw <- as.character(info[[20]]) + parts <- strsplit(unlist(strsplit(raw, ";", fixed=TRUE)), "-", fixed=TRUE) + + if (length(parts[[1]]) >= 2) { + # normalize locale to something like en_US + locale <- paste(tolower(parts[[1]][1]), toupper(parts[[1]][2]), sep="_") + } else { + locale <- paste(tolower(parts[[1]][1]), toupper(parts[[1]][1]), sep="_") + } + message(locale) + return(locale) +} + +systemInfo <- function () { + raw <- system("systeminfo /FO csv", intern=TRUE, wait=TRUE) + info <- read.csv(textConnection(raw)) + return(info) +} diff --git a/R/lucid.R b/R/lucid.R new file mode 100644 index 0000000..55ebbf7 --- /dev/null +++ b/R/lucid.R @@ -0,0 +1,278 @@ + +# return a list of functions that can be used to interact with lucid +lucidClient <- function(service, authInfo) { + service <- parseHttpUrl(service) + + list( + + status = function() { + handleResponse(GET(service, authInfo, "/internal/status")) + }, + + currentUser = function() { + handleResponse(GET(service, authInfo, "/users/current/")) + }, + + accountsForUser = function(userId) { + path <- "/accounts/" + query <- "" + listRequest(service, authInfo, path, query, "accounts") + }, + + getAccountUsage = function(accountId, usageType='hours', applicationId=NULL, + from=NULL, until=NULL, interval=NULL) { + path <- paste("/accounts/", accountId, "/usage/", usageType, "/", sep="") + query <- list() + if (!is.null(applicationId)) + query$application=applicationId + if (!is.null(from)) + query$from = from + if (is.null(until)) + query$until = until + if (is.null(interval)) + query$interval = interval + handleResponse(GET(service, authInfo, path, queryString(query))) + }, + + listApplications = function(accountId, filters = list()) { + path <- "/applications/" + query <- paste(filterQuery( + c("account_id", names(filters)), + c(accountId, unname(filters)) + ), collapse = "&") + listRequest(service, authInfo, path, query, "applications") + }, + + getApplication = function(applicationId) { + path <- paste("/applications/", applicationId, sep="") + handleResponse(GET(service, authInfo, path)) + }, + + getApplicationMetrics = function(applicationId, series, metrics, from=NULL, until=NULL, interval=NULL) { + path <- paste("/applications/", applicationId, "/metrics/", series, "/", sep="") + query <- list() + m <- paste(lapply(metrics, function(x){paste("metric", urlEncode(x), sep="=")}), collapse = "&") + if (!is.null(from)) + query$from = from + if (is.null(until)) + query$until = until + if (is.null(interval)) + query$interval = interval + handleResponse(GET(service, authInfo, path, paste(m, queryString(query), sep="&"))) + }, + + getLogs = function(applicationId, entries = 50, streaming = FALSE, + writer = NULL) { + path <- paste("/applications/", applicationId, "/logs", sep="") + query <- paste("count=", entries, + "&tail=", if (streaming) "1" else "0", sep="") + handleResponse(GET(service, authInfo, path, query, writer = writer)) + }, + + createApplication = function(name, template, accountId) { + json <- list() + json$name <- name + json$template <- template + json$account <- as.numeric(accountId) + handleResponse(POST_JSON(service, authInfo, "/applications/", json)) + }, + + listApplicationProperties = function(applicationId) { + path <- paste("/applications/", applicationId, "/properties/", sep="") + handleResponse(GET(authInfo, path)) + }, + + setApplicationProperty = function(applicationId, propertyName, + propertyValue, force=FALSE) { + path <- paste("/applications/", applicationId, "/properties/", + propertyName, sep="") + v <- list() + v$value <- propertyValue + query <- paste("force=", if (force) "1" else "0", sep="") + handleResponse(PUT_JSON(authInfo, path, v, query)) + }, + + unsetApplicationProperty = function(applicationId, propertyName, + force=FALSE) { + path <- paste("/applications/", applicationId, "/properties/", + propertyName, sep="") + query <- paste("force=", if (force) "1" else "0", sep="") + handleResponse(DELETE(service, authInfo, path, query)) + }, + + uploadApplication = function(applicationId, bundlePath) { + path <- paste("/applications/", applicationId, "/upload", sep="") + handleResponse(POST(service, + authInfo, + path, + contentType="application/x-gzip", + file=bundlePath)) + }, + + deployApplication = function(applicationId, bundleId=NULL) { + path <- paste("/applications/", applicationId, "/deploy", sep="") + json <- list() + json$bundle <- as.numeric(bundleId) + handleResponse(POST_JSON(service, authInfo, path, json)) + }, + + terminateApplication = function(applicationId) { + path <- paste("/applications/", applicationId, "/terminate", sep="") + handleResponse(POST_JSON(service, authInfo, path, list())) + }, + + inviteApplicationUser = function(applicationId, email, + invite_email=NULL, invite_email_message=NULL) { + path <- paste("/applications/", applicationId, "/authorization/users", + sep="") + json <- list() + json$email <- email + if (!is.null(invite_email)) + json$invite_email=invite_email + if (!is.null(invite_email_message)) + json$invite_email_message=invite_email_message + handleResponse(POST_JSON(service, authInfo, path, json)) + }, + + addApplicationUser = function(applicationId, userId) { + path <- paste("/applications/", applicationId, "/authorization/users/", + userId, sep="") + handleResponse(PUT(service, authInfo, path, NULL)) + }, + + removeApplicationUser = function(applicationId, userId) { + path <- paste("/applications/", applicationId, "/authorization/users/", + userId, sep="") + handleResponse(DELETE(service, authInfo, path, NULL)) + }, + + listApplicationAuthoization = function(applicationId) { + path <- paste("/applications/", applicationId, "/authorization", + sep="") + listRequest(service, authInfo, path, NULL, "authorization") + }, + + listApplicationUsers = function(applicationId) { + path <- paste("/applications/", applicationId, "/authorization/users", + sep="") + listRequest(service, authInfo, path, NULL, "users") + }, + + listApplicationGroups = function(applicationId) { + path <- paste("/applications/", applicationId, "/authorization/groups", + sep="") + listRequest(service, authInfo, path, NULL, "groups") + }, + + listApplicationInvitations = function(applicationId) { + path <- "/invitations/" + query <- paste(filterQuery("app_id", applicationId), collapse="&") + listRequest(service, authInfo, path, query, "invitations") + }, + + listTasks = function(accountId, filters = NULL) { + if (is.null(filters)) { + filters <- vector() + } + path <- "/tasks/" + filters <- c(filterQuery("account_id", accountId), filters) + query <- paste(filters, collapse="&") + listRequest(service, authInfo, path, query, "tasks", max=100) + }, + + getTaskInfo = function(taskId) { + path <- paste("/tasks/", taskId, sep="") + handleResponse(GET(service, authInfo, path)) + }, + + getTaskLogs = function(taskId) { + path <- paste("/tasks/", taskId, "/logs/", sep="") + handleResponse(GET(service, authInfo, path)) + }, + + waitForTask = function(taskId, quiet = FALSE) { + + if (!quiet) { + cat("Waiting for task: ", taskId, "\n", sep="") + } + + path <- paste("/tasks/", taskId, sep="") + + lastStatus <- NULL + while(TRUE) { + + # check status + status <- handleResponse(GET(service, authInfo, path)) + + # display status to the user if it changed + if (!identical(lastStatus, status$description)) { + if (!quiet) + cat(" ", status$status, ": ", status$description, "\n", sep="") + lastStatus <- status$description + } + + # are we finished? (note: this codepath is the only way to exit this function) + if (status$finished) { + if (identical(status$status, "success")) { + return (NULL) + } else { + # always show task log on error + hr("Begin Task Log") + taskLog(taskId, authInfo$name, authInfo$server, output="stderr") + hr("End Task Log") + stop(status$error, call. = FALSE) + } + } + + # wait for 1 second before polling again + Sys.sleep(1) + } + } + ) +} + +listRequest = function(service, authInfo, path, query, listName, page = 100, + max=NULL) { + + # accumulate multiple pages of results + offset <- 0 + results <- list() + + while(TRUE) { + + # add query params + queryWithList <- paste(query, "&count=", page, "&offset=", offset, sep="") + + # make request and append the results + response <- handleResponse(GET(service, authInfo, path, queryWithList)) + results <- append(results, response[[listName]]) + + # update the offset + offset <- offset + response$count + + # get all results if no max was specified + if (is.null(max)) { + max = response$total + } + + # exit if we've got them all + if (length(results) >= response$total || length(results) >= max) + break + } + + return(results) +} + +filterQuery <- function(param, value, operator = NULL) { + if (is.null(operator)) { + op <- ":" + } else { + op <- paste(":", operator, ":", sep="") + } + q <- paste("filter=", param, op, value, sep="") + return(q) +} + +isContentType <- function(response, contentType) { + grepl(contentType, response$contentType, fixed = TRUE) +} diff --git a/R/restartApp.R b/R/restartApp.R new file mode 100644 index 0000000..f0bd8fd --- /dev/null +++ b/R/restartApp.R @@ -0,0 +1,34 @@ +#' Restart an Application +#' +#' Restart an application currently running on a remote server. +#' +#' @param appName Name of application to restart +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers (see \code{\link{servers}}) +#' @param quiet Request that no status information be printed to the console +#' during the operation. +#' @examples +#' \dontrun{ +#' +#' # restart an application +#' restartApp("myapp") +#' } +#' @seealso \code{\link{applications}}, \code{\link{deployApp}}, and +#' \code{\link{terminateApp}} +#' @export +restartApp <- function(appName, account = NULL, server = NULL, quiet = FALSE) { + + # define deploy task + taskDef <- list() + taskDef$beginStatus <- "Restarting application" + taskDef$endStatus <- "Application successfully restarted" + taskDef$action <- function(client, application) { + client$deployApplication(application$id) + } + + # perform it + applicationTask(taskDef, appName, account, server, quiet) +} + diff --git a/R/rmdindex.R b/R/rmdindex.R new file mode 100644 index 0000000..d069294 --- /dev/null +++ b/R/rmdindex.R @@ -0,0 +1,120 @@ + +# Write an index.htm file for an Rmd deployment if necessary (returns the +# files written so they can be removed after deployment) +writeRmdIndex <- function(appName, appDir) { + + # files written + files <- NULL + + # no index required for Shiny, or for directories with an index.Rmd + if (!file.exists(file.path(appDir, "ui.R")) && + !file.exists(file.path(appDir, "server.R")) && + !file.exists(file.path(appDir, "index.htm")) && + !file.exists(file.path(appDir, "index.Rmd"))) + { + # otherwise enumerate the Rmd files as the basis for the index + appFiles <- list.files(path = appDir, pattern = "\\.(rmd|html)$", + recursive = FALSE, ignore.case = TRUE) + + if (length(appFiles) == 1) + indexPage <- redirectWebPage(appFiles[1]) + else + indexPage <- listingWebPage(appName, appFiles) + + indexFile <- file.path(appDir, "index.htm") + files <- c(files, indexFile) + writeLines(indexPage, indexFile, useBytes = TRUE) + } + + files +} + +redirectWebPage <- function(appFile) { + meta <- paste('', sep = "") + webPage(meta, NULL) +} + +listingWebPage <- function(appDir, appFiles) { + + head <- c("") + + appDir <- htmlEscape(appDir) + appFiles <- htmlEscape(appFiles) + + body <- paste("

", basename(appDir), "

", sep = "") + body <- c(body, paste("", sep = "")) + + webPage(head, body) +} + +webPage <- function(head, body) { + + if (is.null(head)) + head <- c() + + if (is.null(body)) + body <- c() + + enc2utf8(c( + '', + '', + '', + '', + head, + '', + '', + body, + '', + '') + ) +} + +htmlEscape <- local({ + + .htmlSpecials <- list( + `&` = '&', + `<` = '<', + `>` = '>' + ) + .htmlSpecialsPattern <- paste(names(.htmlSpecials), collapse='|') + .htmlSpecialsAttrib <- c( + .htmlSpecials, + `'` = ''', + `"` = '"', + `\r` = ' ', + `\n` = ' ' + ) + .htmlSpecialsPatternAttrib <- paste(names(.htmlSpecialsAttrib), collapse='|') + + function(text, attribute=FALSE) { + pattern <- if(attribute) + .htmlSpecialsPatternAttrib + else + .htmlSpecialsPattern + + # Short circuit in the common case that there's nothing to escape + if (!any(grepl(pattern, text))) + return(text) + + specials <- if(attribute) + .htmlSpecialsAttrib + else + .htmlSpecials + + for (chr in names(specials)) { + text <- gsub(chr, specials[[chr]], text, fixed=TRUE) + } + + return(text) + } +}) + diff --git a/R/rpubs.R b/R/rpubs.R new file mode 100644 index 0000000..87c0c4b --- /dev/null +++ b/R/rpubs.R @@ -0,0 +1,171 @@ +#' Upload a file to RPubs +#' +#' This function publishes a file to rpubs.com. If the upload succeeds a +#' list that includes an \code{id} and \code{continueUrl} is returned. A browser +#' should be opened to the \code{continueUrl} to complete publishing of the +#' document. If an error occurs then a diagnostic message is returned in the +#' \code{error} element of the list. +#' +#' @param title The title of the document. +#' @param contentFile The path to the content file to upload. +#' @param originalDoc The document that was rendered to produce the +#' \code{contentFile}. May be \code{NULL} if the document is not known. +#' @param id If this upload is an update of an existing document then the id +#' parameter should specify the document id to update. Note that the id is +#' provided as an element of the list returned by successful calls to +#' \code{rpubsUpload}. +#' @param properties A named list containing additional document properties +#' (RPubs doesn't currently expect any additional properties, this parameter +#' is reserved for future use). +#' +#' @return A named list. If the upload was successful then the list contains a +#' \code{id} element that can be used to subsequently update the document as +#' well as a \code{continueUrl} element that provides a URL that a browser +#' should be opened to in order to complete publishing of the document. If the +#' upload fails then the list contains an \code{error} element which contains +#' an explanation of the error that occurred. +#' +#' @examples +#' \dontrun{ +#' # upload a document +#' result <- rpubsUpload("My document title", "Document.html") +#' if (!is.null(result$continueUrl)) +#' browseURL(result$continueUrl) +#' else +#' stop(result$error) +#' +#' # update the same document with a new title +#' updateResult <- rpubsUpload("My updated title", "Document.html", +#' id = result$id) +#' } +#' @export +rpubsUpload <- function(title, + contentFile, + originalDoc, + id = NULL, + properties = list()) { + + # validate inputs + if (!is.character(title)) + stop("title must be specified") + if (nzchar(title) == FALSE) + stop("title pmust be a non-empty string") + if (!is.character(contentFile)) + stop("contentFile parameter must be specified") + if (!file.exists(contentFile)) + stop("specified contentFile does not exist") + if (!is.list(properties)) + stop("properties paramater must be a named list") + + pathFromId <- function(id) { + split <- strsplit(id, "^https?://[^/]+")[[1]] + if (length(split) == 2) + return(split[2]) + else + return(NULL) + } + + buildPackage <- function(title, + contentFile, + properties = list()) { + + # build package.json + properties$title = title + packageJson <- RJSONIO::toJSON(properties) + + # create a tempdir to build the package in and copy the files to it + fileSep <- .Platform$file.sep + packageDir <- tempfile() + dir.create(packageDir) + packageFile <- function(fileName) { + paste(packageDir, fileName, sep = fileSep) + } + writeLines(packageJson, packageFile("package.json")) + file.copy(contentFile, packageFile("index.html")) + + # switch to the package dir for building + oldWd <- getwd() + setwd(packageDir) + on.exit(setwd(oldWd)) + + # create the tarball + tarfile <- tempfile("package", fileext = ".tar.gz") + utils::tar(tarfile, files = ".", compression = "gzip") + + # return the full path to the tarball + return(tarfile) + } + + # build the package + packageFile <- buildPackage(title, contentFile, properties) + + # determine whether this is a new doc or an update + isUpdate <- FALSE + method <- "POST" + path <- "/api/v1/document" + headers <- list() + headers$Connection <- "close" + if (!is.null(id)) { + isUpdate <- TRUE + path <- pathFromId(id) + method <- "PUT" + } + + # use https if using RCurl, and vanilla HTTP otherwise + http <- httpFunction() + if (identical(http, httpRCurl)) { + protocol <- "https" + port <- 443 + } else { + protocol <- "http" + port <- 80 + } + + # send the request + result <- http(protocol, "api.rpubs.com", port, method, path, headers, + "application/x-compressed", file = packageFile) + + # check for success + succeeded <- FALSE + if (isUpdate && (result$status == 200)) + succeeded <- TRUE + else if (result$status == 201) + succeeded <- TRUE + + # mark content as UTF-8 + content <- result$content + Encoding(content) <- "UTF-8" + + # return either id & continueUrl or error + if (succeeded) { + parsedContent <- RJSONIO::fromJSON(content) + id <- ifelse(isUpdate, id, result$location) + url <- as.character(parsedContent["continueUrl"]) + + # we use the source doc as the key for the deployment record as long as + # it's a recognized document path; otherwise we use the content file + recordSource <- ifelse(!is.null(originalDoc) && isDocumentPath(originalDoc), + originalDoc, contentFile) + + # use the title if given, and the filename name of the document if not + recordName <- ifelse(is.null(title) || nchar(title) == 0, + basename(recordSource), title) + + rpubsRec <- deploymentRecord(recordName, "rpubs", "rpubs.com", id, id, url, + as.numeric(Sys.time())) + rpubsRecFile <- deploymentFile(recordSource, recordName, "rpubs", + "rpubs.com") + write.dcf(rpubsRec, rpubsRecFile, width = 4096) + + # record in global history + if (!is.null(originalDoc) && nzchar(originalDoc)) + addToDeploymentHistory(originalDoc, rpubsRec) + + # return the publish information + return(list(id = id, + continueUrl = url)) + } else { + return(list(error = content)) + } +} + diff --git a/R/rsa.R b/R/rsa.R new file mode 100644 index 0000000..4674fcb --- /dev/null +++ b/R/rsa.R @@ -0,0 +1,19 @@ + +# generate a unique ID +createUniqueId <- function(bytes) { + paste(as.hexmode(sample(256, bytes)-1), collapse="") +} + +# generateToken generates a token for signing requests sent to the RStudio +# Connect service. The token's ID and public key are sent to the server, and +# the private key is saved locally. +generateToken <- function() { + key <- PKI::PKI.genRSAkey(bits = 2048L) + priv.der <- PKI::PKI.save.key(key, format = "DER") + pub.der <- PKI::PKI.save.key(key, format = "DER", private = FALSE) + list( + token = paste0("T", createUniqueId(16)), + public_key = RCurl::base64Encode(pub.der), + private_key = RCurl::base64Encode(priv.der) + ) +} diff --git a/R/rsconnect-package.R b/R/rsconnect-package.R new file mode 100644 index 0000000..ac4f61b --- /dev/null +++ b/R/rsconnect-package.R @@ -0,0 +1,59 @@ +##' rsconnect +##' +##' Deployment Interface for R Markdown Documents and Shiny Applications +##' +##' The rsconnect package provides a programmatic deployment +##' interface for RPubs, shinyapps.io, and RStudio Connect. Supported contents +##' types include R Markdown documents, Shiny applications, plots, and static +##' web content. +##' +##' @section Managing Applications: +##' +##' Deploy and manage applications with the following functions: +##' +##' \tabular{ll}{ +##' +##' \code{\link{deployApp}:} \tab +##' Deploy a Shiny application to a server.\cr\cr +##' +##' \code{\link{configureApp}:} \tab +##' Configure an application currently running on a server.\cr\cr +##' +##' \code{\link{restartApp}:} \tab +##' Restart an application currently running on a server.\cr\cr +##' +##' \code{\link{terminateApp}:} \tab +##' Terminate an application currently running on a server.\cr\cr +##' +##' \code{\link{deployments}:} \tab +##' List deployment records for a given application directory. +##' +##' } +##' +##' More information on application management is available in the +##' \code{\link{applications}} help page. +##' +##' @section Managing Accounts and Users: +##' +##' Manage accounts on the local system. +## +##' \tabular{ll}{ +##' +##' \code{\link{setAccountInfo}:} \tab +##' Register an account.\cr\cr +##' +##' \code{\link{removeAccount}:} \tab +##' Remove an account.\cr\cr +##' +##' \code{\link{accountInfo}:} \tab +##' View information for a given account.\cr\cr +##' } +##' +##' More information on account management is available in the +##' \code{\link{accounts}} help page. +##' +##' @name rsconnect-package +##' @aliases rsconnect-package rsconnect +##' @docType package +##' @keywords package +NULL diff --git a/R/servers.R b/R/servers.R new file mode 100644 index 0000000..acc1fc1 --- /dev/null +++ b/R/servers.R @@ -0,0 +1,210 @@ +#' Server Management Functions +#' +#' Functions to manage the list of known servers to which +#' \pkg{rsconnect} can deploy and manage applications. +#' +#' Register a server with \code{addServer} or \code{discoverServers} (the latter +#' is useful only if your administrator has configured server autodiscovery). +#' Once a server is registered, you can connect to an account on the server +#' using \code{\link{connectUser}}. +#' +#' The \code{servers} and \code{serverInfo} functions are provided for viewing +#' previously registered servers. +#' +#' There is always at least one server registered (the \code{shinyapps.io} +#' server) +#' +#' @param name Optional nickname for the server. If none is given, the nickname +#' is inferred from the server's hostname. +#' @param url Server's URL. Should look like \code{http://servername/} or +#' \code{http://servername:port/}. +#' @param local Return only local servers (i.e. not \code{shinyapps.io}) +#' @param quiet Suppress output and prompts where possible. +#' @return +#' \code{servers} returns a data frame with registered server names and URLs. +#' \code{serverInfo} returns a list with details for a particular server. +#' @rdname servers +#' @examples +#' \dontrun{ +#' +#' # register a local server +#' addServer("http://myrsconnect/", "myserver") +#' +#' # list servers +#' servers(local = TRUE) +#' +#' # connect to an account on the server +#' connectUser(server = "myserver") +#' } +#' @export +servers <- function(local = FALSE) { + configFiles <- list.files(serverConfigDir(), pattern=glob2rx("*.dcf"), + full.names = TRUE) + parsed <- lapply(configFiles, read.dcf) + locals <- do.call(rbind, parsed) + if (local) { + locals + } else { + rbind(locals, as.data.frame(shinyappsServerInfo(), stringsAsFactors = FALSE)) + } +} + +serverConfigDir <- function() { + rsconnectConfigDir("servers") +} + +serverConfigFile <- function(name) { + normalizePath(file.path(serverConfigDir(), paste(name, ".dcf", sep="")), + mustWork = FALSE) +} + +shinyappsServerInfo <- function() { + info <- list(name = "shinyapps.io", + url = getOption("rsconnect.shinyapps_url", "https://api.shinyapps.io/v1")) +} + +#' @rdname servers +#' @export +discoverServers <- function(quiet = FALSE) { + # TODO: Better discovery mechanism? + discovered <- getOption("rsconnect.local_servers", "http://localhost:3939/__api__") + + # get the URLs of the known servers, and silently add any that aren't yet + # present + existing <- servers()[,"url"] + introduced <- setdiff(discovered, existing) + lapply(introduced, function(url) { addServer(url, quiet = TRUE) }) + + if (!quiet && length(introduced) > 0) { + message("Discovered ", length(introduced), + (if (length(introduced) == 1) "server" else "servers"), ":") + lapply(introduced, message) + } else if (!quiet) { + message("No new servers found.") + } + invisible(introduced) +} + +getDefaultServer <- function(local = FALSE, prompt = TRUE) { + existing <- servers(local) + # if there are no existing servers, silently try to discover one to work with + if (length(existing) == 0 || nrow(existing) == 0) { + discoverServers(quiet = TRUE) + existing <- servers(local) + } + + # if exactly one server exists, return it + if (nrow(existing) == 1) { + return(list(name = as.character(existing[,"name"]), + url = as.character(existing[,"url"]))) + } + + # no default server, prompt if there are multiple choices + if (nrow(existing) > 1 && prompt && interactive()) { + name <- as.character(existing[1,"name"]) + message("Registered servers: ", paste(existing[,"name"], collapse = ", ")) + input <- readline(paste0( + "Which server (default '", name ,"')? ")) + if (nchar(input) > 0) { + name <- input + } + return(serverInfo(name)) + } +} + +#' @rdname servers +#' @export +addConnectServer <- function(url, name = NULL, quiet = FALSE) { + addServer(ensureConnectServerUrl(url), name, quiet) +} + +#' @rdname servers +#' @export +addServer <- function(url, name = NULL, quiet = FALSE) { + if (!isStringParam(url)) + stop(stringParamErrorMessage("url")) + + serverUrl <- parseHttpUrl(url) + + # TODO: test server by hitting URL and getting config? + + # if no name is supplied for the server, make one up based on the host portion + # of its URL + if (is.null(name)) { + name <- serverUrl$host + if (!quiet && interactive()) { + input <- readline(paste0( + "Enter a nickname for this server (default '", name, "'): ")) + if (nchar(input) > 0) { + name <- input + } + } + } + + # write the server info + configFile <- serverConfigFile(name) + write.dcf(list(name = name, + url = url), + configFile) + + if (!quiet) { + message("Server '", name, "' added successfully: ", url) + } +} + +#' @rdname servers +#' @export +removeServer <- function(name) { + if (!isStringParam(name)) + stop(stringParamErrorMessage("name")) + configFile <- serverConfigFile(name) + if (file.exists(configFile)) + unlink(configFile) + else + warning("The server '", name,"' is not currently registered.") +} + + +#' @rdname servers +#' @export +serverInfo <- function(name) { + if (!isStringParam(name)) + stop(stringParamErrorMessage("name")) + + # there's no config file for shinyapps.io + if (identical(name, "shinyapps.io")) { + return(shinyappsServerInfo()) + } + + configFile <- serverConfigFile(name) + if (!file.exists(configFile)) + stop(missingServerErrorMessage(name)) + + serverDcf <- readDcf(serverConfigFile(name), all=TRUE) + info <- as.list(serverDcf) + info +} + +missingServerErrorMessage <- function(name) { + paste0("server named '", name, "' does not exist") +} + +clientForAccount <- function(account) { + + if (account$server == shinyappsServerInfo()$name) + lucidClient(shinyappsServerInfo()$url, account) + else { + server <- serverInfo(account$server) + connectClient(server$url, account) + } +} + +ensureConnectServerUrl <- function(url) { + # ensure 'url' ends with '/__api__' + if (!grepl("/__api__$", url)) + url <- paste(url, "/__api__", sep = "") + + # if we have duplicated leading slashes, remove them + url <- gsub("(/+__api__)$", "/__api__", url) + url +} diff --git a/R/static-analysis.R b/R/static-analysis.R new file mode 100644 index 0000000..e69de29 diff --git a/R/tasks.R b/R/tasks.R new file mode 100644 index 0000000..cf00875 --- /dev/null +++ b/R/tasks.R @@ -0,0 +1,89 @@ +#' List Tasks +#' +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers (see \code{\link{servers}}) +#' @return +#' Returns a data frame with the following columns: +#' \tabular{ll}{ +#' \code{id} \tab Task id \cr +#' \code{action} \tab Task action\cr +#' \code{status} \tab Current task status\cr +#' \code{created_time} \tab Task creation time\cr +#' \code{finished_time} \tab Task finished time\cr +#' } +#' @examples +#' \dontrun{ +#' +#' # list tasks for the default account +#' tasks() +#' +#' } +#' @seealso \code{\link{taskLog}} +#' @export +tasks <- function(account = NULL, server = NULL) { + + # resolve account and create connect client + accountDetails <- accountInfo(resolveAccount(account, server), server) + client <- clientForAccount(accountDetails) + + # list tasks + tasks <- client$listTasks(accountDetails$accountId) + + # extract the subset of fields we're interested in + res <- lapply(tasks, `[`, c('id', 'action', 'status', 'created_time')) + + # convert to data frame + res <- do.call(rbind, res) + + as.data.frame(res, stringsAsFactors = FALSE) +} + + +#' Show task log +#' +#' Writes the task log for the given task +#' @param taskId Task Id +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers (see \code{\link{servers}}) +#' @param output Where to write output. Valid values are \code{NULL} or \code{stderr} +#' @examples +#' \dontrun{ +#' +#' # write task log to stdout +#' taskLog(12345) +#' +#' # write task log to stderr +#' taskLog(12345, output="stderr") +#' +#' } +#' @seealso \code{\link{tasks}} +#' @export +taskLog <- function(taskId, account = NULL, server = NULL, output = NULL) { + + # resolve account and create connect client + accountDetails <- accountInfo(resolveAccount(account, server), server) + client <- clientForAccount(accountDetails) + + if (identical(output, "stderr")) { + conn <- stderr() + } else{ + conn <- "" + } + + # show task log + cat(client$getTaskLogs(taskId), file=conn) + + # get child tasks + tasks <- client$listTasks(accountDetails$accountId, + filters=filterQuery("parent_id", taskId)) + + # get child task logs + for (task in tasks) { + taskLog(task['id'], account = account, server = server, output = output) + } + +} diff --git a/R/terminateApp.R b/R/terminateApp.R new file mode 100644 index 0000000..31a50f0 --- /dev/null +++ b/R/terminateApp.R @@ -0,0 +1,35 @@ +#' Terminate an Application +#' +#' Terminate an application currently running on a remote server. +#' +#' @param appName Name of application to terminate +#' @param account Account name. If a single account is registered on the system +#' then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers (see \code{\link{servers}}) +#' @param quiet Request that no status information be printed to the console +#' during the termination. +#' @examples +#' \dontrun{ +#' +#' # terminate an application +#' terminateApp("myapp") +#' } +#' @seealso \code{\link{applications}}, \code{\link{deployApp}}, and +#' \code{\link{restartApp}} +#' @export +terminateApp <- function(appName, account = NULL, server = NULL, + quiet = FALSE) { + + # define terminate task + taskDef <- list() + taskDef$beginStatus <- "Terminating application" + taskDef$endStatus <- "Application successfully terminated" + taskDef$action <- function(client, application) { + client$terminateApplication(application$id) + } + + # perform it + applicationTask(taskDef, appName, account, server = server, quiet) +} + diff --git a/R/usage.R b/R/usage.R new file mode 100644 index 0000000..9683ceb --- /dev/null +++ b/R/usage.R @@ -0,0 +1,149 @@ +#' Show Application Usage +#' +#' Show application usage of a currently deployed application +#' @param appName Name of application +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @param usageType Use metric to retreive (for example: "hours") +#' @param from Date range starting timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param until Date range ending timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param interval Summarization interval. Data points at intervals less then this +#' will be grouped. (Number of seconds or relative time delta e.g. "1h"). +#' @note This function only works for ShinyApps servers. +#' @export +showUsage <- function(appDir=getwd(), appName=NULL, account = NULL, server=NULL, + usageType="hours", from=NULL, until=NULL, interval=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # intialize client + api <- clientForAccount(accountDetails) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # get application usage + data <- api$getAccountUsage(accountDetails$accountId, + usageType, + application$id, + from, + until, + interval) + + if (length(data$points) < 1) { + stop("No data.", call.=FALSE) + } + + # get data points + points <- data$points[[1]] + points <- lapply(points, function(X) { + X[[1]] <- X[[1]]/1000 # convert from milliseconds to seconds + X + }) + + # convert to data frame + df <- data.frame(matrix(unlist(points), nrow=length(points), byrow=T), stringsAsFactors=FALSE) + colnames(df) <- c("timestamp", usageType) + return(df) +} + +#' Show Application Metrics +#' +#' Show application metrics of a currently deployed application +#' @param metricSeries Metric series to query e.g. "container.cpu" +#' @param metricNames Metric names in the series to query e.g. c("cpu.user", "cpu.system") +#' @param appName Name of application +#' @param appDir Directory containing application. Defaults to +#' current working directory. +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @param from Date range starting timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param until Date range ending timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param interval Summarization interval. Data points at intervals less then this +#' will be grouped. (Number of seconds or relative time delta e.g. "1h"). +#' @note This function only works for ShinyApps servers. +#' @export +showMetrics <- function(metricSeries, metricNames, appDir=getwd(), appName=NULL, account = NULL, server=NULL, + from=NULL, until=NULL, interval=NULL) { + + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # intialize client + api <- clientForAccount(accountDetails) + + # resolve application + if (is.null(appName)) + appName = basename(appDir) + application <- resolveApplication(accountDetails, appName) + + # get application usage + data <- api$getApplicationMetrics(application$id, + metricSeries, + metricNames, + from, + until, + interval) + + if (length(data$points) < 1) { + stop("No data.", call.=FALSE) + } + + # get data points + points <- data$points + points <- lapply(points, function(X) { + X$time <- X$time/1000 # convert from milliseconds to seconds + X + }) + + # convert to data frame + df <- data.frame(matrix(unlist(points), nrow=length(points), byrow=T), stringsAsFactors=FALSE) + colnames(df) <- c(metricNames, "timestamp") + return(df) +} + +#' Show Account Usage +#' +#' Show account usage +#' @param account Account name. If a single account is registered on the +#' system then this parameter can be omitted. +#' @param server Server name. Required only if you use the same account name on +#' multiple servers. +#' @param usageType Use metric to retreive (for example: "hours") +#' @param from Date range starting timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param until Date range ending timestamp (Unix timestamp or relative time +#' delta such as "2d" or "3w"). +#' @param interval Summarization interval. Data points at intervals less then this +#' will be grouped. (Number of seconds or relative time delta e.g. "1h"). +#' @note This function only works for ShinyApps servers. +#' @export +accountUsage <- function(account=NULL, server=NULL, usageType="hours", + from=NULL, until=NULL, interval=NULL) { + # resolve account + accountDetails <- accountInfo(resolveAccount(account, server), server) + + # intialize client + api <- clientForAccount(accountDetails) + + # get application usage + data <- api$getAccountUsage(accountDetails$accountId, + usageType, + NULL, + from, + until, + interval) +} diff --git a/R/utils.R b/R/utils.R new file mode 100644 index 0000000..9425be2 --- /dev/null +++ b/R/utils.R @@ -0,0 +1,169 @@ +.globals <- new.env(parent = emptyenv()) + +isStringParam <- function(param) { + is.character(param) && (length(param) == 1) +} + +stringParamErrorMessage <- function(param) { + paste(param, "must be a single element character vector") +} + +regexExtract <- function(re, input) { + match <- regexec(re, input) + matchLoc <- match[1][[1]] + if (length(matchLoc) > 1) { + matchLen <-attributes(matchLoc)$match.length + return (substr(input, matchLoc[2], matchLoc[2] + matchLen[2]-1)) + } + else { + return (NULL) + } +} + +displayStatus <- function(quiet) { + quiet <- quiet || httpDiagnosticsEnabled() + function (status) { + if (!quiet) + cat(status) + } +} + +withStatus <- function(quiet) { + quiet <- quiet || httpDiagnosticsEnabled() + function(status, code) { + if (!quiet) + cat(status, "...", sep="") + force(code) + if (!quiet) + cat("DONE\n") + } +} + +httpDiagnosticsEnabled <- function() { + return (getOption("rsconnect.http.trace", FALSE) || + getOption("rsconnect.http.verbose", FALSE)) +} + +readPassword <- function(prompt) { + if (rstudioapi::hasFun("askForPassword")) { + password <- rstudioapi::askForPassword(prompt) + } else { + + os <- Sys.info()[['sysname']] + + echoOff <- function() { + if (identical(os, "Darwin") || identical(os, "Linux")) { + #system("stty cbreak -echo <&2") + } else { + # TODO: disable echo on Windows + } + } + + echoOn <- function() { + if (identical(os, "Darwin") || identical(os, "Linux")) { + #system("stty echo") + } else { + # TODO: enable echo on Windows + } + } + + echoOff() + password <- readline(prompt) + echoOn() + } + return (password) +} + +# wrapper around read.dcf to workaround LC_CTYPE bug +readDcf <- function(...) { + loc <- Sys.getlocale('LC_CTYPE') + on.exit(Sys.setlocale('LC_CTYPE', loc)) + read.dcf(...) +} + + +#' Generate a line with embedded message +#' +#' Generates a message, surrounded with \code{#}, that extends +#' up to length \code{n}. +#' @param message A string (single-line message). +#' @param n The total number length of the generated string -- +#' the message is padded with \code{#} up to length \code{n}. +#' @noRd +hr <- function(message = "", n = 80) { + if (nzchar(message)) { + r <- as.integer((n - nchar(message) - 2) / 2) + hr <- paste(rep.int("#", r), collapse = '') + cat(hr, message, hr, sep=" ", '\n') + } else { + hr <- paste(rep.int("#", n), collapse = '') + cat(hr, sep="", '\n') + } +} + +# this function was defined in the shiny package; in the unlikely event that +# shiny:::checkEncoding() is not available, use a simplified version here +checkEncoding2 <- function(file) { + tryCatch( + getFromNamespace('checkEncoding', 'shiny')(file), + error = function(e) { + if (.Platform$OS.type != 'windows') return('UTF-8') + x <- readLines(file, encoding = 'UTF-8', warn = FALSE) + isUTF8 <- !any(is.na(iconv(x, 'UTF-8'))) + if (isUTF8) 'UTF-8' else getOption('encoding') + } + ) +} + +# if shiny:::checkEncoding() gives UTF-8, use it, otherwise first consider +# the RStudio project encoding, and eventually getOption('encoding') +checkEncoding <- function(file) { + enc1 <- .globals$encoding + enc2 <- checkEncoding2(file) + if (enc2 == 'UTF-8') return(enc2) + if (length(enc1)) enc1 else enc2 +} + +# read the Encoding field from the *.Rproj file +rstudioEncoding <- function(dir) { + proj <- list.files(dir, '[.]Rproj$', full.names = TRUE) + if (length(proj) != 1L) return() # there should be one and only one .Rproj + enc <- drop(readDcf(proj, 'Encoding')) + enc[!is.na(enc)] +} + +# return the leaf from a path (e.g. /foo/abc/def -> def) +fileLeaf <- function(path) { + components <- strsplit(path, "/") + unlist(lapply(components, function(component) { + component[length(component)] + })) +} + +# whether the given path points to an individual piece of content +isDocumentPath <- function(path) { + ext <- tolower(tools::file_ext(path)) + !is.null(ext) && ext != "" +} + +# given a path, return the directory under which rsconnect package state is +# stored +rsconnectRootPath <- function(appPath) { + if (isDocumentPath(appPath)) + file.path(dirname(appPath), "rsconnect", "documents", basename(appPath)) + else + file.path(appPath, "rsconnect") +} + +dirExists <- function(x) { + utils::file_test('-d', x) +} + +capitalize <- function(x) { + if (nchar(x) == 0) + x + else + paste0(toupper(substr(x, 1, 1)), substring(x, 2)) +} + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..df55473 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +rsconnect +======================================================= + +An R package used for deploying applications to the [ShinyApps](http://shinyapps.io/) hosted service. + +## Installation + +To install directly from GitHub, run this: + +```r +if (!require("devtools")) + install.packages("devtools") +devtools::install_github("rstudio/rsconnect") +``` + +## Usage + +To get started using ShinyApps checkout the [Getting Started Guide](http://shiny.rstudio.com/articles/shinyapps.html). diff --git a/inst/cert/cacert.pem b/inst/cert/cacert.pem new file mode 100644 index 0000000..7fbc29a --- /dev/null +++ b/inst/cert/cacert.pem @@ -0,0 +1,3637 @@ +## +## ca-bundle.crt -- Bundle of CA Root Certificates +## +## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012 +## +## 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: +## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 +## +## 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. +## + +# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $ + +GTE CyberTrust Global Root +========================== +-----BEGIN CERTIFICATE----- +MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg +Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG +A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz +MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL +Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 +IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u +sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql +HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID +AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW +M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF +NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ +-----END CERTIFICATE----- + +Thawte Server CA +================ +-----BEGIN CERTIFICATE----- +MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE +AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j +b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV +BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u +c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG +A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 +ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl +/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 +1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J +GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ +GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= +-----END CERTIFICATE----- + +Thawte Premium Server CA +======================== +-----BEGIN CERTIFICATE----- +MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT +DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs +dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE +AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl +ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT +AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU +VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 +aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ +cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 +aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh +Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ +qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm +SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf +8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t +UCemDaYj+bvLpgcUQg== +-----END CERTIFICATE----- + +Equifax Secure CA +================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE +ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 +MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT +B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR +fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW +8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE +CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS +spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 +zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB +BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 +70+sB3c4 +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 1 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy +MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE +NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i +o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq +kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 +RbyhkwS7hp86W0N6w4pl +-----END CERTIFICATE----- + +Digital Signature Trust Co. Global CA 3 +======================================= +-----BEGIN CERTIFICATE----- +MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE +ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy +MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs +IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA +A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD +VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS +xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo +BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 +dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw +IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY +MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM +BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB +AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi +up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 +mPnHfxsb1gYgAlihw6ID +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA +TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah +WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf +Tqj/ZA1k +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G2 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT +MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz +dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO +FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 +lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB +MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT +1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD +Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 +-----END CERTIFICATE----- + +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----- + +GlobalSign Root CA - R2 +======================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv +YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh +bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT +aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln +bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 +ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp +s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN +S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL +TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C +ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E +FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i +YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN +BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp +9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu +01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 +9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 +TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== +-----END CERTIFICATE----- + +ValiCert Class 1 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy +MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi +GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm +DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG +lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX +icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP +Orf1LXLI +-----END CERTIFICATE----- + +ValiCert Class 2 VA +=================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC +CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf +ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ +SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV +UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 +W9ViH0Pd +-----END CERTIFICATE----- + +RSA Root Certificate 1 +====================== +-----BEGIN CERTIFICATE----- +MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp +b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs +YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh +bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw +MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 +d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg +UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 +LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td +3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H +BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs +3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF +V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r +on+jjBXu +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 +EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc +cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw +EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj +055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f +j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC +/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 +xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa +t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== +-----END CERTIFICATE----- + +Verisign Class 4 Public Primary Certification Authority - G3 +============================================================ +-----BEGIN CERTIFICATE----- +MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh +dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw +CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy +dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS +tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM +8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW +Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX +Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA +j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt +mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm +fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd +RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG +UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== +-----END CERTIFICATE----- + +Entrust.net Secure Server CA +============================ +-----BEGIN CERTIFICATE----- +MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg +cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl +ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG +A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi +eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p +dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ +aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 +gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw +ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw +CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l +dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF +bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu +dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw +NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow +HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA +BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN +Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 +n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= +-----END CERTIFICATE----- + +Entrust.net Premium 2048 Secure Server CA +========================================= +-----BEGIN CERTIFICATE----- +MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u +ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp +bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV +BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx +NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 +d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl +MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u +ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL +Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr +hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW +nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi +VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC +AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER +gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B +AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo +oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS +o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z +2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX +OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== +-----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----- + +Equifax Secure Global eBusiness CA +================================== +-----BEGIN CERTIFICATE----- +MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp +bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx +HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds +b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV +PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN +qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn +hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs +MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN +I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY +NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 1 +============================= +-----BEGIN CERTIFICATE----- +MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB +LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE +ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz +IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ +1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a +IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk +MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW +Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF +AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 +lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ +KpYrtWKmpj29f5JZzVoqgrI3eQ== +-----END CERTIFICATE----- + +Equifax Secure eBusiness CA 2 +============================= +-----BEGIN CERTIFICATE----- +MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE +ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y +MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT +DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn +2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 +BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG +A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx +JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG +A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e +uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB +Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 +jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia +78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm +V+GRMOrN +-----END CERTIFICATE----- + +AddTrust Low-Value Services Root +================================ +-----BEGIN CERTIFICATE----- +MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU +cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw +CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO +ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 +54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr +oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 +Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui +GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w +HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD +AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT +RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw +HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt +ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph +iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY +eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr +mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj +ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= +-----END CERTIFICATE----- + +AddTrust External Root +====================== +-----BEGIN CERTIFICATE----- +MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD +VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw +NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU +cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg +Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 ++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw +Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo +aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy +2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 +7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P +BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL +VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk +VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB +IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl +j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 +6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 +e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u +G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= +-----END CERTIFICATE----- + +AddTrust Public Services Root +============================= +-----BEGIN CERTIFICATE----- +MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU +cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ +BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l +dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu +nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i +d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG +Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw +HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G +A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux +FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G +A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 +JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL ++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao +GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 +Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H +EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= +-----END CERTIFICATE----- + +AddTrust Qualified Certificates Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML +QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU +cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx +CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ +IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx +64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 +KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o +L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR +wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU +MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ +BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE +BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y +azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD +ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG +GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X +dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze +RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB +iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= +-----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----- + +RSA Security 2048 v3 +==================== +-----BEGIN CERTIFICATE----- +MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK +ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy +MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb +BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 +Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb +WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH +KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP ++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ +MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E +FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY +v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj +0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj +VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 +nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA +pKnXwiJPZ9d37CAFYd4= +-----END CERTIFICATE----- + +GeoTrust Global CA +================== +-----BEGIN CERTIFICATE----- +MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK +Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw +MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo +BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet +8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc +T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU +vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD +AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk +DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q +zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 +d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 +mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p +XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm +Mw== +-----END CERTIFICATE----- + +GeoTrust Global CA 2 +==================== +-----BEGIN CERTIFICATE----- +MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw +MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j +LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ +NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k +LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA +Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b +HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF +MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH +K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 +srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh +ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL +OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC +x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF +H4z1Ir+rzoPz4iIprn2DQKi6bA== +-----END CERTIFICATE----- + +GeoTrust Universal CA +===================== +-----BEGIN CERTIFICATE----- +MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 +MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu +Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t +JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e +RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs +7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d +8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V +qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga +Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB +Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu +KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 +ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 +XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB +hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc +aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 +qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL +oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK +xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF +KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 +DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK +xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU +p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI +P/rmMuGNG2+k5o7Y+SlIis5z/iw= +-----END CERTIFICATE----- + +GeoTrust Universal CA 2 +======================= +-----BEGIN CERTIFICATE----- +MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 +MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg +SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA +A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 +DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 +j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q +JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a +QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 +WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP +20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn +ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC +SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG +8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 ++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E +BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z +dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ +4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ +mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq +A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg +Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP +pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d +FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp +gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm +X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS +-----END CERTIFICATE----- + +America Online Root Certification Authority 1 +============================================= +-----BEGIN CERTIFICATE----- +MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG +v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z +DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh +sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP +8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T +AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z +o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf +GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF +VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft +3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g +Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds +sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 +-----END CERTIFICATE----- + +America Online Root Certification Authority 2 +============================================= +-----BEGIN CERTIFICATE----- +MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT +QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp +Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG +A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg +T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en +fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 +f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO +qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN +RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 +gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn +6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid +FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 +Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj +B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op +aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE +AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY +T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p ++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg +JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy +zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO +ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh +1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf +GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff +Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP +cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= +-----END CERTIFICATE----- + +Visa eCommerce Root +=================== +-----BEGIN CERTIFICATE----- +MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG +EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug +QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 +WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm +VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv +bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL +F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b +RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 +TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI +/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs +GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG +MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc +CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW +YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz +zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu +YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt +398znM/jra6O1I7mT1GvFpLgXPYHDw== +-----END CERTIFICATE----- + +Certum Root CA +============== +-----BEGIN CERTIFICATE----- +MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK +ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla +Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u +by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x +wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL +kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ +89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K +Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P +NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq +hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ +GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg +GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ +0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS +qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== +-----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----- + +Comodo Secure Services root +=========================== +-----BEGIN CERTIFICATE----- +MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw +MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu +Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi +BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP +9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc +rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC +oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V +p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E +FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w +gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj +YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm +aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm +4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj +Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL +DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw +pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H +RR3B7Hzs/Sk= +-----END CERTIFICATE----- + +Comodo Trusted Services root +============================ +-----BEGIN CERTIFICATE----- +MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS +R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg +TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw +MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h +bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw +IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 +3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y +/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 +juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS +ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud +DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB +/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp +ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl +cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw +uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 +pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA +BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l +R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O +9y5Xt5hwXsjEeLBi +-----END CERTIFICATE----- + +QuoVadis Root CA +================ +-----BEGIN CERTIFICATE----- +MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE +ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 +eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz +MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp +cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD +EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk +J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL +F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL +YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen +AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w +PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y +ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 +MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj +YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs +ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh +Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW +Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu +BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw +FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 +tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo +fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul +LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x +gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi +5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi +5nrQNiOKSnQ2+Q== +-----END CERTIFICATE----- + +QuoVadis Root CA 2 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +QuoVadis Root CA 3 +================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Security Communication Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP +U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw +8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM +DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX +5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd +DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 +JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw +DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g +0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a +mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ +s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ +6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi +FL39vmwLAw== +-----END CERTIFICATE----- + +Sonera Class 2 Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG +U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw +NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh +IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 +/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT +dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG +f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P +tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH +nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT +XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt +0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI +cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph +Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx +EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH +llpwrN9M +-----END CERTIFICATE----- + +Staat der Nederlanden Root CA +============================= +-----BEGIN CERTIFICATE----- +MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE +ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w +HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh +bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt +vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P +jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca +C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth +vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 +22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV +HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v +dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN +BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR +EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw +MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y +nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR +iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== +-----END CERTIFICATE----- + +TDC Internet Root CA +==================== +-----BEGIN CERTIFICATE----- +MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE +ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx +NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu +ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j +xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL +znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc +5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 +otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI +AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM +VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM +MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC +AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe +UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G +CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m +gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ +2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb +O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU +Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l +-----END CERTIFICATE----- + +UTN DATACorp SGC Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ +BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa +MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w +HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy +dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys +raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo +wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA +9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv +33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud +DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 +BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD +LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 +DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft +Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 +I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx +EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP +DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI +-----END CERTIFICATE----- + +UTN USERFirst Hardware Root CA +============================== +-----BEGIN CERTIFICATE----- +MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE +BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl +IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd +BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx +OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 +eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz +ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI +wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd +tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 +i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf +Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw +gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF +lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF +UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF +BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM +//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW +XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 +lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn +iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 +nfhmqA== +-----END CERTIFICATE----- + +Camerfirma Chambers of Commerce Root +==================================== +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx +NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp +cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn +MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC +AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU +xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH +NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW +DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV +d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud +EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v +cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P +AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh +bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD +VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz +aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi +fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD +L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN +UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n +ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 +erfutGWaIZDgqtCYvDi1czyL+Nw= +-----END CERTIFICATE----- + +Camerfirma Global Chambersign Root +================================== +-----BEGIN CERTIFICATE----- +MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe +QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i +ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx +NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt +YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg +MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw +ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J +1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O +by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl +6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c +8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ +BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j +aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B +Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj +aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y +ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh +bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA +PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y +gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ +PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 +IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes +t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== +-----END CERTIFICATE----- + +NetLock Notary (Class A) Root +============================= +-----BEGIN CERTIFICATE----- +MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI +EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j +ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX +DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH +EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD +VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz +cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM +D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ +z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC +/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 +tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 +4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG +A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC +Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv +bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu +IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn +LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 +ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz +IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh +IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu +b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh +bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg +Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp +bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 +ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP +ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB +CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr +KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM +8CgHrTwXZoi1/baI +-----END CERTIFICATE----- + +NetLock Business (Class B) Root +=============================== +-----BEGIN CERTIFICATE----- +MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg +VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD +VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv +bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg +VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB +iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S +o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr +1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV +HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ +RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh +dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 +ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv +c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg +YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh +c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz +Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA +bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl +IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 +YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj +cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM +43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR +stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI +-----END CERTIFICATE----- + +NetLock Express (Class C) Root +============================== +-----BEGIN CERTIFICATE----- +MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT +CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV +BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD +KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ +BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 +dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j +ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB +jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z +W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 +euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw +DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN +RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn +YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB +IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i +aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 +ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs +ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo +dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y +emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k +IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ +UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg +YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 +xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW +gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== +-----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----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE +FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 +Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj +YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH +AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw +Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg +U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 +LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl +cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh +cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT +dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC +AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh +3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm +vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk +fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 +fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ +EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq +yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl +1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ +lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro +g14= +-----END CERTIFICATE----- + +Taiwan GRCA +=========== +-----BEGIN CERTIFICATE----- +MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG +EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X +DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv +dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN +w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 +BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O +1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO +htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov +J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 +Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t +B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB +O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 +lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV +HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 +09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ +TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj +Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 +Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU +D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz +DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk +Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk +7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ +CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy ++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS +-----END CERTIFICATE----- + +Firmaprofesional Root CA +======================== +-----BEGIN CERTIFICATE----- +MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT +GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp +Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA +ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL +MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT +OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 +ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V +j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH +lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf +3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 +NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww +KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG +AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud +DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD +ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq +u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf +wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm +7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG +VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= +-----END CERTIFICATE----- + +Wells Fargo Root CA +=================== +-----BEGIN CERTIFICATE----- +MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV +BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl +bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv +MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX +x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 +E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 +OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j +sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj +YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF +BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD +ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv +m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R +OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx +x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 +tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= +-----END CERTIFICATE----- + +Swisscom Root CA 1 +================== +-----BEGIN CERTIFICATE----- +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 +NY6E0F/6MBr1mmz0DlP5OlvRHA== +-----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----- + +Certplus Class 2 Primary CA +=========================== +-----BEGIN CERTIFICATE----- +MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE +BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN +OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy +dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR +5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ +Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO +YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e +e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME +CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ +YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t +L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD +P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R +TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ +7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW +//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 +l7+ijrRU +-----END CERTIFICATE----- + +DST Root CA X3 +============== +-----BEGIN CERTIFICATE----- +MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK +ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X +DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 +cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT +rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 +UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy +xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d +utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ +MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug +dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE +GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw +RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS +fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ +-----END CERTIFICATE----- + +DST ACES CA X6 +============== +-----BEGIN CERTIFICATE----- +MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG +EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT +MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha +MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE +CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI +DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa +pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow +GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy +MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud +EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu +Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy +dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU +CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 +5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t +Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq +nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs +vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 +oKfN5XozNmr6mis= +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 1 +============================================== +-----BEGIN CERTIFICATE----- +MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP +MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 +acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx +MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg +U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB +TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC +aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX +yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i +Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ +8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 +W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME +BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 +sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE +q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy +B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY +nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H +-----END CERTIFICATE----- + +TURKTRUST Certificate Services Provider Root 2 +============================================== +-----BEGIN CERTIFICATE----- +MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF +bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP +MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg +QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN +MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr +dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G +A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls +acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe +LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI +x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g +QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr +5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB +AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G +A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt +Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 +Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ +hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P +9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 +UrbnBEI= +-----END CERTIFICATE----- + +SwissSign Gold CA - G2 +====================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +SwissSign Silver CA - G2 +======================== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority +======================================== +-----BEGIN CERTIFICATE----- +MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx +CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ +cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN +b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 +nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge +RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt +tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD +AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI +hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K +Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN +NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa +Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG +1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= +-----END CERTIFICATE----- + +thawte Primary Root CA +====================== +-----BEGIN CERTIFICATE----- +MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 +MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg +SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv +KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT +FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs +oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ +1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc +q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K +aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p +afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD +VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF +AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE +uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX +xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 +jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH +z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G5 +============================================================ +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln +biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh +dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt +YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz +j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD +Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ +Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r +fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ +BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv +Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG +SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ +X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE +KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC +Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE +ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----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----- + +Network Solutions Certificate Authority +======================================= +-----BEGIN CERTIFICATE----- +MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG +EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr +IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx +MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu +MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx +jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT +aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT +crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc +/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB +AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv +bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA +A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q +4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ +GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv +wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD +ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey +-----END CERTIFICATE----- + +WellsSecure Public Root Certificate Authority +============================================= +-----BEGIN CERTIFICATE----- +MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM +F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw +NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN +MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl +bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD +VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 +iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 +i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 +bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB +K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB +AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu +cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm +lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB +i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww +GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg +Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI +K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 +bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj +qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es +E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ +tylv2G0xffX8oRAHh84vWdw+WNs= +-----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----- + +IGC/A +===== +-----BEGIN CERTIFICATE----- +MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD +VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE +Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy +MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI +EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT +STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 +TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW +So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy +HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd +frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ +tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB +egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC +iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK +q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q +MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg +Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI +lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF +0mBWWg== +-----END CERTIFICATE----- + +Security Communication EV RootCA1 +================================= +-----BEGIN CERTIFICATE----- +MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc +U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh +dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE +BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl +Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO +/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX +WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z +ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 +bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK +9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG +SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm +iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG +Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW +mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW +T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 +-----END CERTIFICATE----- + +OISTE WISeKey Global Root GA CA +=============================== +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE +BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG +A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH +bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD +VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw +IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 +IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 +Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg +Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD +d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ +/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R +LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw +AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ +KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm +MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 ++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa +hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY +okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= +-----END CERTIFICATE----- + +Microsec e-Szigno Root CA +========================= +-----BEGIN CERTIFICATE----- +MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE +BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL +EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 +MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz +dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT +GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB +AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG +d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N +oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc +QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ +PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb +MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG +IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD +VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 +LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A +dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn +AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA +4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg +AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA +egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 +Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO +PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv +c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h +cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw +IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT +WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV +MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER +MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp +Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal +HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT +nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE +aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a +86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK +yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB +S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= +-----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----- + +AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. +====================================== +-----BEGIN CERTIFICATE----- +MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT +AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg +LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w +HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ +U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh +IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN +yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU +2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 +4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP +2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm +8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf +HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa +Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK +5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b +czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g +ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF +BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug +cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf +AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX +EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v +/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 +MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 +3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk +eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f +/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h +RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU +Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 2 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw +MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw +IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 +xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ +Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u +SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G +dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ +KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj +TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP +JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk +vQ== +-----END CERTIFICATE----- + +TC TrustCenter Class 3 CA II +============================ +-----BEGIN CERTIFICATE----- +MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy +IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw +MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 +c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE +AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W +yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo +6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ +uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk +2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB +/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB +7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 +Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU +cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i +SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u +TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE +O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 +yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 +IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal +092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc +5A== +-----END CERTIFICATE----- + +TC TrustCenter Universal CA I +============================= +-----BEGIN CERTIFICATE----- +MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN +MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg +VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw +JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD +ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC +qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv +xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw +ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O +gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j +BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG +1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy +vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 +ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT +ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a +7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY +-----END CERTIFICATE----- + +Deutsche Telekom Root CA 2 +========================== +-----BEGIN CERTIFICATE----- +MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT +RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG +A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 +MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G +A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS +b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 +bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI +KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY +AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK +Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV +jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV +HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr +E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy +zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 +rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G +dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU +Cm26OWMohpLzGITY+9HPBVZkVw== +-----END CERTIFICATE----- + +ComSign Secured CA +================== +-----BEGIN CERTIFICATE----- +MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE +AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w +NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD +QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw +ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs +49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH +7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB +kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 +9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw +AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t +U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA +j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC +AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a +BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp +FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP +51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz +OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== +-----END CERTIFICATE----- + +Cybertrust Global Root +====================== +-----BEGIN CERTIFICATE----- +MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li +ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 +MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD +ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA ++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW +0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL +AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin +89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT +8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP +BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 +MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G +A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO +lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi +5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 +hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T +X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW +WL1WMRJOEcgh4LMRkWXbtKaIOM5V +-----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----- + +T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 +============================================================================================================================= +-----BEGIN CERTIFICATE----- +MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH +DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q +aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry +b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV +BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg +S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 +MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl +IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF +n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl +IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft +dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl +cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO +Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 +xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR +6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL +hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd +BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF +MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 +N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT +y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh +LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M +dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= +-----END CERTIFICATE----- + +Buypass Class 2 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 +MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M +cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 +0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 +0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R +uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV +1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt +7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 +fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w +wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho +-----END CERTIFICATE----- + +Buypass Class 3 CA 1 +==================== +-----BEGIN CERTIFICATE----- +MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU +QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 +MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh +c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx +ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 +n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia +AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c +1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P +AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 +pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA +EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 +htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj +el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 +-----END CERTIFICATE----- + +EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 +========================================================================== +-----BEGIN CERTIFICATE----- +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 +-----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----- + +CNNIC ROOT +========== +-----BEGIN CERTIFICATE----- +MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE +ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw +OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD +o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz +VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT +VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or +czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK +y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC +wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S +lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 +Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM +O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 +BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 +G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m +mxE= +-----END CERTIFICATE----- + +ApplicationCA - Japanese Government +=================================== +-----BEGIN CERTIFICATE----- +MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT +SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw +MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl +cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 +fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN +wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE +jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu +nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU +WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV +BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD +vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs +o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g +/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD +io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW +dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL +rosot4LKGAfmt1t06SAZf7IbiVQ= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G3 +============================================= +-----BEGIN CERTIFICATE----- +MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE +BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 +IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy +eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz +NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo +YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT +LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j +K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE +c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C +IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu +dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC +MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr +2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 +cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE +Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD +AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s +t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt +-----END CERTIFICATE----- + +thawte Primary Root CA - G2 +=========================== +-----BEGIN CERTIFICATE----- +MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC +VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu +IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg +Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV +MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG +b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt +IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS +LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 +8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU +mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN +G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K +rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== +-----END CERTIFICATE----- + +thawte Primary Root CA - G3 +=========================== +-----BEGIN CERTIFICATE----- +MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE +BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 +aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv +cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w +ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh +d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD +VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG +A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At +P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC ++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY +7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW +vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ +KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK +A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu +t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC +8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm +er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= +-----END CERTIFICATE----- + +GeoTrust Primary Certification Authority - G2 +============================================= +-----BEGIN CERTIFICATE----- +MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC +VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu +Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD +ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 +OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg +MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl +b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG +BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc +KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD +VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ +EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m +ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 +npaqBA+K +-----END CERTIFICATE----- + +VeriSign Universal Root Certification Authority +=============================================== +-----BEGIN CERTIFICATE----- +MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE +BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO +ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk +IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u +IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV +UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv +cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl +IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj +1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP +MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 +9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I +AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR +tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G +CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O +a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud +DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 +Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx +Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx +P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P +wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 +mJO37M2CYfE45k+XmCpajQ== +-----END CERTIFICATE----- + +VeriSign Class 3 Public Primary Certification Authority - G4 +============================================================ +-----BEGIN CERTIFICATE----- +MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC +VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 +b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz +ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU +cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo +b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 +Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz +rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB +/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw +HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u +Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD +A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx +AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== +-----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----- + +Staat der Nederlanden Root CA - G2 +================================== +-----BEGIN CERTIFICATE----- +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 +66+KAQ== +-----END CERTIFICATE----- + +CA Disig +======== +-----BEGIN CERTIFICATE----- +MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK +QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw +MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz +bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm +GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD +Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo +hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt +ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w +gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P +AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz +aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff +ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa +BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t +WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 +mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ +CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K +ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA +4Z7CRneC9VkGjCFMhwnN5ag= +-----END CERTIFICATE----- + +Juur-SK +======= +-----BEGIN CERTIFICATE----- +MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA +c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw +DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG +SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy +aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf +TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC ++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw +UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa +Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF +MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD +HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh +AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA +cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr +AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw +cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE +FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G +A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo +ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL +abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 +IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh +Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 +yyqcjg== +-----END CERTIFICATE----- + +Hongkong Post Root CA 1 +======================= +-----BEGIN CERTIFICATE----- +MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT +DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx +NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n +IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 +ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr +auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh +qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY +V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV +HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i +h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio +l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei +IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps +T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT +c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== +-----END CERTIFICATE----- + +SecureSign RootCA11 +=================== +-----BEGIN CERTIFICATE----- +MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi +SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS +b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw +KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 +cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL +TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO +wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq +g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP +O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA +bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX +t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh +OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r +bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ +Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 +y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 +lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= +-----END CERTIFICATE----- + +ACEDICOM Root +============= +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Verisign Class 3 Public Primary Certification Authority +======================================================= +-----BEGIN CERTIFICATE----- +MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx +FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 +IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow +XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz +IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA +A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 +f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol +hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky +CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX +bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ +D/xwzoiQ +-----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----- + +E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi +=================================================== +-----BEGIN CERTIFICATE----- +MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz +ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 +MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 +cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u +aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY +8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y +jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI +JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk +9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD +AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG +SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d +F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq +D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 +Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq +fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX +-----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----- + +TC TrustCenter Universal CA III +=============================== +-----BEGIN CERTIFICATE----- +MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC +REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy +IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe +Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU +QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex +KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt +QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO +juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut +CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 +M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G +A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ +BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA +g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ +KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK +BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV +CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq +woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== +-----END CERTIFICATE----- + +Autoridad de Certificacion Firmaprofesional CIF A62634068 +========================================================= +-----BEGIN CERTIFICATE----- +MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA +BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 +MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw +QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB +NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD +Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P +B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY +7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH +ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI +plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX +MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX +LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK +bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU +vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud +EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH +DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp +cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA +bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx +ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx +51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk +R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP +T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f +Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl +osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR +crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR +saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD +KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi +6Et8Vcad+qMUu2WFbm5PEn4KPJ2V +-----END CERTIFICATE----- + +Izenpe.com +========== +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- + +Chambers of Commerce Root - 2008 +================================ +-----BEGIN CERTIFICATE----- +MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy +Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl +ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF +EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl +cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA +XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj +h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ +ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk +NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g +D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 +lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ +0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj +ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 +EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI +G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ +BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh +bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh +bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC +CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH +AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 +wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH +3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU +RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 +M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 +YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF +9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK +zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG +nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg +OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ +-----END CERTIFICATE----- + +Global Chambersign Root - 2008 +============================== +-----BEGIN CERTIFICATE----- +MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD +MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv +bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu +QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx +NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg +Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ +QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD +aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf +VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf +XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 +ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB +/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA +TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M +H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe +Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF +HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh +wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB +AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT +BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE +BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm +aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm +aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp +1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 +dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG +/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 +ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s +dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg +9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH +foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du +qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr +P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq +c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z +09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B +-----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----- + +Certinomis - Autorité Racine +============================= +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK +Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg +LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG +A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw +JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa +wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly +Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw +2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N +jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q +c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC +lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb +xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g +530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna +4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G +A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ +KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x +WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva +R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 +nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B +CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv +JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE +qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b +WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE +wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ +vgt2Fl43N+bYdJeimUV5 +-----END CERTIFICATE----- + +Root CA Generalitat Valenciana +============================== +-----BEGIN CERTIFICATE----- +MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE +ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 +IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 +WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE +CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 +F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B +ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ +D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte +JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB +AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n +dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB +ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl +AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA +YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy +AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA +aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt +AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA +YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu +AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA +OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 +dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV +BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G +A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S +b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh +TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz +Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 +NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH +iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt ++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= +-----END CERTIFICATE----- + +A-Trust-nQual-03 +================ +-----BEGIN CERTIFICATE----- +MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE +Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy +a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R +dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw +RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 +ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 +c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA +zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n +yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE +SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 +iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V +cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV +eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 +ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr +sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd +JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS +mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 +ahq97BvIxYSazQ== +-----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----- + +EC-ACC +====== +-----BEGIN CERTIFICATE----- +MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE +BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w +ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD +VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE +CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT +BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 +MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt +SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl +Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh +cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK +w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT +ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 +HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a +E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw +0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD +VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 +Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l +dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ +lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa +Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe +l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 +E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D +5EI= +-----END CERTIFICATE----- + +Hellenic Academic and Research Institutions RootCA 2011 +======================================================= +-----BEGIN CERTIFICATE----- +MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT +O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y +aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT +AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z +IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo +IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI +1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa +71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u +8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH +3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ +MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 +MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu +b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt +XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 +TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD +/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N +7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 +-----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----- + +Trustis FPS Root CA +=================== +-----BEGIN CERTIFICATE----- +MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG +EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 +IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV +BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ +RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk +H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa +cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt +o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA +AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd +BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c +GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC +yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P +8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV +l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl +iB6XzCGcKQENZetX2fNXlrtIzYE= +-----END CERTIFICATE----- + +StartCom Certification Authority +================================ +-----BEGIN CERTIFICATE----- +MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu +ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 +NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk +LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg +U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw +ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y +o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ +Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d +eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt +2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z +6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ +osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ +untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc +UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT +37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD +VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ +Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 +dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu +c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv +bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 +aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 +aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t +L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG +cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 +fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm +N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN +Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T +tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX +e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA +2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs +HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE +JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib +D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= +-----END CERTIFICATE----- + +StartCom Certification Authority G2 +=================================== +-----BEGIN CERTIFICATE----- +MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN +U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg +RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE +ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp +dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O +o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG +4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi +Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul +Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs +O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H +vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L +nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS +FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa +z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E +BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ +KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K +2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk +J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ +JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG +/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc +nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld +blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc +l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm +7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm +obp573PYtlNXLfbQ4ddI +-----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----- + +EE Certification Centre Root CA +=============================== +-----BEGIN CERTIFICATE----- +MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG +EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy +dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw +MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB +UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy +ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM +TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 +rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw +93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN +P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ +MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF +BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj +xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM +lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u +uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU +3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM +dcGWxZ0= +-----END CERTIFICATE----- + +GoDaddy - G2 With Cross to G1, includes Root +============================================ +-----BEGIN CERTIFICATE----- +MIIE0DCCA7igAwIBAgIBBzANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx +EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT +EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp +ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTExMDUwMzA3MDAwMFoXDTMxMDUwMzA3 +MDAwMFowgbQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH +EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjEtMCsGA1UE +CxMkaHR0cDovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMTMwMQYDVQQD +EypHbyBEYWRkeSBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IC0gRzIwggEi +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC54MsQ1K92vdSTYuswZLiBCGzD +BNliF44v/z5lz4/OYuY8UhzaFkVLVat4a2ODYpDOD2lsmcgaFItMzEUz6ojcnqOv +K/6AYZ15V8TPLvQ/MDxdR/yaFrzDN5ZBUY4RS1T4KL7QjL7wMDge87Am+GZHY23e +cSZHjzhHU9FGHbTj3ADqRay9vHHZqm8A29vNMDp5T19MR/gd71vCxJ1gO7GyQ5HY +pDNO6rPWJ0+tJYqlxvTV0KaudAVkV4i1RFXULSo6Pvi4vekyCgKUZMQWOlDxSq7n +eTOvDCAHf+jfBDnCaQJsY1L6d8EbyHSHyLmTGFBUNUtpTrw700kuH9zB0lL7AgMB +AAGjggEaMIIBFjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV +HQ4EFgQUQMK9J47MNIMwojPX+2yz8LQsgM4wHwYDVR0jBBgwFoAUOpqFBxBnKLbv +9r0FQW4gwZTaD94wNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8v +b2NzcC5nb2RhZGR5LmNvbS8wNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5n +b2RhZGR5LmNvbS9nZHJvb3QtZzIuY3JsMEYGA1UdIAQ/MD0wOwYEVR0gADAzMDEG +CCsGAQUFBwIBFiVodHRwczovL2NlcnRzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkv +MA0GCSqGSIb3DQEBCwUAA4IBAQAIfmyTEMg4uJapkEv/oV9PBO9sPpyIBslQj6Zz +91cxG7685C/b+LrTW+C05+Z5Yg4MotdqY3MxtfWoSKQ7CC2iXZDXtHwlTxFWMMS2 +RJ17LJ3lXubvDGGqv+QqG+6EnriDfcFDzkSnE3ANkR/0yBOtg2DZ2HKocyQetawi +DsoXiWJYRBuriSUBAA/NxBti21G00w9RKpv0vHP8ds42pM3Z2Czqrpv1KrKQ0U11 +GIo/ikGQI31bS/6kA1ibRrLDYGCD+H1QQc7CoZDDu+8CL9IVVO5EFdkKrqeKM+2x +LXY2JtwE65/3YR8V3Idv7kaWKK2hJn0KCacuBKONvPi8BDAB +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEfTCCA2WgAwIBAgIDG+cVMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVT +MSEwHwYDVQQKExhUaGUgR28gRGFkZHkgR3JvdXAsIEluYy4xMTAvBgNVBAsTKEdv +IERhZGR5IENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMTAx +MDcwMDAwWhcNMzEwNTMwMDcwMDAwWjCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT +B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHku +Y29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1 +dGhvcml0eSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv3Fi +CPH6WTT3G8kYo/eASVjpIoMTpsUgQwE7hPHmhUmfJ+r2hBtOoLTbcJjHMgGxBT4H +Tu70+k8vWTAi56sZVmvigAf88xZ1gDlRe+X5NbZ0TqmNghPktj+pA4P6or6KFWp/ +3gvDthkUBcrqw6gElDtGfDIN8wBmIsiNaW02jBEYt9OyHGC0OPoCjM7T3UYH3go+ +6118yHz7sCtTpJJiaVElBWEaRIGMLKlDliPfrDqBmg4pxRyp6V0etp6eMAo5zvGI +gPtLXcwy7IViQyU0AlYnAZG0O3AqP26x6JyIAX2f1PnbU21gnb8s51iruF9G/M7E +GwM8CetJMVxpRrPgRwIDAQABo4IBFzCCARMwDwYDVR0TAQH/BAUwAwEB/zAOBgNV +HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9BUFuIMGU2g/eMB8GA1Ud +IwQYMBaAFNLEsNKR1EwRcbNhyz2h/t2oatTjMDQGCCsGAQUFBwEBBCgwJjAkBggr +BgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRkeS5jb20vMDIGA1UdHwQrMCkwJ6Al +oCOGIWh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Ryb290LmNybDBGBgNVHSAEPzA9 +MDsGBFUdIAAwMzAxBggrBgEFBQcCARYlaHR0cHM6Ly9jZXJ0cy5nb2RhZGR5LmNv +bS9yZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAWQtTvZKGEacke+1bMc8d +H2xwxbhuvk679r6XUOEwf7ooXGKUwuN+M/f7QnaF25UcjCJYdQkMiGVnOQoWCcWg +OJekxSOTP7QYpgEGRJHjp2kntFolfzq3Ms3dhP8qOCkzpN1nsoX+oYggHFCJyNwq +9kIDN0zmiN/VryTyscPfzLXs4Jlet0lUIDyUGAzHHFIYSaRt4bNYC8nY7NmuHDKO +KHAN4v6mF56ED71XcLNa6R+ghlO773z/aQvgSMO3kwvIClTErF0UZzdsyqUvMQg3 +qm5vjLyb4lddJIGvl5echK1srDdMZvNhkREg5L4wn3qkKQmw4TRfZHcYQFHfjDCm +rw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh +MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE +YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 +MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo +ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg +MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN +ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA +PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w +wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi +EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY +avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ +YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE +sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h +/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 +IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj +YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD +ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy +OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P +TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ +HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER +dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf +ReYNnyicsbkqWletNw+vHX/bvZ8= +-----END CERTIFICATE----- + diff --git a/inst/examples/diamonds/server.R b/inst/examples/diamonds/server.R new file mode 100644 index 0000000..de5f9e3 --- /dev/null +++ b/inst/examples/diamonds/server.R @@ -0,0 +1,30 @@ +library(shiny) +library(ggplot2) + +shinyServer(function(input, output) { + + dataset <- reactive(function() { + diamonds[sample(nrow(diamonds), input$sampleSize),] + }) + + output$plot <- reactivePlot(function() { + + p <- ggplot(dataset(), aes_string(x=input$x, y=input$y)) + geom_point() + + if (input$color != 'None') + p <- p + aes_string(color=input$color) + + facets <- paste(input$facet_row, '~', input$facet_col) + if (facets != '. ~ .') + p <- p + facet_grid(facets) + + if (input$jitter) + p <- p + geom_jitter() + if (input$smooth) + p <- p + geom_smooth() + + print(p) + + }, height=700) + +}) diff --git a/inst/examples/diamonds/ui.R b/inst/examples/diamonds/ui.R new file mode 100644 index 0000000..b09b6b0 --- /dev/null +++ b/inst/examples/diamonds/ui.R @@ -0,0 +1,29 @@ +library(shiny) +library(ggplot2) + +dataset <- diamonds + +shinyUI(pageWithSidebar( + + headerPanel("Diamonds Explorer"), + + sidebarPanel( + + sliderInput('sampleSize', 'Sample Size', min=1, max=nrow(dataset), + value=min(1000, nrow(dataset)), step=500, round=0), + + selectInput('x', 'X', names(dataset)), + selectInput('y', 'Y', names(dataset), names(dataset)[[2]]), + selectInput('color', 'Color', c('None', names(dataset))), + + checkboxInput('jitter', 'Jitter'), + checkboxInput('smooth', 'Smooth'), + + selectInput('facet_row', 'Facet Row', c(None='.', names(dataset))), + selectInput('facet_col', 'Facet Column', c(None='.', names(dataset))) + ), + + mainPanel( + plotOutput('plot') + ) +)) diff --git a/inst/examples/sessioninfo/server.R b/inst/examples/sessioninfo/server.R new file mode 100644 index 0000000..f1ad353 --- /dev/null +++ b/inst/examples/sessioninfo/server.R @@ -0,0 +1,27 @@ +library(shiny) + +shinyServer(function(input, output, session) { + + # output sessionInfo + output$sessionInfo <- renderPrint({ + sessionInfo() + }) + + # output urlInfo + output$urlInfo <- renderText({ + paste(sep = "", + "protocol: ", session$clientData$url_protocol, "\n", + "hostname: ", session$clientData$url_hostname, "\n", + "pathname: ", session$clientData$url_pathname, "\n", + "port: ", session$clientData$url_port, "\n", + "search: ", session$clientData$url_search, "\n" + ) + }) + + # output userInfo + output$userInfo <- renderText({ + paste(sep="", + "user: ", session$user, "\n") + }) + +}) diff --git a/inst/examples/sessioninfo/ui.R b/inst/examples/sessioninfo/ui.R new file mode 100644 index 0000000..1416240 --- /dev/null +++ b/inst/examples/sessioninfo/ui.R @@ -0,0 +1,12 @@ +library(shiny) + +shinyUI(fluidPage( + h3("URL"), + verbatimTextOutput("urlInfo"), + + h3("Session"), + verbatimTextOutput("sessionInfo"), + + h3("User"), + verbatimTextOutput("userInfo") +)) diff --git a/man/accountUsage.Rd b/man/accountUsage.Rd new file mode 100644 index 0000000..62bd326 --- /dev/null +++ b/man/accountUsage.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/usage.R +\name{accountUsage} +\alias{accountUsage} +\title{Show Account Usage} +\usage{ +accountUsage(account = NULL, server = NULL, usageType = "hours", + from = NULL, until = NULL, interval = NULL) +} +\arguments{ +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} + +\item{usageType}{Use metric to retreive (for example: "hours")} + +\item{from}{Date range starting timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{until}{Date range ending timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{interval}{Summarization interval. Data points at intervals less then this +will be grouped. (Number of seconds or relative time delta e.g. "1h").} +} +\description{ +Show account usage +} +\note{ +This function only works for ShinyApps servers. +} + diff --git a/man/accounts.Rd b/man/accounts.Rd new file mode 100644 index 0000000..db12091 --- /dev/null +++ b/man/accounts.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accounts.R +\name{accounts} +\alias{accountInfo} +\alias{accounts} +\alias{removeAccount} +\title{Account Management Functions} +\usage{ +accounts(server = NULL) + +accountInfo(name, server = NULL) + +removeAccount(name, server = NULL) +} +\arguments{ +\item{server}{Name of the server on which the account is registered +(optional; see \code{\link{servers}})} + +\item{name}{Name of account} +} +\value{ +\code{accounts} returns a data frame with the names of all accounts +registered on the system and the servers on which they reside. +\code{accountInfo} returns a list with account details. +} +\description{ +Functions to enumerate and remove accounts on the local system. Prior to +deploying applications you need to register your account on the local system. +} +\details{ +You register an account using the \code{\link{setAccountInfo}} function (for +ShinyApps) or \code{\link{connectUser}} function (for other servers). You can +subsequently remove the account using the \code{removeAccount} function. + +The \code{accounts} and \code{accountInfo} functions are provided for viewing +previously registered accounts. +} + diff --git a/man/addAuthorizedUser.Rd b/man/addAuthorizedUser.Rd new file mode 100644 index 0000000..dbe7963 --- /dev/null +++ b/man/addAuthorizedUser.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{addAuthorizedUser} +\alias{addAuthorizedUser} +\title{Add authorized user to application} +\usage{ +addAuthorizedUser(email, appDir = getwd(), appName = NULL, account = NULL, + server = NULL, sendEmail = NULL) +} +\arguments{ +\item{email}{Email address of user to add.} + +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application.} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} + +\item{sendEmail}{Send an email letting the user know the application +has been shared with them.} +} +\description{ +Add authorized user to application +} +\note{ +This function works only for ShinyApps servers. +} +\seealso{ +\code{\link{removeAuthorizedUser}} and \code{\link{showUsers}} +} + diff --git a/man/addLinter.Rd b/man/addLinter.Rd new file mode 100644 index 0000000..5b3d929 --- /dev/null +++ b/man/addLinter.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lint-framework.R +\name{addLinter} +\alias{addLinter} +\title{Add a Linter} +\usage{ +addLinter(name, linter) +} +\arguments{ +\item{name}{The name of the linter, as a string.} + +\item{linter}{A \code{\link{linter}}.} +} +\description{ +Add a linter, to be used in subsequent calls to \code{\link{lint}}. +} +\examples{ +addLinter("no.capitals", linter( + + ## Identify lines containing capital letters -- either by name or by index + apply = function(content, ...) { + grep("[A-Z]", content) + }, + + ## Only use this linter on R files (paths ending with .r or .R) + takes = function(paths) { + grep("[rR]$", paths) + }, + + # Use the default message constructor + message = function(content, lines, ...) { + makeLinterMessage("Capital letters found on the following lines", content, lines) + }, + + # Give a suggested prescription + suggest = "Do not use capital letters in these documents." +)) +} + diff --git a/man/appDependencies.Rd b/man/appDependencies.Rd new file mode 100644 index 0000000..4950744 --- /dev/null +++ b/man/appDependencies.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/dependencies.R +\name{appDependencies} +\alias{appDependencies} +\title{Detect Application Dependencies} +\usage{ +appDependencies(appDir = getwd(), appFiles = NULL) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to current working +directory.} + +\item{appFiles}{The files and directories to bundle and deploy (only if +\code{upload = TRUE}). Can be \code{NULL}, in which case all the files in +the directory containing the application are bundled. Takes precedence over +\code{appFileManifest} if both are supplied.} +} +\value{ +Returns a data frame listing the package + dependencies detected for the application: \tabular{ll}{ \code{package} + \tab Name of package \cr \code{version} \tab Version of package\cr } +} +\description{ +Recursively detect all package dependencies for an application. This function +parses all .R files in the applicaition directory to determine what packages +the application depends on; and for each of those packages what other +packages they depend on. +} +\details{ +Dependencies are determined by parsing application source code and + looking for calls to \code{library}, \code{require}, \code{::}, and + \code{:::}. + + Recursive dependencies are detected by examining the \code{Depends}, + \code{Imports}, and \code{LinkingTo} fields of the packages immediately + dependend on by the application. +} +\note{ +Since the \code{Suggests} field is not included when determining + recursive dependencies of packages, it's possible that not every package + required to run your application will be detected. + + In this case, you can force a package to be included dependency by + inserting call(s) to \code{require} within your source directory. This code + need not actually execute, for example you could create a standalone file + named \code{dependencies.R} with the following code: \cr \cr + \code{require(xts)} \cr \code{require(colorspace)} \cr + + This will force the \code{xts} and \code{colorspace} packages to be + installed along with the rest of your application when it is deployed. +} +\examples{ +\dontrun{ + +# dependencies for the app in the current working dir +appDependencies() + +# dependencies for an app in another directory +appDependencies("~/projects/shiny/app1") +} +} +\seealso{ +\link[rsconnect:rsconnectPackages]{Using Packages with rsconnect} +} + diff --git a/man/applications.Rd b/man/applications.Rd new file mode 100644 index 0000000..3726196 --- /dev/null +++ b/man/applications.Rd @@ -0,0 +1,49 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/applications.R +\name{applications} +\alias{applications} +\title{List Deployed Applications} +\usage{ +applications(account = NULL, server = NULL) +} +\arguments{ +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} +} +\value{ +Returns a data frame with the following columns: +\tabular{ll}{ +\code{name} \tab Name of application \cr +\code{url} \tab URL where application can be accessed\cr +\code{config_url} \tab URL where application can be configured\cr +\code{status} \tab Current status of application. Valid values are +\code{pending}, \code{deploying}, \code{running}, \code{terminating}, and +\code{terminated}. +} +} +\description{ +List all applications currently deployed for a given account. +} +\note{ +To register an account you call the \link{setAccountInfo} function. +} +\examples{ +\dontrun{ + +# list all applications for the default account +applications() + +# list all applications for a specific account +applications("myaccount") + +# view the list of applications in the data viewer +View(applications()) +} +} +\seealso{ +\code{\link{deployApp}}, \code{\link{terminateApp}} +} + diff --git a/man/authorizedUsers.Rd b/man/authorizedUsers.Rd new file mode 100644 index 0000000..292fcd9 --- /dev/null +++ b/man/authorizedUsers.Rd @@ -0,0 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{authorizedUsers} +\alias{authorizedUsers} +\title{(Deprecated) List authorized users for an application} +\usage{ +authorizedUsers(appDir = getwd()) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to current working +directory.} +} +\description{ +(Deprecated) List authorized users for an application +} + diff --git a/man/configureApp.Rd b/man/configureApp.Rd new file mode 100644 index 0000000..3191ae0 --- /dev/null +++ b/man/configureApp.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/configureApp.R +\name{configureApp} +\alias{configureApp} +\title{Configure an Application} +\usage{ +configureApp(appName, appDir = getwd(), account = NULL, server = NULL, + redeploy = TRUE, size = NULL, instances = NULL, quiet = FALSE) +} +\arguments{ +\item{appName}{Name of application to configure} + +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers (see \code{\link{servers}})} + +\item{redeploy}{Re-deploy application after its been configured.} + +\item{size}{Configure application instance size} + +\item{instances}{Configure number of application instances} + +\item{quiet}{Request that no status information be printed to the console +during the deployment.} +} +\description{ +Configure an application running on a remote server. +} +\examples{ +\dontrun{ + +# set instance size for an application +configureApp("myapp", size="xlarge") +} +} +\seealso{ +\code{\link{applications}}, \code{\link{deployApp}} +} + diff --git a/man/connectUser.Rd b/man/connectUser.Rd new file mode 100644 index 0000000..6945661 --- /dev/null +++ b/man/connectUser.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accounts.R +\name{connectUser} +\alias{connectUser} +\title{Connect User Account} +\usage{ +connectUser(account = NULL, server = NULL, quiet = FALSE) +} +\arguments{ +\item{account}{A name for the account to connect. Optional.} + +\item{server}{The server to connect to. Optional if there is only one server +registered.} + +\item{quiet}{Whether or not to show messages and prompts while connecting the +account.} +} +\description{ +Connect a user account to the package so that it can be used to deploy and +manage applications on behalf of the account. +} +\details{ +When this function is invoked, a web browser will be opened to a + page on the target server where you will be prompted to enter your + credentials. Upon successful authentication, your local installation of + \pkg{rsconnect} and your server account will be paired, and you'll + be able to deploy and manage applications using the package without further + prompts for credentials. +} + diff --git a/man/deployApp.Rd b/man/deployApp.Rd new file mode 100644 index 0000000..58740eb --- /dev/null +++ b/man/deployApp.Rd @@ -0,0 +1,98 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deployApp.R +\name{deployApp} +\alias{deployApp} +\title{Deploy an Application} +\usage{ +deployApp(appDir = getwd(), appFiles = NULL, appFileManifest = NULL, + appPrimaryDoc = NULL, appSourceDoc = NULL, appName = NULL, + contentCategory = NULL, account = NULL, server = NULL, upload = TRUE, + launch.browser = getOption("rsconnect.launch.browser", interactive()), + quiet = FALSE, lint = TRUE, metadata = list()) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to current working +directory.} + +\item{appFiles}{The files and directories to bundle and deploy (only if +\code{upload = TRUE}). Can be \code{NULL}, in which case all the files in +the directory containing the application are bundled. Takes precedence over +\code{appFileManifest} if both are supplied.} + +\item{appFileManifest}{An alternate way to specify the files to be deployed; +a file containing the names of the files, one per line, relative to the +\code{appDir}.} + +\item{appPrimaryDoc}{If the application contains more than one document, this +parameter indicates the primary one, as a path relative to \code{appDir}. +Can be \code{NULL}, in which case the primary document is inferred from the +contents being deployed.} + +\item{appSourceDoc}{If the application is composed of static files (e.g +HTML), this parameter indicates the source document, if any, as a fully +qualified path. Deployment information returned by +\code{\link{deployments}} is associated with the source document.} + +\item{appName}{Name of application (names must be unique within an +account). Defaults to the base name of the specified \code{appDir}.} + +\item{contentCategory}{Optional; the kind of content being deployed (e.g. +\code{"plot"}, \code{"document"}, or \code{"application"}).} + +\item{account}{Account to deploy application to. This +parameter is only required for the initial deployment of an application +when there are multiple accounts configured on the system (see +\link{accounts}).} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} + +\item{upload}{If \code{TRUE} (the default) then the application is uploaded +from the local system prior to deployment. If \code{FALSE} then it is +re-deployed using the last version that was uploaded.} + +\item{launch.browser}{If true, the system's default web browser will be +launched automatically after the app is started. Defaults to \code{TRUE} in +interactive sessions only.} + +\item{quiet}{Request that no status information be printed to the console +during the deployment.} + +\item{lint}{Lint the project before initiating deployment, to identify +potentially problematic code?} + +\item{metadata}{Additional metadata fields to save with the deployment +record. These fields will be returned on subsequent calls to +\code{\link{deployments}}.} +} +\description{ +Deploy a \link[shiny:shiny-package]{shiny} application, an R Markdown +document, or HTML content to a server. +} +\examples{ +\dontrun{ + +# deploy the application in the current working dir +deployApp() + +# deploy an application in another directory +deployApp("~/projects/shiny/app1") + +# deploy using an alternative application name +deployApp("~/projects/shiny/app1", appName = "myapp") + +# deploy specifying an explicit account name, then +# redeploy with no arguments (will automatically use +# the previously specified account) +deployApp(account = "jsmith") +deployApp() + +# deploy but don't launch a browser when completed +deployApp(launch.browser = FALSE) +} +} +\seealso{ +\code{\link{applications}}, \code{\link{terminateApp}}, and + \code{\link{restartApp}} +} + diff --git a/man/deployDoc.Rd b/man/deployDoc.Rd new file mode 100644 index 0000000..b56dd28 --- /dev/null +++ b/man/deployDoc.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deployDoc.R +\name{deployDoc} +\alias{deployDoc} +\title{Deploy a Document} +\usage{ +deployDoc(doc, ...) +} +\arguments{ +\item{doc}{Path to the document to deploy.} + +\item{...}{Additional arguments to \code{\link{deployApp}}. Do not supply +\code{appDir}, \code{appFiles}, or \code{appPrimaryDoc}; +these three parameters are automatically generated by \code{deployDoc} from +the document.} +} +\description{ +Deploys an application consisting of a single R Markdown document or other +single file (such as an HTML or PDF document). +} +\details{ +When deploying an R Markdown document, any files which are + required to render and display the file must be deployed. + + This method discovers these additional files using + \code{\link[rmarkdown:find_external_resources]{find_external_resources}} + from \pkg{rmarkdown}. + + If you find that the document is missing dependencies, either specify the + dependencies explicitly in the document (the documentation for + \code{\link[rmarkdown:find_external_resources]{find_external_resources}} + explains how to do this), or call \code{\link{deployApp}} directly and + specify your own file list in the \code{appFiles} parameter. +} + diff --git a/man/deployments.Rd b/man/deployments.Rd new file mode 100644 index 0000000..f2e9b92 --- /dev/null +++ b/man/deployments.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deployments.R +\name{deployments} +\alias{deployments} +\title{List Application Deployments} +\usage{ +deployments(appPath, nameFilter = NULL, accountFilter = NULL, + serverFilter = NULL, excludeOrphaned = TRUE) +} +\arguments{ +\item{appPath}{The path to the content that was deployed, either a directory +or an individual document.} + +\item{nameFilter}{Return only deployments matching the given name (optional)} + +\item{accountFilter}{Return only deployments matching the given account +(optional)} + +\item{serverFilter}{Return only deployments matching the given server +(optional)} + +\item{excludeOrphaned}{If \code{TRUE} (the default), return only deployments +made by a currently registered account. Deployments made from accounts that +are no longer registered (via e.g.\code{\link{removeAccount}}) will not be +returned.} +} +\value{ +Returns a data frame with at least following columns: +\tabular{ll}{ +\code{name} \tab Name of deployed application\cr +\code{account} \tab Account owning deployed application\cr +\code{bundleId} \tab Identifier of deployed application's bundle\cr +\code{url} \tab URL of deployed application\cr +\code{when} \tab When the application was deployed (in seconds since the + epoch)\cr +} + +If additional metadata has been saved with the deployment record using the +\code{metadata} argument to \code{\link{deployApp}}, the frame will include +additional columns. +} +\description{ +List deployment records for a given application. +} +\examples{ +\dontrun{ + +# Return all deployments of the ~/r/myapp directory made with the 'abc' +# account +deployments("~/r/myapp", accountFilter="abc") +} +} +\seealso{ +\code{\link{applications}} to get a list of deployments from the + server, and \code{\link{deployApp}} to create a new deployment. +} + diff --git a/man/lint.Rd b/man/lint.Rd new file mode 100644 index 0000000..4c30cf4 --- /dev/null +++ b/man/lint.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lint-framework.R +\name{lint} +\alias{lint} +\title{Lint a Project} +\usage{ +lint(project, files = NULL, appPrimaryDoc = NULL) +} +\arguments{ +\item{project}{Path to a project directory.} + +\item{files}{Specific files to lint. Can be NULL, in which case all +the files in the directory will be linted.} + +\item{appPrimaryDoc}{The primary file in the project directory. Can be NULL, +in which case it's inferred (if possible) from the directory contents.} +} +\description{ +Takes the set of active linters (see \code{\link{addLinter}}), and applies +them to all files within a project. +} + diff --git a/man/linter.Rd b/man/linter.Rd new file mode 100644 index 0000000..9542d70 --- /dev/null +++ b/man/linter.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lint-framework.R +\name{linter} +\alias{linter} +\title{Create a Linter} +\usage{ +linter(apply, takes, message, suggestion) +} +\arguments{ +\item{apply}{Function that, given the content of a file, returns the indices +at which problems were found.} + +\item{takes}{Function that, given a set of paths, returns the subset of +paths that this linter uses.} + +\item{message}{Function that, given content and lines, returns an +informative message for the user. Typically generated with +\code{\link{makeLinterMessage}}.} + +\item{suggestion}{String giving a prescribed fix for the linted problem.} +} +\description{ +Generate a linter, which can identify errors or problematic regions in a +project. +} +\examples{ +addLinter("no.capitals", linter( + + ## Identify lines containing capital letters -- either by name or by index + apply = function(content, ...) { + grep("[A-Z]", content) + }, + + ## Only use this linter on R files (paths ending with .r or .R) + takes = function(paths) { + grep("[rR]$", paths) + }, + + # Use the default message constructor + message = function(content, lines, ...) { + makeLinterMessage("Capital letters found on the following lines", content, lines) + }, + + # Give a suggested prescription + suggest = "Do not use capital letters in these documents." +)) +} + diff --git a/man/makeLinterMessage.Rd b/man/makeLinterMessage.Rd new file mode 100644 index 0000000..eaa6435 --- /dev/null +++ b/man/makeLinterMessage.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/lint-utils.R +\name{makeLinterMessage} +\alias{makeLinterMessage} +\title{Construct a Linter Message} +\usage{ +makeLinterMessage(header, content, lines) +} +\arguments{ +\item{header}{A header message describing the linter.} + +\item{content}{The content of the file that was linted.} + +\item{lines}{The line numbers from \code{content} that contain lint.} +} +\description{ +Pretty-prints a linter message. Primarily used as a helper +for constructing linter messages with \code{\link{linter}}. +} + diff --git a/man/options.Rd b/man/options.Rd new file mode 100644 index 0000000..5ad488a --- /dev/null +++ b/man/options.Rd @@ -0,0 +1,49 @@ +\name{rsconnectOptions} +\alias{rsconnectOptions} + +\title{Package Options} + +\description{ +The \pkg{rsconnect} package supports several options that control the method used for http communications, the printing of diagnostic information for http requests, and the launching of an external browser after deployment. +} + +\details{ +Supported global options include: +\describe{ + \item{\code{rsconnect.http}}{Http implementation used for connections to the back-end service: + \tabular{ll}{ + \code{rcurl} \tab Secure https using the \code{RCurl} package\cr + \code{curl} \tab Secure https using the curl system utility \cr + \code{internal} \tab Insecure http using raw sockets\cr + } + If no option is specified then \code{rcurl} is used by default. + } + \item{\code{rsconnect.http.trace}}{When \code{TRUE}, trace http calls (prints the method, path, and total milliseconds for each http request)} + \item{\code{rsconnect.http.trace.json}}{When \code{TRUE}, trace JSON content (shows JSON payloads sent to and received from the server))} + \item{\code{rsconnect.http.verbose}}{When \code{TRUE}, print verbose output for http connections (useful only for debugging SSL certificate or http connection problems)} + \item{\code{rsconnect.launch.browser}}{When \code{TRUE}, automatically launch a browser to view applications after they are deployed} + \item{\code{rsconnect.locale.cache}}{When \code{FALSE}, disable the detected locale cache (Windows only). } + \item{\code{rsconnect.locale}}{Override the detected locale. } +} +} + +\examples{ +\dontrun{ + +# use curl for http connections +options(rsconnect.http = "curl") + +# trace http requests +options(rsconnect.http.trace = TRUE) + +# print verbose output for http requests +options(rsconnect.http.verbose = TRUE) + +# print JSON content +options(rsconnect.http.trace.json = TRUE) + +# don't automatically launch a browser after deployment +options(rsconnect.launch.browser = FALSE) +} +} + diff --git a/man/packages.Rd b/man/packages.Rd new file mode 100644 index 0000000..5e588a4 --- /dev/null +++ b/man/packages.Rd @@ -0,0 +1,35 @@ +\name{rsconnectPackages} +\alias{rsconnectPackages} + +\title{Using Packages with rsconnect} + +\description{ +Deployed applications can depend on any package available on CRAN as well as any package hosted in a public \href{https://www.github.com}{GitHub} repository. + +When an application is deployed it's source code is scanned for dependencies using the \code{\link{appDependencies}} function. The list of dependencies is sent to the server along with the application source code and these dependencies are then installed alongside the application. + +Note that the \code{Suggests} dependencies of packages are not automatically included in the list of dependent packages. See the \emph{Note} section of the documentation of the \link{appDependencies} function for details on how to force packages to be included in the dependency list. +} + +\section{CRAN Packages}{ +When sastisfying CRAN package dependencies, the server will build the exact versions of packages that were installed on the system from which the application is deployed. + +If a locally installed package was not obtained from CRAN (e.g. was installed from R-Forge) and as a result doesn't have a version that matches a version previously published to CRAN then an error will occur. It's therefore important that you run against packages installed directly from CRAN in your local configuration. +} + +\section{GitHub Packages}{ +It's also possible to depend on packages hosted in public GitHub repositories, so long as they are installed via the \link[devtools:install_github]{install_github} function from the \pkg{devtools} package. + +This works because \code{install_github} records the exact Github commit that was installed locally, making it possible to download and install the same source code on the deployment server. + +Note that in order for this to work correctly you need to install the very latest version of \code{devtools} from Github. You can do this as follows: + +\preformatted{ +library(devtools) +install_github("devtools", "hadley") +} +} + +\seealso{ +\code{\link{appDependencies}} +} diff --git a/man/proxies.Rd b/man/proxies.Rd new file mode 100644 index 0000000..cdbc7e5 --- /dev/null +++ b/man/proxies.Rd @@ -0,0 +1,60 @@ +\name{rsconnectProxies} +\alias{rsconnectProxies} + +\title{HTTP Proxy Configuration} + +\description{ +If your system is behind an HTTP proxy then additional configuration may be required to connect to the ShinyApp service. The required configuration varies depending on what type of HTTP connection you are making to the server. + +The default HTTP connection type is \code{rcurl} however addition connection types \code{curl} and \code{internal} are also supported. The HTTP connection type is configured using the \code{\link[rsconnect:rsconnectOptions]{rsconnect.http}} global option. +} + +\section{HTTP Proxy Environment Variable}{ + +The most straightforward way to specify a proxy for \code{rcurl} and \code{curl} connections is to set the \env{http_proxy} environment variable. For example, you could add the following code to your \code{.Rprofile}: + +\preformatted{ +Sys.setenv(http_proxy = "http://proxy.example.com") +} + +Proxy settings can include a host-name, port, and username/password if necessary. The following are all valid values for the \code{http_proxy} environment variable: + +\preformatted{ +http://proxy.example.com/ +http://proxy.example.com:1080/ +http://username:password@proxy.example.com:1080/ +} + +} + +\section{Setting RCurl Proxy Options}{ + +The default HTTP connection type is \code{rcurl}. If you need more configurability than affored by the \code{http_proxy} environment variable you can specify RCurl proxy options explicity using \code{RCurlOptions}. For example, you could add the following code to your \code{.Rprofile}: + +\preformatted{ +options(RCurlOptions = list(proxy = "http://proxy.example.com") +} + +You can set any underling curl option using this mechanism. To do this you translate curl options to lowercase and remove the \code{CURL_} prefix (for example, \code{CURLOPT_PROXYPORT} becomes \code{proxyport}). + +A list of available curl options can be found here: \href{http://curl.haxx.se/libcurl/c/curl_easy_setopt.html}{curl http proxy options}. + +} + +\section{Using Internet Explorer Proxy Settings}{ + +If you are running on Windows and have difficulty configuring proxy settings for \code{rcurl} or \code{curl} connections, it's possible to re-use your Internet Explorer proxy settings for connections to the server. To do this you set the http connection type to \code{internal} as follows: + +\preformatted{ +options(rsconnect.http = "internal") +} + +There are two things to keep in mind when using \code{internal} connection types: + +\enumerate{ + \item The \code{internal} connection type uses an insecure (non-encrypted) http connection to the server. If you require an encrypted https connection it's recommended that you use an \code{rcurl} or \code{curl} connection. + \item To take advantage of Internet Explorer proxy settings you must be using the \code{internet2} routines via the \code{setInternet2} function (this is the default within RStudio on Windows). You can check whether \code{internet2} is enabled by executing the following code: \code{ setInternet2(use = NA)} +} + +} + diff --git a/man/removeAuthorizedUser.Rd b/man/removeAuthorizedUser.Rd new file mode 100644 index 0000000..4e625c4 --- /dev/null +++ b/man/removeAuthorizedUser.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{removeAuthorizedUser} +\alias{removeAuthorizedUser} +\title{Remove authorized user from an application} +\usage{ +removeAuthorizedUser(user, appDir = getwd(), appName = NULL, + account = NULL, server = NULL) +} +\arguments{ +\item{user}{The user to remove. Can be id or email address.} + +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application.} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} +} +\description{ +Remove authorized user from an application +} +\note{ +This function works only for ShinyApps servers. +} +\seealso{ +\code{\link{addAuthorizedUser}} and \code{\link{showUsers}} +} + diff --git a/man/restartApp.Rd b/man/restartApp.Rd new file mode 100644 index 0000000..3afed25 --- /dev/null +++ b/man/restartApp.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/restartApp.R +\name{restartApp} +\alias{restartApp} +\title{Restart an Application} +\usage{ +restartApp(appName, account = NULL, server = NULL, quiet = FALSE) +} +\arguments{ +\item{appName}{Name of application to restart} + +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers (see \code{\link{servers}})} + +\item{quiet}{Request that no status information be printed to the console +during the operation.} +} +\description{ +Restart an application currently running on a remote server. +} +\examples{ +\dontrun{ + +# restart an application +restartApp("myapp") +} +} +\seealso{ +\code{\link{applications}}, \code{\link{deployApp}}, and + \code{\link{terminateApp}} +} + diff --git a/man/rpubsUpload.Rd b/man/rpubsUpload.Rd new file mode 100644 index 0000000..797baef --- /dev/null +++ b/man/rpubsUpload.Rd @@ -0,0 +1,55 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/rpubs.R +\name{rpubsUpload} +\alias{rpubsUpload} +\title{Upload a file to RPubs} +\usage{ +rpubsUpload(title, contentFile, originalDoc, id = NULL, properties = list()) +} +\arguments{ +\item{title}{The title of the document.} + +\item{contentFile}{The path to the content file to upload.} + +\item{originalDoc}{The document that was rendered to produce the +\code{contentFile}. May be \code{NULL} if the document is not known.} + +\item{id}{If this upload is an update of an existing document then the id +parameter should specify the document id to update. Note that the id is +provided as an element of the list returned by successful calls to +\code{rpubsUpload}.} + +\item{properties}{A named list containing additional document properties +(RPubs doesn't currently expect any additional properties, this parameter +is reserved for future use).} +} +\value{ +A named list. If the upload was successful then the list contains a + \code{id} element that can be used to subsequently update the document as + well as a \code{continueUrl} element that provides a URL that a browser + should be opened to in order to complete publishing of the document. If the + upload fails then the list contains an \code{error} element which contains + an explanation of the error that occurred. +} +\description{ +This function publishes a file to rpubs.com. If the upload succeeds a +list that includes an \code{id} and \code{continueUrl} is returned. A browser +should be opened to the \code{continueUrl} to complete publishing of the +document. If an error occurs then a diagnostic message is returned in the +\code{error} element of the list. +} +\examples{ +\dontrun{ +# upload a document +result <- rpubsUpload("My document title", "Document.html") +if (!is.null(result$continueUrl)) + browseURL(result$continueUrl) +else + stop(result$error) + +# update the same document with a new title +updateResult <- rpubsUpload("My updated title", "Document.html", + id = result$id) +} +} + diff --git a/man/rsconnect-package.Rd b/man/rsconnect-package.Rd new file mode 100644 index 0000000..3d5426f --- /dev/null +++ b/man/rsconnect-package.Rd @@ -0,0 +1,65 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/rsconnect-package.R +\docType{package} +\name{rsconnect-package} +\alias{rsconnect} +\alias{rsconnect-package} +\title{rsconnect} +\description{ +Deployment Interface for R Markdown Documents and Shiny Applications +} +\details{ +The rsconnect package provides a programmatic deployment +interface for RPubs, shinyapps.io, and RStudio Connect. Supported contents +types include R Markdown documents, Shiny applications, plots, and static +web content. +} +\section{Managing Applications}{ + + +Deploy and manage applications with the following functions: + +\tabular{ll}{ + + \code{\link{deployApp}:} \tab + Deploy a Shiny application to a server.\cr\cr + + \code{\link{configureApp}:} \tab + Configure an application currently running on a server.\cr\cr + + \code{\link{restartApp}:} \tab + Restart an application currently running on a server.\cr\cr + + \code{\link{terminateApp}:} \tab + Terminate an application currently running on a server.\cr\cr + + \code{\link{deployments}:} \tab + List deployment records for a given application directory. + +} + +More information on application management is available in the +\code{\link{applications}} help page. +} + +\section{Managing Accounts and Users}{ + + +Manage accounts on the local system. +\tabular{ll}{ + + \code{\link{setAccountInfo}:} \tab + Register an account.\cr\cr + + \code{\link{removeAccount}:} \tab + Remove an account.\cr\cr + + \code{\link{accountInfo}:} \tab + View information for a given account.\cr\cr +} + +More information on account management is available in the +\code{\link{accounts}} help page. +} +\keyword{package} + diff --git a/man/servers.Rd b/man/servers.Rd new file mode 100644 index 0000000..b381460 --- /dev/null +++ b/man/servers.Rd @@ -0,0 +1,68 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/servers.R +\name{servers} +\alias{addConnectServer} +\alias{addServer} +\alias{discoverServers} +\alias{removeServer} +\alias{serverInfo} +\alias{servers} +\title{Server Management Functions} +\usage{ +servers(local = FALSE) + +discoverServers(quiet = FALSE) + +addConnectServer(url, name = NULL, quiet = FALSE) + +addServer(url, name = NULL, quiet = FALSE) + +removeServer(name) + +serverInfo(name) +} +\arguments{ +\item{local}{Return only local servers (i.e. not \code{shinyapps.io})} + +\item{quiet}{Suppress output and prompts where possible.} + +\item{url}{Server's URL. Should look like \code{http://servername/} or +\code{http://servername:port/}.} + +\item{name}{Optional nickname for the server. If none is given, the nickname +is inferred from the server's hostname.} +} +\value{ +\code{servers} returns a data frame with registered server names and URLs. +\code{serverInfo} returns a list with details for a particular server. +} +\description{ +Functions to manage the list of known servers to which +\pkg{rsconnect} can deploy and manage applications. +} +\details{ +Register a server with \code{addServer} or \code{discoverServers} (the latter +is useful only if your administrator has configured server autodiscovery). +Once a server is registered, you can connect to an account on the server +using \code{\link{connectUser}}. + +The \code{servers} and \code{serverInfo} functions are provided for viewing +previously registered servers. + +There is always at least one server registered (the \code{shinyapps.io} +server) +} +\examples{ +\dontrun{ + +# register a local server +addServer("http://myrsconnect/", "myserver") + +# list servers +servers(local = TRUE) + +# connect to an account on the server +connectUser(server = "myserver") +} +} + diff --git a/man/setAccountInfo.Rd b/man/setAccountInfo.Rd new file mode 100644 index 0000000..f8f1bad --- /dev/null +++ b/man/setAccountInfo.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/accounts.R +\name{setAccountInfo} +\alias{setAccountInfo} +\title{Set ShinyApps Account Info} +\usage{ +setAccountInfo(name, token, secret) +} +\arguments{ +\item{name}{Name of account to save or remove} + +\item{token}{User token for the account} + +\item{secret}{User secret for the account} +} +\description{ +Configure a ShinyApps account for publishing from this system. +} +\examples{ +\dontrun{ + +# register an account +setAccountInfo("user", "token", "secret") + +# remove the same account +removeAccount("user") +} + +} + diff --git a/man/setProperty.Rd b/man/setProperty.Rd new file mode 100644 index 0000000..e9efca2 --- /dev/null +++ b/man/setProperty.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/configureApp.R +\name{setProperty} +\alias{setProperty} +\title{Set Application property} +\usage{ +setProperty(propertyName, propertyValue, appPath = getwd(), appName = NULL, + account = NULL, force = FALSE) +} +\arguments{ +\item{propertyName}{Name of property to set} + +\item{propertyValue}{Nalue to set property to} + +\item{appPath}{Directory or file that was deployed. Defaults to current +working directory.} + +\item{appName}{Name of application} + +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{force}{Forcibly set the property} +} +\description{ +Set a property on currently deployed ShinyApps application. +} +\note{ +This function only works for ShinyApps servers. +} +\examples{ +\dontrun{ + +# set instance size for an application +setProperty("application.instances.count", 1) + +# disable application package cache +setProperty("application.package.cache", FALSE) + +} +} + diff --git a/man/showInvited.Rd b/man/showInvited.Rd new file mode 100644 index 0000000..a0e945d --- /dev/null +++ b/man/showInvited.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{showInvited} +\alias{showInvited} +\title{List invited users for an application} +\usage{ +showInvited(appDir = getwd(), appName = NULL, account = NULL, + server = NULL) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application.} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} +} +\description{ +List invited users for an application +} +\note{ +This function works only for ShinyApps servers. +} +\seealso{ +\code{\link{addAuthorizedUser}} and \code{\link{showUsers}} +} + diff --git a/man/showLogs.Rd b/man/showLogs.Rd new file mode 100644 index 0000000..7044fb7 --- /dev/null +++ b/man/showLogs.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/applications.R +\name{showLogs} +\alias{showLogs} +\title{Show Application Logs} +\usage{ +showLogs(appPath = getwd(), appFile = NULL, appName = NULL, + account = NULL, entries = 50, streaming = FALSE) +} +\arguments{ +\item{appPath}{The path to the directory or file that was deployed.} + +\item{appFile}{The path to the R source file that contains the application +(for single file applications).} + +\item{appName}{The name of the application to show logs for. May be omitted +if only one application deployment was made from \code{appPath}.} + +\item{account}{The account under which the application was deployed. May be +omitted if only one account is registered on the system.} + +\item{entries}{The number of log entries to show. Defaults to 50 entries.} + +\item{streaming}{Whether to stream the logs. If \code{TRUE}, then the +function does not return; instead, log entries are written to the console +as they are made, until R is interrupted. Defaults to \code{FALSE}.} +} +\description{ +Show the logs for a deployed ShinyApps application. +} +\note{ +This function works only for ShinyApps servers. +} + diff --git a/man/showMetrics.Rd b/man/showMetrics.Rd new file mode 100644 index 0000000..091cccc --- /dev/null +++ b/man/showMetrics.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/usage.R +\name{showMetrics} +\alias{showMetrics} +\title{Show Application Metrics} +\usage{ +showMetrics(metricSeries, metricNames, appDir = getwd(), appName = NULL, + account = NULL, server = NULL, from = NULL, until = NULL, + interval = NULL) +} +\arguments{ +\item{metricSeries}{Metric series to query e.g. "container.cpu"} + +\item{metricNames}{Metric names in the series to query e.g. c("cpu.user", "cpu.system")} + +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} + +\item{from}{Date range starting timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{until}{Date range ending timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{interval}{Summarization interval. Data points at intervals less then this +will be grouped. (Number of seconds or relative time delta e.g. "1h").} +} +\description{ +Show application metrics of a currently deployed application +} +\note{ +This function only works for ShinyApps servers. +} + diff --git a/man/showProperties.Rd b/man/showProperties.Rd new file mode 100644 index 0000000..cadd331 --- /dev/null +++ b/man/showProperties.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/configureApp.R +\name{showProperties} +\alias{showProperties} +\title{Show Application property} +\usage{ +showProperties(appPath = getwd(), appName = NULL, account = NULL) +} +\arguments{ +\item{appPath}{Directory or file that was deployed. Defaults to current +working directory.} + +\item{appName}{Name of application} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} +} +\description{ +Show propreties of an application deployed to ShinyApps. +} +\note{ +This function works only for ShinyApps servers. +} + diff --git a/man/showUsage.Rd b/man/showUsage.Rd new file mode 100644 index 0000000..7c1ac48 --- /dev/null +++ b/man/showUsage.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/usage.R +\name{showUsage} +\alias{showUsage} +\title{Show Application Usage} +\usage{ +showUsage(appDir = getwd(), appName = NULL, account = NULL, + server = NULL, usageType = "hours", from = NULL, until = NULL, + interval = NULL) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} + +\item{usageType}{Use metric to retreive (for example: "hours")} + +\item{from}{Date range starting timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{until}{Date range ending timestamp (Unix timestamp or relative time +delta such as "2d" or "3w").} + +\item{interval}{Summarization interval. Data points at intervals less then this +will be grouped. (Number of seconds or relative time delta e.g. "1h").} +} +\description{ +Show application usage of a currently deployed application +} +\note{ +This function only works for ShinyApps servers. +} + diff --git a/man/showUsers.Rd b/man/showUsers.Rd new file mode 100644 index 0000000..88fdc19 --- /dev/null +++ b/man/showUsers.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/auth.R +\name{showUsers} +\alias{showUsers} +\title{List authorized users for an application} +\usage{ +showUsers(appDir = getwd(), appName = NULL, account = NULL, + server = NULL) +} +\arguments{ +\item{appDir}{Directory containing application. Defaults to +current working directory.} + +\item{appName}{Name of application.} + +\item{account}{Account name. If a single account is registered on the +system then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers.} +} +\description{ +List authorized users for an application +} +\note{ +This function works only for ShinyApps servers. +} +\seealso{ +\code{\link{addAuthorizedUser}} and \code{\link{showInvited}} +} + diff --git a/man/taskLog.Rd b/man/taskLog.Rd new file mode 100644 index 0000000..8d8fc40 --- /dev/null +++ b/man/taskLog.Rd @@ -0,0 +1,37 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tasks.R +\name{taskLog} +\alias{taskLog} +\title{Show task log} +\usage{ +taskLog(taskId, account = NULL, server = NULL, output = NULL) +} +\arguments{ +\item{taskId}{Task Id} + +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers (see \code{\link{servers}})} + +\item{output}{Where to write output. Valid values are \code{NULL} or \code{stderr}} +} +\description{ +Writes the task log for the given task +} +\examples{ +\dontrun{ + +# write task log to stdout +taskLog(12345) + +# write task log to stderr +taskLog(12345, output="stderr") + +} +} +\seealso{ +\code{\link{tasks}} +} + diff --git a/man/tasks.Rd b/man/tasks.Rd new file mode 100644 index 0000000..9b81d1d --- /dev/null +++ b/man/tasks.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/tasks.R +\name{tasks} +\alias{tasks} +\title{List Tasks} +\usage{ +tasks(account = NULL, server = NULL) +} +\arguments{ +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers (see \code{\link{servers}})} +} +\value{ +Returns a data frame with the following columns: +\tabular{ll}{ +\code{id} \tab Task id \cr +\code{action} \tab Task action\cr +\code{status} \tab Current task status\cr +\code{created_time} \tab Task creation time\cr +\code{finished_time} \tab Task finished time\cr +} +} +\description{ +List Tasks +} +\examples{ +\dontrun{ + +# list tasks for the default account +tasks() + +} +} +\seealso{ +\code{\link{taskLog}} +} + diff --git a/man/terminateApp.Rd b/man/terminateApp.Rd new file mode 100644 index 0000000..c44ea5d --- /dev/null +++ b/man/terminateApp.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/terminateApp.R +\name{terminateApp} +\alias{terminateApp} +\title{Terminate an Application} +\usage{ +terminateApp(appName, account = NULL, server = NULL, quiet = FALSE) +} +\arguments{ +\item{appName}{Name of application to terminate} + +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{server}{Server name. Required only if you use the same account name on +multiple servers (see \code{\link{servers}})} + +\item{quiet}{Request that no status information be printed to the console +during the termination.} +} +\description{ +Terminate an application currently running on a remote server. +} +\examples{ +\dontrun{ + +# terminate an application +terminateApp("myapp") +} +} +\seealso{ +\code{\link{applications}}, \code{\link{deployApp}}, and + \code{\link{restartApp}} +} + diff --git a/man/unsetProperty.Rd b/man/unsetProperty.Rd new file mode 100644 index 0000000..0132081 --- /dev/null +++ b/man/unsetProperty.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/configureApp.R +\name{unsetProperty} +\alias{unsetProperty} +\title{Unset Application property} +\usage{ +unsetProperty(propertyName, appPath = getwd(), appName = NULL, + account = NULL, force = FALSE) +} +\arguments{ +\item{propertyName}{Name of property to unset} + +\item{appPath}{Directory or file that was deployed. Defaults to current +working directory.} + +\item{appName}{Name of application} + +\item{account}{Account name. If a single account is registered on the system +then this parameter can be omitted.} + +\item{force}{Forcibly unset the property} +} +\description{ +Unset a property on currently deployed ShinyApps application (restoring to +its default value) +} +\note{ +This function only works for ShinyApps servers. +} +\examples{ +\dontrun{ + +# unset application package cache property to revert to default +unsetProperty("application.package.cache") + +} +} + diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..2d8ad36 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(rsconnect) + +test_check("rsconnect") diff --git a/tests/testthat/project-MASS/MASS.R b/tests/testthat/project-MASS/MASS.R new file mode 100644 index 0000000..0997254 --- /dev/null +++ b/tests/testthat/project-MASS/MASS.R @@ -0,0 +1 @@ +library(MASS) diff --git a/tests/testthat/shiny-app-in-subdir/my-app/server.R b/tests/testthat/shiny-app-in-subdir/my-app/server.R new file mode 100644 index 0000000..e69de29 diff --git a/tests/testthat/shiny-app-in-subdir/my-app/ui.r b/tests/testthat/shiny-app-in-subdir/my-app/ui.r new file mode 100644 index 0000000..e69de29 diff --git a/tests/testthat/shiny-rmds/non-shiny-rmd.Rmd b/tests/testthat/shiny-rmds/non-shiny-rmd.Rmd new file mode 100644 index 0000000..f9476ad --- /dev/null +++ b/tests/testthat/shiny-rmds/non-shiny-rmd.Rmd @@ -0,0 +1,7 @@ +--- +title: Not a Shiny R Markdown Document +output: html_document +--- + + + diff --git a/tests/testthat/shiny-rmds/shiny-rmd-dashes.Rmd b/tests/testthat/shiny-rmds/shiny-rmd-dashes.Rmd new file mode 100644 index 0000000..6a399b8 --- /dev/null +++ b/tests/testthat/shiny-rmds/shiny-rmd-dashes.Rmd @@ -0,0 +1,7 @@ +--- +title: Shiny R Markdown with Dashes +output: html_document +runtime: shiny +--- + + diff --git a/tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd b/tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd new file mode 100644 index 0000000..77dde71 --- /dev/null +++ b/tests/testthat/shiny-rmds/shiny-rmd-dots.Rmd @@ -0,0 +1,9 @@ +--- +title: Shiny R Markdown with Dots +output: html_document +runtime: shiny +... + +Hello, world! + + diff --git a/tests/testthat/shinyapp-appR/app.R b/tests/testthat/shinyapp-appR/app.R new file mode 100644 index 0000000..91b7294 --- /dev/null +++ b/tests/testthat/shinyapp-appR/app.R @@ -0,0 +1,12 @@ +server <- function(input, output) { + output$distPlot <- renderPlot({ + hist(rnorm(input$obs), col = 'darkgray', border = 'white') + }) +} +ui <- fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("obs", "Number of observations:", min = 10, max = 500, + value = 100)), + mainPanel(plotOutput("distPlot")))) +shinyApp(ui = ui, server = server) diff --git a/tests/testthat/shinyapp-simple/server.R b/tests/testthat/shinyapp-simple/server.R new file mode 100644 index 0000000..7631acb --- /dev/null +++ b/tests/testthat/shinyapp-simple/server.R @@ -0,0 +1,8 @@ +library(shiny) +shinyServer(function(input, output) { + output$distPlot <- renderPlot({ + dist <- rnorm(input$obs) + hist(dist) + }) + output$obs <- renderText({paste(input$obs, "\n", input$obs)}) +}) diff --git a/tests/testthat/shinyapp-simple/ui.R b/tests/testthat/shinyapp-simple/ui.R new file mode 100644 index 0000000..1337476 --- /dev/null +++ b/tests/testthat/shinyapp-simple/ui.R @@ -0,0 +1,11 @@ +library(shiny) +shinyUI(pageWithSidebar( + headerPanel("Hello, Shiny!"), + sidebarPanel( + sliderInput("obs", "Number of observations:", + min = 1, + max = 1000, + value = 500)), + mainPanel( + plotOutput("distPlot"))) +) diff --git a/tests/testthat/shinyapp-singleR/single.R b/tests/testthat/shinyapp-singleR/single.R new file mode 100644 index 0000000..91b7294 --- /dev/null +++ b/tests/testthat/shinyapp-singleR/single.R @@ -0,0 +1,12 @@ +server <- function(input, output) { + output$distPlot <- renderPlot({ + hist(rnorm(input$obs), col = 'darkgray', border = 'white') + }) +} +ui <- fluidPage( + sidebarLayout( + sidebarPanel( + sliderInput("obs", "Number of observations:", min = 10, max = 500, + value = 100)), + mainPanel(plotOutput("distPlot")))) +shinyApp(ui = ui, server = server) diff --git a/tests/testthat/shinyapp-with-absolute-paths/College.txt b/tests/testthat/shinyapp-with-absolute-paths/College.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/testthat/shinyapp-with-absolute-paths/ShinyDocument.Rmd b/tests/testthat/shinyapp-with-absolute-paths/ShinyDocument.Rmd new file mode 100644 index 0000000..bc7c688 --- /dev/null +++ b/tests/testthat/shinyapp-with-absolute-paths/ShinyDocument.Rmd @@ -0,0 +1,55 @@ +--- +title: "Shiny Document" +author: "Phoenix Wright" +date: "July 16, 2014" +output: html_document +runtime: shiny +--- + +This R Markdown document is made interactive using Shiny. Unlike the more traditional workflow of creating static reports, you can now create documents that allow your readers to change the assumptions underlying your analysis and see the results immediately. + +To learn more, see [Interative Documents](http://rmarkdown.rstudio.com/authoring_shiny.html). + +## Inputs and Outputs + +You can embed Shiny inputs and outputs in your document. Outputs are automatically updated whenever inputs change. This demonstrates how a standard R plot can be made interactive by wrapping it in the Shiny `renderPlot` function. The `selectInput` and `sliderInput` functions create the input widgets used to drive the plot. + +```{r, echo=FALSE} +inputPanel( + selectInput("n_breaks", label = "Number of bins:", + choices = c(10, 20, 35, 50), selected = 20), + + sliderInput("bw_adjust", label = "Bandwidth adjustment:", + min = 0.2, max = 2, value = 1, step = 0.2) +) + +renderPlot({ + hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks), + xlab = "Duration (minutes)", main = "Geyser eruption duration") + + dens <- density(faithful$eruptions, adjust = input$bw_adjust) + lines(dens, col = "blue") +}) +``` + +## Embedded Application + +It's also possible to embed an entire Shiny application within an R Markdown document using the `shinyAppDir` function. This example embeds a Shiny application located in another directory: + +```{r, echo=FALSE} +shinyAppDir( + file.path("~/home/file.txt"), + options=list( + width="100%", height=550 + ) +) +``` + +Note the use of the `height` parameter to determine how much vertical space the embedded application should occupy. + +You can also use the `shinyApp` function to define an application inline rather then in an external directory. + +In all of R code chunks above the `echo = FALSE` attribute is used. This is to prevent the R code within the chunk from rendering in the document alongside the Shiny components. + + + diff --git a/tests/testthat/shinyapp-with-absolute-paths/ShinyPresentation.Rmd b/tests/testthat/shinyapp-with-absolute-paths/ShinyPresentation.Rmd new file mode 100644 index 0000000..31fa6f2 --- /dev/null +++ b/tests/testthat/shinyapp-with-absolute-paths/ShinyPresentation.Rmd @@ -0,0 +1,50 @@ +--- +title: "Shiny Presentation" +author: "Miles Edgeworth" +date: "July 16, 2014" +output: ioslides_presentation +runtime: shiny +--- + +## Shiny Presentation + +This R Markdown presentation is made interactive using Shiny. The viewers of the presentation can change the assumptions underlying what's presented and see the results immediately. + +To learn more, see [Interative Documents](http://rmarkdown.rstudio.com/authoring_shiny.html). + +Here's some internal help: [Helpful Link](/Users/MrBurns/) +And another: [Favourite Goats](../../goats.txt) + +## Slide with Interactive Plot + +```{r, echo=FALSE} +inputPanel( + selectInput("n_breaks", label = "Number of bins:", + choices = c(10, 20, 35, 50), selected = 20), + + sliderInput("bw_adjust", label = "Bandwidth adjustment:", + min = 0.2, max = 2, value = 1, step = 0.2) +) + +renderPlot({ + hist(faithful$eruptions, probability = TRUE, breaks = as.numeric(input$n_breaks), + xlab = "Duration (minutes)", main = "Geyser eruption duration") + + dens <- density(faithful$eruptions, adjust = input$bw_adjust) + lines(dens, col = "blue") +}) +``` + +## Slide with Bullets + +- Bullet 1 +- Bullet 2 +- Bullet 3 + +## Slide with R Code and Output + +```{r} +summary(cars) +``` + + diff --git a/tests/testthat/shinyapp-with-absolute-paths/server.R b/tests/testthat/shinyapp-with-absolute-paths/server.R new file mode 100644 index 0000000..a7a37a5 --- /dev/null +++ b/tests/testthat/shinyapp-with-absolute-paths/server.R @@ -0,0 +1,39 @@ + +# This is the server logic for a Shiny web application. +# You can find out more about building applications with Shiny here: +# +# http://shiny.rstudio.com +# + +library(shiny) + +shinyServer(function(input, output) { + + output$distPlot <- renderPlot({ + + # read a file on disk + otherFile <- read.table("~/.rsconnect-tests/local-file.txt") + anotherFile <- readLines('../../foo.bar') + serverFile <- "\\\\server\\path\\to\\file" + validWeblink <- "//www.google.com/" + + # generate bins based on input$bins from ui.R + x <- faithful[, 2] + bins <- seq(min(x), max(x), length.out = input$bins + 1) + + # don't warn on this line + text <- paste0("x:", round(new_row$x, 2), " y:", round(new_row$y, 2)) + + # draw the histogram with the specified number of bins + hist(x, breaks = bins, col = 'darkgray', border = 'white') + + ## read a csv file + file <- read.csv("college.txt") ## bad + file <- read.csv("College.txt") ## okay + + ## don't warn about absolute paths that could be URL query paths + file <- paste("/applcations") + + }) + +}) diff --git a/tests/testthat/shinyapp-with-absolute-paths/subdir/Genetics.txt b/tests/testthat/shinyapp-with-absolute-paths/subdir/Genetics.txt new file mode 100644 index 0000000..e69de29 diff --git a/tests/testthat/shinyapp-with-absolute-paths/ui.R b/tests/testthat/shinyapp-with-absolute-paths/ui.R new file mode 100644 index 0000000..9429b09 --- /dev/null +++ b/tests/testthat/shinyapp-with-absolute-paths/ui.R @@ -0,0 +1,33 @@ + +# This is the user-interface definition of a Shiny web application. +# You can find out more about building applications with Shiny here: +# +# http://shiny.rstudio.com +# + +library(shiny) + +shinyUI(fluidPage( + + # Application title + titlePanel("Old Faithful Geyser Data"), + + # Some image + img(src="/images/icon.png"), + + # Sidebar with a slider input for number of bins + sidebarLayout( + sidebarPanel( + sliderInput("bins", + "Number of bins:", + min = 1, + max = 50, + value = 30) + ), + + # Show a plot of the generated distribution + mainPanel( + plotOutput("distPlot") + ) + ) +)) diff --git a/tests/testthat/test-bundle.R b/tests/testthat/test-bundle.R new file mode 100644 index 0000000..a9a2505 --- /dev/null +++ b/tests/testthat/test-bundle.R @@ -0,0 +1,47 @@ +context("bundle") + +makeShinyBundleTempDir <- function(appName, appDir, appPrimaryDoc) { + tarfile <- bundleApp(appName, appDir, bundleFiles(appDir), appPrimaryDoc, + "application", NULL) + bundleTempDir <- tempfile() + utils::untar(tarfile, exdir = bundleTempDir) + unlink(tarfile) + bundleTempDir +} + +# avoid 'trying to use CRAN without setting a mirror' errors +repos <- getOption("repos") +options(repos = c(CRAN = "https://cran.rstudio.com")) +on.exit(options(repos = repos), add = TRUE) + +test_that("simple Shiny app bundle is runnable", { + skip_on_cran() + bundleTempDir <- makeShinyBundleTempDir("simple_shiny", "shinyapp-simple", + NULL) + on.exit(unlink(bundleTempDir, recursive = TRUE)) + expect_true(inherits(shiny::shinyAppDir(bundleTempDir), "shiny.appobj")) +}) + +test_that("app.R Shiny app bundle is runnable", { + skip_on_cran() + bundleTempDir <- makeShinyBundleTempDir("app_r_shiny", "shinyapp-appR", + NULL) + on.exit(unlink(bundleTempDir, recursive = TRUE)) + expect_true(inherits(shiny::shinyAppDir(bundleTempDir), "shiny.appobj")) +}) + +test_that("single-file Shiny app bundle is runnable", { + skip_on_cran() + bundleTempDir <- makeShinyBundleTempDir("app_r_shiny", "shinyapp-singleR", + "single.R") + on.exit(unlink(bundleTempDir, recursive = TRUE)) + expect_true(inherits(shiny::shinyAppDir(bundleTempDir), "shiny.appobj")) +}) + +test_that("recommended packages are snapshotted", { + skip_on_cran() + bundleTempDir <- makeShinyBundleTempDir("MASS", "project-MASS", "MASS.R") + lockfile <- file.path(bundleTempDir, "packrat/packrat.lock") + deps <- packrat:::readLockFilePackages(lockfile) + expect_true("MASS" %in% names(deps)) +}) diff --git a/tests/testthat/test-connect.R b/tests/testthat/test-connect.R new file mode 100644 index 0000000..ae81758 --- /dev/null +++ b/tests/testthat/test-connect.R @@ -0,0 +1,142 @@ +context("connect") + +# NOTE: These tests expect that you're already running connect; the tests +# will speak to that running connect process (if it can find it) +findConnect <- function() { + connect <- Sys.which("connect") + if (connect == "") { + possibleLocs <- c( + "~/git/connect/bin" + ) + for (loc in possibleLocs) { + if (file.exists(file.path(loc, "connect"))) { + return(normalizePath(file.path(loc, "connect"))) + } + } + stop("Couldn't find an appropriate 'connect' binary") + } +} + +isConnectRunning <- function() { + any(grepl("./bin/connect", system2("ps", "-a", stdout = TRUE), fixed = TRUE)) +} + +test_that("Users API", { + + skip_on_cran() + + if (!isConnectRunning()) { + cat("No running 'connect' instance detected -- tests skipped.") + return() + } + + ## rm db/*.db + server <- getDefaultServer(local = TRUE) + + connect <- connectClient(server$url, list()) + id <- createUniqueId(16) + + # add a user + record <- userRecord( + email = paste0("user", id ,"@gmail.com"), + username = paste0("user", id), + first_name = "User", + last_name = "Resu", + password = paste0("password", id) + ) + + response <- connect$addUser(record) + + # check a couple main fields + expect_equal( + response[c("email", "first_name", "last_name", "username")], + list( + email = record$email, + first_name = record$first_name, + last_name = record$last_name, + username = record$username + ) + ) + + # make sure we returned an empty password field (or no password field?) + expect_true(response$password %in% "" || is.null(response$password)) + + # generate a token + accountId <- response$id + token <- generateToken() + + tokenResponse <- connect$addToken(list(token = token$token, + public_key = token$public_key, + user_id = accountId)) + + Sys.sleep(1) + + # open the URL in the browser + utils::browseURL(tokenResponse$token_claim_url) + + # Sleep for a second so we can be sure that automatic auth happened + Sys.sleep(2) + + # finally, create a fully authenticated client using the new token, and + # keep trying to authenticate until we're successful + connect <- connectClient(service = server$url, authInfo = + list(token = token$token, + private_key = token$private_key)) + + repeat { + tryCatch({ + user <- connect$currentUser() + break + }, + error = function(e, ...) { + # we expect this to return unauthorized until the token becomes active, + # but bubble other errors + if (length(grep("401 - Unauthorized", e$message)) == 0) { + stop(e) + } + Sys.sleep(1) + }) + } + + # Create and remove an example application + + ## Create it + splineReticulator <- connect$createApplication("SplineReticulator") + + # Update the account id (since we have moved from unauthed user + # to authed user) + accountId <- splineReticulator$user_id + + ## Confirm it exists + apps <- connect$listApplications(accountId) + app <- apps[[which(sapply(apps, `[[`, "id") == splineReticulator$id)]] + expect_true(app$name == "SplineReticulator") + + ## Upload a bundle + pwd_splat <- strsplit(getwd(), "/")[[1]] + if (pwd_splat[length(pwd_splat)] == "rsconnect") { + path <- "tests/testthat/test-shinyApp/test-shinyApp.tar.gz" + } else { + path <- "test-shinyApp/test-shinyApp.tar.gz" + } + + response <- connect$uploadApplication( + splineReticulator$id, + normalizePath(path = path) + ) + + ## Deploy an application + appId <- response$app_id + response <- connect$deployApplication(appId) + id <- response$id + + ## Query the app for success / failure + response <- connect$waitForTask(id) + + ## Terminate the application (does not remove it from store) + connect$terminateApplication(appId) + + apps <- connect$listApplications(accountId) + expect_false(response$id %in% sapply(apps, "[[", "id")) + +}) diff --git a/tests/testthat/test-detection.R b/tests/testthat/test-detection.R new file mode 100644 index 0000000..fee09b2 --- /dev/null +++ b/tests/testthat/test-detection.R @@ -0,0 +1,7 @@ +context("type detection") + +test_that("Shiny R Markdown files are detected correctly", { + expect_true(isShinyRmd("./shiny-rmds/shiny-rmd-dashes.Rmd")) + expect_true(isShinyRmd("./shiny-rmds/shiny-rmd-dots.Rmd")) + expect_false(isShinyRmd("./shiny-rmds/non-shiny-rmd.Rmd")) +}) diff --git a/tests/testthat/test-lint.R b/tests/testthat/test-lint.R new file mode 100644 index 0000000..e0cacb4 --- /dev/null +++ b/tests/testthat/test-lint.R @@ -0,0 +1,73 @@ +context("lint") + +test_that("linter warns about absolute paths and relative paths", { + + ## Create a local file that 'server.R' tries to use + testDir <- "~/.rsconnect-tests" + exists <- file.exists(testDir) + + dir.create("~/.rsconnect-tests", showWarnings = FALSE) + file.create("~/.rsconnect-tests/local-file.txt") + + serverPath <- list.files("shinyapp-with-absolute-paths", + pattern = "server\\.R$") + + result <- lint("shinyapp-with-absolute-paths") + + absPathLintedIndices <- result[[serverPath]]$absolute.paths$indices + expect_identical(as.numeric(absPathLintedIndices), 15) + + relPathLintedIndices <- result[[serverPath]]$invalid.relative.paths$indices + expect_identical(as.numeric(relPathLintedIndices), 16) + + if (!exists) + unlink(testDir, recursive = TRUE) +}) + +test_that("badRelativePaths identifies bad paths correctly", { + + path <- "R/test.R" + ok <- "file.path('../inst/include')" + expect_false(badRelativePaths(ok, path = path)) + + bad <- "file.path('../../elsewhere')" + expect_true(badRelativePaths(bad, path = path)) + + ok <- "'../foo', '../bar', '../baz'" + expect_false(badRelativePaths(ok, path = path)) + +}) + +test_that("The linter identifies invalid application structures", { + expect_error(lint(".")) + expect_error(lint("shiny-app-in-subdir")) + lint("shiny-app-in-subdir/my-app") +}) + +test_that("The linter identifies files not matching in case sensitivity", { + result <- lint("shinyapp-with-absolute-paths") + server.R <- result[["server.R"]] + filepath.capitalization <- server.R[["filepath.capitalization"]] + expect_true(filepath.capitalization$indices == 31) +}) + +test_that("The linter believes that the Shiny example apps are okay", { + + examples <- list.files(system.file("examples", package = "shiny"), full.names = TRUE) + if (length(examples)) { + + results <- lapply(examples, lint) + + lints <- suppressMessages(lapply(results, printLinterResults)) + lapply(lints, function(project) { + lapply(project, function(file) { + lapply(file, function(linter) { + expect_true(length(linter$indices) == 0) + }) + }) + }) + + } + + +}) diff --git a/tests/testthat/test-shinyApp/test-shinyApp.tar.gz b/tests/testthat/test-shinyApp/test-shinyApp.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..ac11b48c10ba3de32efa5feb9d1a4d28dc858199 GIT binary patch literal 7088 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