@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
556 lines (553 loc) • 28.3 kB
JavaScript
import { forkJoin, of } from 'rxjs';
import { catchError, map, mergeMap } from 'rxjs/operators';
import { ErrorExtended } from '../data/error-extended';
import { NativeQ } from '../data/native-q';
import { LogLevel } from '../diagnostics/log-level';
import { Logging } from '../diagnostics/logging';
import { HostCoreManager, HostCoreTokenMode } from '../host/host-core-manager';
import { EnvironmentModule } from './environment-modules';
/**
* The Manifest service class.
* (Localized string cannot be used in this class due to initialization phase when the strings are not ready yet.)
*/
export class ManifestLoader {
static logSourceName = 'ManifestLoader';
static gatewayUrl = 'gatewayUrl';
static manifestFile = 'manifest.json';
static deferred = NativeQ.defer();
static internalLoaded = ManifestLoader.deferred.promise;
/**
* Manifest loading promise.
*/
get loaded() {
return ManifestLoader.internalLoaded;
}
/**
* Load the manifest.
*/
static loadManifest() {
const self = MsftSme.self();
const mode = self.Init ? self.Init.mode : 0 /* MsftSme.EnvironmentMode.NotUse */;
const hostCoreManager = new HostCoreManager();
switch (mode) {
case 0 /* MsftSme.EnvironmentMode.NotUse */:
// Turn OFF iframe feature.
ManifestLoader.deferred.reject('no iFrame');
break;
case 1 /* MsftSme.EnvironmentMode.LoadEmbedded */:
// JSON file posting by module iframe.
const manifest = {
name: self.Init.moduleName,
version: self.Init.moduleVersion,
signature: EnvironmentModule.defaultSignature,
shell: {
name: EnvironmentModule.nameOfShell,
origin: self.Init.shellOrigin
}
};
// Turn ON module self-loading.
ManifestLoader.load(hostCoreManager, manifest);
break;
case 2 /* MsftSme.EnvironmentMode.Load */:
// Turn ON iframe feature by Shell and Module.
ManifestLoader.load(hostCoreManager);
break;
}
return ManifestLoader.internalLoaded;
}
/**
* Load the manifest into the MsftSme.Environment.
*
* @param hostCoreManager the hostCoreManager object to load the manifest.
* @param manifest the self loading manifest.
* @return Promise<any> the promise object.
*/
static load(hostCoreManager, manifest) {
if (manifest) {
ManifestLoader.update(manifest, null);
return ManifestLoader.internalLoaded;
}
const gatewayUrlParam = MsftSme.getLocationSearchParameter(ManifestLoader.gatewayUrl);
let manifestUrl = ManifestLoader.manifestFile;
if (gatewayUrlParam && MsftSme.self().Init.isProduction && Object.keys(MsftSme.sideLoad()).length === 0) {
// use the gateway endpoint for manifest source.
manifestUrl = `${gatewayUrlParam.value}/${ManifestLoader.manifestFile}`;
}
hostCoreManager.httpGet(manifestUrl)
.pipe(mergeMap(result => ManifestLoader.mergeGatewayManifest(hostCoreManager, result.response)), mergeMap(shellManifest => {
const response = shellManifest;
if (response.modules) {
return ManifestLoader.fetchSideloadManifests(hostCoreManager)
.pipe(map(sideLoads => {
const sideloadShellOrigins = [];
sideLoads = sideLoads.filter(s => {
if (MsftSme.isNullOrUndefined(s)) {
return false;
}
const isShell = s.name === EnvironmentModule.nameOfShell;
if (isShell) {
sideloadShellOrigins.push(s.origin);
}
return !isShell;
});
if (sideloadShellOrigins.length > 0) {
Logging.log({
source: ManifestLoader.logSourceName,
level: LogLevel.Warning,
consoleGroupHeader: `Unable to sideload: "${sideloadShellOrigins}".`,
message: `Cannot sideload ${EnvironmentModule.nameOfShell} from ${sideloadShellOrigins}.
Did you mean to run ${EnvironmentModule.nameOfShell} locally?`
});
}
return { manifest: response, sideLoads: sideLoads };
}));
}
return of({ manifest: response, sideLoads: [] });
}))
.subscribe({
next: result => {
const manifestResult = result.manifest;
const modules = manifestResult.modules;
const selfInit = MsftSme.self().Init;
selfInit.shellVersion = manifestResult.version;
selfInit.gatewayApiVersion = manifestResult.gatewayApiVersion;
selfInit.gatewayPlatform = manifestResult.gatewayPlatform;
result.sideLoads.forEach(sideLoad => {
if (sideLoad) {
sideLoad.isSideLoaded = true;
const foundIndex = modules.findIndex((item) => item.name === sideLoad.name);
if (foundIndex >= 0) {
modules.splice(foundIndex, 1, sideLoad);
}
else {
modules.push(sideLoad);
}
}
});
ManifestLoader.update(result.manifest, hostCoreManager.token);
},
error: error => {
// communicate main.ts for error message.
const extendedError = error;
if (hostCoreManager.tokenMode === HostCoreTokenMode.Aad) {
extendedError.extendedSource = ErrorExtended.sources.aadSso;
}
ManifestLoader.deferred.reject(error);
}
});
return ManifestLoader.internalLoaded;
}
/**
* Merges the GatewayUrl manifest with the passed in shell manifest
* Merges modules only at this time with a preference for modules included in the shell
*/
static mergeGatewayManifest(hostCoreManager, shellManifest) {
// it's production mode and no side-loading omits calling manifest.json again.
if (MsftSme.self().Init.isProduction && Object.keys(MsftSme.sideLoad()).length === 0) {
return of(shellManifest);
}
const gatewayUrlParam = MsftSme.getLocationSearchParameter(ManifestLoader.gatewayUrl);
if (!gatewayUrlParam) {
return of(shellManifest);
}
return hostCoreManager.getNoCache(`${gatewayUrlParam.value}/${ManifestLoader.manifestFile}`, false, 'json')
.pipe(map(result => {
const gatewayManifest = result.response;
if (Array.isArray(gatewayManifest.modules)) {
if (!Array.isArray(shellManifest.modules)) {
shellManifest.modules = gatewayManifest.modules;
}
else {
gatewayManifest.modules.forEach(mod => {
mod.origin = gatewayUrlParam.value;
const foundIndex = shellManifest.modules.findIndex((item) => item.name === mod.name);
if (foundIndex === -1) {
shellManifest.modules.push(mod);
}
});
}
}
return shellManifest;
}), catchError(() => {
// no localization
Logging.log({
source: ManifestLoader.logSourceName,
level: LogLevel.Warning,
consoleGroupHeader: `Unable to load gateway manifest: "${gatewayUrlParam.value}".`,
message: `Cannot load ${gatewayUrlParam.value}. Please make sure that a manifest.json is available at this location.`
});
return of(shellManifest);
}));
}
/**
* retrieves all of the side loaded manifests.
*
* @return Observable<any[]> the manifests.
*/
static fetchSideloadManifests(hostCoreManager) {
const sideLoadList = MsftSme.sideLoad();
if (Object.keys(sideLoadList).length === 0) {
return of([]);
}
const sideLoadManifestAwaiters = [];
MsftSme.forEachKey(sideLoadList, (key, sideLoad) => {
sideLoadManifestAwaiters.push(
// don't send credentials when debugging a side-loading module.
hostCoreManager.getNoCache(`${sideLoad.origin}/${ManifestLoader.manifestFile}`, false, 'json', false)
.pipe(map(result => {
const manifest = result.response;
manifest.origin = sideLoad.origin;
return manifest;
}), catchError(() => {
// no localization
Logging.log({
source: ManifestLoader.logSourceName,
level: LogLevel.Warning,
consoleGroupHeader: `Unable to sideload: "${sideLoad.origin}".`,
message: `Cannot sideload ${sideLoad.origin}. Please make sure that an extension is running at this origin.`
});
return of(null);
})));
});
return forkJoin(sideLoadManifestAwaiters);
}
/**
* Update the environment by the manifest.
*/
static update(manifest, token) {
try {
const self = MsftSme.self();
if (token) {
// store the last token if exists.
if (!manifest.configuration) {
manifest.configuration = {};
}
// passed the signOn objec to GatewayConnection object to configure into the SignOnManager.
manifest.configuration.signOn = { signedHttpRequestToken: token };
}
self.Environment = EnvironmentModule.createEnvironment(manifest, self.Resources.localeId);
ManifestLoader.deferred.resolve();
}
catch (e) {
// no localization
const message = 'Unable to load the manifest: {0}'.format(e);
ManifestLoader.deferred.reject(message);
throw new Error(message);
}
}
}
//# sourceMappingURL=manifest-loader.js.map
// SIG // Begin signature block
// SIG // MIIoKgYJKoZIhvcNAQcCoIIoGzCCKBcCAQExDzANBglg
// SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor
// SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC
// SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg
// SIG // hbztwqZLJt6BU7yIHXhEvvjyiBj0WdTaP4Tp1+eKZg6g
// SIG // gg12MIIF9DCCA9ygAwIBAgITMwAABARsdAb/VysncgAA
// SIG // AAAEBDANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV
// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
// SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT
// SIG // aWduaW5nIFBDQSAyMDExMB4XDTI0MDkxMjIwMTExNFoX
// SIG // DTI1MDkxMTIwMTExNFowdDELMAkGA1UEBhMCVVMxEzAR
// SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v
// SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv
// SIG // bjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
// SIG // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
// SIG // tCg32mOdDA6rBBnZSMwxwXegqiDEUFlvQH9Sxww07hY3
// SIG // w7L52tJxLg0mCZjcszQddI6W4NJYb5E9QM319kyyE0l8
// SIG // EvA/pgcxgljDP8E6XIlgVf6W40ms286Cr0azaA1f7vaJ
// SIG // jjNhGsMqOSSSXTZDNnfKs5ENG0bkXeB2q5hrp0qLsm/T
// SIG // WO3oFjeROZVHN2tgETswHR3WKTm6QjnXgGNj+V6rSZJO
// SIG // /WkTqc8NesAo3Up/KjMwgc0e67x9llZLxRyyMWUBE9co
// SIG // T2+pUZqYAUDZ84nR1djnMY3PMDYiA84Gw5JpceeED38O
// SIG // 0cEIvKdX8uG8oQa047+evMfDRr94MG9EWwIDAQABo4IB
// SIG // czCCAW8wHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYB
// SIG // BQUHAwMwHQYDVR0OBBYEFPIboTWxEw1PmVpZS+AzTDwo
// SIG // oxFOMEUGA1UdEQQ+MDykOjA4MR4wHAYDVQQLExVNaWNy
// SIG // b3NvZnQgQ29ycG9yYXRpb24xFjAUBgNVBAUTDTIzMDAx
// SIG // Mis1MDI5MjMwHwYDVR0jBBgwFoAUSG5k5VAF04KqFzc3
// SIG // IrVtqMp1ApUwVAYDVR0fBE0wSzBJoEegRYZDaHR0cDov
// SIG // L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWlj
// SIG // Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNybDBhBggr
// SIG // BgEFBQcBAQRVMFMwUQYIKwYBBQUHMAKGRWh0dHA6Ly93
// SIG // d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvY2VydHMvTWlj
// SIG // Q29kU2lnUENBMjAxMV8yMDExLTA3LTA4LmNydDAMBgNV
// SIG // HRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4ICAQCI5g/S
// SIG // KUFb3wdUHob6Qhnu0Hk0JCkO4925gzI8EqhS+K4umnvS
// SIG // BU3acsJ+bJprUiMimA59/5x7WhJ9F9TQYy+aD9AYwMtb
// SIG // KsQ/rst+QflfML+Rq8YTAyT/JdkIy7R/1IJUkyIS6srf
// SIG // G1AKlX8n6YeAjjEb8MI07wobQp1F1wArgl2B1mpTqHND
// SIG // lNqBjfpjySCScWjUHNbIwbDGxiFr93JoEh5AhJqzL+8m
// SIG // onaXj7elfsjzIpPnl8NyH2eXjTojYC9a2c4EiX0571Ko
// SIG // mhENF3RtR25A7/X7+gk6upuE8tyMy4sBkl2MUSF08U+E
// SIG // 2LOVcR8trhYxV1lUi9CdgEU2CxODspdcFwxdT1+G8YNc
// SIG // gzHyjx3BNSI4nOZcdSnStUpGhCXbaOIXfvtOSfQX/UwJ
// SIG // oruhCugvTnub0Wna6CQiturglCOMyIy/6hu5rMFvqk9A
// SIG // ltIJ0fSR5FwljW6PHHDJNbCWrZkaEgIn24M2mG1M/Ppb
// SIG // /iF8uRhbgJi5zWxo2nAdyDBqWvpWxYIoee/3yIWpquVY
// SIG // cYGhJp/1I1sq/nD4gBVrk1SKX7Do2xAMMO+cFETTNSJq
// SIG // fTSSsntTtuBLKRB5mw5qglHKuzapDiiBuD1Zt4QwxA/1
// SIG // kKcyQ5L7uBayG78kxlVNNbyrIOFH3HYmdH0Pv1dIX/Mq
// SIG // 7avQpAfIiLpOWwcbjzCCB3owggVioAMCAQICCmEOkNIA
// SIG // AAAAAAMwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYT
// SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH
// SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y
// SIG // cG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290
// SIG // IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDExMB4XDTEx
// SIG // MDcwODIwNTkwOVoXDTI2MDcwODIxMDkwOVowfjELMAkG
// SIG // A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAO
// SIG // BgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m
// SIG // dCBDb3Jwb3JhdGlvbjEoMCYGA1UEAxMfTWljcm9zb2Z0
// SIG // IENvZGUgU2lnbmluZyBQQ0EgMjAxMTCCAiIwDQYJKoZI
// SIG // hvcNAQEBBQADggIPADCCAgoCggIBAKvw+nIQHC6t2G6q
// SIG // ghBNNLrytlghn0IbKmvpWlCquAY4GgRJun/DDB7dN2vG
// SIG // EtgL8DjCmQawyDnVARQxQtOJDXlkh36UYCRsr55JnOlo
// SIG // XtLfm1OyCizDr9mpK656Ca/XllnKYBoF6WZ26DJSJhIv
// SIG // 56sIUM+zRLdd2MQuA3WraPPLbfM6XKEW9Ea64DhkrG5k
// SIG // NXimoGMPLdNAk/jj3gcN1Vx5pUkp5w2+oBN3vpQ97/vj
// SIG // K1oQH01WKKJ6cuASOrdJXtjt7UORg9l7snuGG9k+sYxd
// SIG // 6IlPhBryoS9Z5JA7La4zWMW3Pv4y07MDPbGyr5I4ftKd
// SIG // gCz1TlaRITUlwzluZH9TupwPrRkjhMv0ugOGjfdf8NBS
// SIG // v4yUh7zAIXQlXxgotswnKDglmDlKNs98sZKuHCOnqWbs
// SIG // YR9q4ShJnV+I4iVd0yFLPlLEtVc/JAPw0XpbL9Uj43Bd
// SIG // D1FGd7P4AOG8rAKCX9vAFbO9G9RVS+c5oQ/pI0m8GLhE
// SIG // fEXkwcNyeuBy5yTfv0aZxe/CHFfbg43sTUkwp6uO3+xb
// SIG // n6/83bBm4sGXgXvt1u1L50kppxMopqd9Z4DmimJ4X7Iv
// SIG // hNdXnFy/dygo8e1twyiPLI9AN0/B4YVEicQJTMXUpUMv
// SIG // dJX3bvh4IFgsE11glZo+TzOE2rCIF96eTvSWsLxGoGyY
// SIG // 0uDWiIwLAgMBAAGjggHtMIIB6TAQBgkrBgEEAYI3FQEE
// SIG // AwIBADAdBgNVHQ4EFgQUSG5k5VAF04KqFzc3IrVtqMp1
// SIG // ApUwGQYJKwYBBAGCNxQCBAweCgBTAHUAYgBDAEEwCwYD
// SIG // VR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
// SIG // BBgwFoAUci06AjGQQ7kUBU7h6qfHMdEjiTQwWgYDVR0f
// SIG // BFMwUTBPoE2gS4ZJaHR0cDovL2NybC5taWNyb3NvZnQu
// SIG // Y29tL3BraS9jcmwvcHJvZHVjdHMvTWljUm9vQ2VyQXV0
// SIG // MjAxMV8yMDExXzAzXzIyLmNybDBeBggrBgEFBQcBAQRS
// SIG // MFAwTgYIKwYBBQUHMAKGQmh0dHA6Ly93d3cubWljcm9z
// SIG // b2Z0LmNvbS9wa2kvY2VydHMvTWljUm9vQ2VyQXV0MjAx
// SIG // MV8yMDExXzAzXzIyLmNydDCBnwYDVR0gBIGXMIGUMIGR
// SIG // BgkrBgEEAYI3LgMwgYMwPwYIKwYBBQUHAgEWM2h0dHA6
// SIG // Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvZG9jcy9w
// SIG // cmltYXJ5Y3BzLmh0bTBABggrBgEFBQcCAjA0HjIgHQBM
// SIG // AGUAZwBhAGwAXwBwAG8AbABpAGMAeQBfAHMAdABhAHQA
// SIG // ZQBtAGUAbgB0AC4gHTANBgkqhkiG9w0BAQsFAAOCAgEA
// SIG // Z/KGpZjgVHkaLtPYdGcimwuWEeFjkplCln3SeQyQwWVf
// SIG // Liw++MNy0W2D/r4/6ArKO79HqaPzadtjvyI1pZddZYSQ
// SIG // fYtGUFXYDJJ80hpLHPM8QotS0LD9a+M+By4pm+Y9G6XU
// SIG // tR13lDni6WTJRD14eiPzE32mkHSDjfTLJgJGKsKKELuk
// SIG // qQUMm+1o+mgulaAqPyprWEljHwlpblqYluSD9MCP80Yr
// SIG // 3vw70L01724lruWvJ+3Q3fMOr5kol5hNDj0L8giJ1h/D
// SIG // Mhji8MUtzluetEk5CsYKwsatruWy2dsViFFFWDgycSca
// SIG // f7H0J/jeLDogaZiyWYlobm+nt3TDQAUGpgEqKD6CPxNN
// SIG // ZgvAs0314Y9/HG8VfUWnduVAKmWjw11SYobDHWM2l4bf
// SIG // 2vP48hahmifhzaWX0O5dY0HjWwechz4GdwbRBrF1HxS+
// SIG // YWG18NzGGwS+30HHDiju3mUv7Jf2oVyW2ADWoUa9WfOX
// SIG // pQlLSBCZgB/QACnFsZulP0V3HjXG0qKin3p6IvpIlR+r
// SIG // +0cjgPWe+L9rt0uX4ut1eBrs6jeZeRhL/9azI2h15q/6
// SIG // /IvrC4DqaTuv/DDtBEyO3991bWORPdGdVk5Pv4BXIqF4
// SIG // ETIheu9BCrE/+6jMpF3BoYibV3FWTkhFwELJm3ZbCoBI
// SIG // a/15n8G9bW1qyVJzEw16UM0xghoMMIIaCAIBATCBlTB+
// SIG // MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv
// SIG // bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWlj
// SIG // cm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYDVQQDEx9NaWNy
// SIG // b3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExAhMzAAAE
// SIG // BGx0Bv9XKydyAAAAAAQEMA0GCWCGSAFlAwQCAQUAoIGu
// SIG // MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisG
// SIG // AQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3
// SIG // DQEJBDEiBCCcykIIyjfwzruFJXHhqj6ZOznGu/RsM/gV
// SIG // dEgg+we88TBCBgorBgEEAYI3AgEMMTQwMqAUgBIATQBp
// SIG // AGMAcgBvAHMAbwBmAHShGoAYaHR0cDovL3d3dy5taWNy
// SIG // b3NvZnQuY29tMA0GCSqGSIb3DQEBAQUABIIBAHjfwsYN
// SIG // LAxsbTTP6UHWzfTi6O/eRFz06+idR8LlGK2jYOnEmJDA
// SIG // WxCs1BqGuDcbMfjYqt38/GkJU+PGe8HtoZk2IuCAzQ04
// SIG // sx1cuCXAN5yPxE/Etk6ou4z2Sy0JN+4MIy2KTzyaCDOu
// SIG // 9W5Vg7BMj0hzjCR7Otd3eZ4ASK27k8I9Ww03XLMb6Gvz
// SIG // mdA2EQA4YRX7kKcPhsGEamH5lgG8+ETyFj5hMyK0Q6t7
// SIG // 4EhlB4MEY8vgUx7BYPstzxQ/Vr99rhsqwN0Nvzt+T24p
// SIG // 2ODkvGcBeYHTFJJKOhgM0FbLoBRz7DzoK01oDptkkhOl
// SIG // iSuQiuCWZsSMA/RBHpI+KTdd1cihgheWMIIXkgYKKwYB
// SIG // BAGCNwMDATGCF4Iwghd+BgkqhkiG9w0BBwKgghdvMIIX
// SIG // awIBAzEPMA0GCWCGSAFlAwQCAQUAMIIBUQYLKoZIhvcN
// SIG // AQkQAQSgggFABIIBPDCCATgCAQEGCisGAQQBhFkKAwEw
// SIG // MTANBglghkgBZQMEAgEFAAQgTfKSk5hcw86M5ORCStgW
// SIG // mr6Rw8tK8uiMt0Kn8F2fNqMCBmeuE6DXihgSMjAyNTAy
// SIG // MjAxNTI4MzkuNDNaMASAAgH0oIHRpIHOMIHLMQswCQYD
// SIG // VQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4G
// SIG // A1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0
// SIG // IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQg
// SIG // QW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hp
// SIG // ZWxkIFRTUyBFU046ODkwMC0wNUUwLUQ5NDcxJTAjBgNV
// SIG // BAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Wg
// SIG // ghHtMIIHIDCCBQigAwIBAgITMwAAAe3hX8vV96VdcwAB
// SIG // AAAB7TANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJV
// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
// SIG // cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
// SIG // dGFtcCBQQ0EgMjAxMDAeFw0yMzEyMDYxODQ1NDFaFw0y
// SIG // NTAzMDUxODQ1NDFaMIHLMQswCQYDVQQGEwJVUzETMBEG
// SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u
// SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
// SIG // MSUwIwYDVQQLExxNaWNyb3NvZnQgQW1lcmljYSBPcGVy
// SIG // YXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046
// SIG // ODkwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29m
// SIG // dCBUaW1lLVN0YW1wIFNlcnZpY2UwggIiMA0GCSqGSIb3
// SIG // DQEBAQUAA4ICDwAwggIKAoICAQCoMMJskrrqapycLxPC
// SIG // 1H7zD7g88NpbEaQ6SjcTIRbzCVyYQNsz8TaL1pqFTEAP
// SIG // L1X7ojL4/EaEW+UjNqZs/ayMyW4YIpFPZP2x4FBMVCdd
// SIG // seF2i+aMMjDHi0LcTQZxM2s3mFMrCZAWSfLYXYDIimFB
// SIG // z8j0oLWGy3VgLmBTKM4xLqv7DZUz8B2SoAmbEtp62ngS
// SIG // l0hOoN73SFwE+Y24SvGQMWhykpG+vXDwcpWvwDe+Tgnr
// SIG // LR7ATRFXN5JS26dm2yy6SYFMRYnME3dMHCQ/UQIQQNC8
// SIG // nLmIvdKkAoWEMXtJsGEo3QrM2S2SBv4PpHRzRukzTtP+
// SIG // UAceGxM9JyrwUQP5OCEmW6YchEyRDSwP4hU9f7B0Ayh1
// SIG // 4Pw9vJo7jewNjeMPIkmneyLSi0ruv2ox/xRGtcJ9yBNC
// SIG // 5BaRktjz7stPaojR+PDA2fuBtCo8xKlkt53mUb7AY+CZ
// SIG // HHqhLm76pdMF6BHv2TvwlVBeQRN22XjaVVRwCgjgJnNe
// SIG // wt7PejcrpUn0qHLgLq+1BN1DzYukWkTr7wT0zl0iXr+N
// SIG // tqUkWSOnWRfe8N21tB6uv3VkW8nFdChtbbZZz24peLtJ
// SIG // EZuNrN8Xf9PTPMzZXDJBI1EciR/91QcGoZFmVbFVb2rU
// SIG // IAs01+ZkewvbhmGVDefX9oZG4/K4gGUsTvTW+r1JZMxU
// SIG // T2MwqQIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFM4b8Oz3
// SIG // 3hAqBEfKlAZf0NKh4CIZMB8GA1UdIwQYMBaAFJ+nFV0A
// SIG // XmJdg/Tl0mWnG1M1GelyMF8GA1UdHwRYMFYwVKBSoFCG
// SIG // Tmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv
// SIG // Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0El
// SIG // MjAyMDEwKDEpLmNybDBsBggrBgEFBQcBAQRgMF4wXAYI
// SIG // KwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0LmNv
// SIG // bS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1T
// SIG // dGFtcCUyMFBDQSUyMDIwMTAoMSkuY3J0MAwGA1UdEwEB
// SIG // /wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYD
// SIG // VR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQCd
// SIG // 1gK2Rd+eGL0eHi+iE6/qDY8sbbsO4emancp6KPN+xq5Z
// SIG // AatiBR4jmRRhm+9Vik0Fo0DLWi/N28bFI7dXYw09p3vC
// SIG // ipbjy4Eoifm0Nud7/4U30i9+7RvW7XOQ3rx37+U7vq9l
// SIG // k6yYpGCNp0jlJ188/CuRPgqJnfq5EdeafH2AoG46hKWT
// SIG // eB7DuXasGt6spJOenGedSre34MWZqeTIQ0raOItZnFuG
// SIG // Dy4+xoD1qRz2QW+u2gCHaG8AQjhYUM4uTi9t6kttj6c7
// SIG // Xamr2zrWuceDhz7sKLttLTJ7ws5YrA2I8cTlbMAf2KW0
// SIG // GVjKbYGd+LZGduEK7/7fs4GUkMqc51FsNdG1n+zgc7zH
// SIG // u2oGGeCBg4s8ZR0ZFyx7jsgm9sSFCKQ5CsbAvlr/60Nd
// SIG // k5TeMR8Js2kNUicu2CqZ03833TsvTgk7iD1KLgfS16HE
// SIG // vjN6m4VKJKgjJ7OJJzabtS4JQgUnJrIZfyosk4D18rZn
// SIG // i9pUwN03WgTmd10WTwiZOu4g8Un6iKcPMY/iFqTu4ntk
// SIG // zFUxBBpbFG6k1CINZmoirEWmCtG3lyZ2IddmjtIefTkI
// SIG // vGWb4Jxzz7l2m/E2kGOixDJHsahZVmwsoNvhy5ku/inU
// SIG // ++dXHzw+hlvqTSFT89rIFVhcmsWPDJPNRSSpMhoJ33V2
// SIG // Za/lkKcbkUM0SbQgS9qsdzCCB3EwggVZoAMCAQICEzMA
// SIG // AAAVxedrngKbSZkAAAAAABUwDQYJKoZIhvcNAQELBQAw
// SIG // gYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n
// SIG // dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVN
// SIG // aWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1p
// SIG // Y3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
// SIG // eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4
// SIG // MzIyNVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldh
// SIG // c2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNV
// SIG // BAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE
// SIG // AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAw
// SIG // ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDk
// SIG // 4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXIyjVX
// SIG // 9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VG
// SIG // Iwy1jRPPdzLAEBjoYH1qUoNEt6aORmsHFPPFdvWGUNzB
// SIG // RMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1yaa8dq6z2
// SIG // Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+
// SIG // jlPP1uyFVk3v3byNpOORj7I5LFGc6XBpDco2LXCOMcg1
// SIG // KL3jtIckw+DJj361VI/c+gVVmG1oO5pGve2krnopN6zL
// SIG // 64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakX
// SIG // W2dg3viSkR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX78
// SIG // 2Z5F37ZyL9t9X4C626p+Nuw2TPYrbqgSUei/BQOj0XOm
// SIG // TTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07B
// SIG // MzlMjgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIz
// SIG // GHLXpyDwwvoSCtdjbwzJNmSLW6CmgyFdXzB0kZSU2LlQ
// SIG // +QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF
// SIG // emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode
// SIG // 2o+eFnJpxq57t7c+auIurQIDAQABo4IB3TCCAdkwEgYJ
// SIG // KwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIEFgQU
// SIG // KqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+n
// SIG // FV0AXmJdg/Tl0mWnG1M1GelyMFwGA1UdIARVMFMwUQYM
// SIG // KwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6
// SIG // Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9S
// SIG // ZXBvc2l0b3J5Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcD
// SIG // CDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNV
// SIG // HQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME
// SIG // GDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8E
// SIG // TzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5j
// SIG // b20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRf
// SIG // MjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoG
// SIG // CCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5j
// SIG // b20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2
// SIG // LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt
// SIG // 4SwfZwExJFvhnnJL/Klv6lwUtj5OR2R4sQaTlz0xM7U5
// SIG // 18JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZnOlNN
// SIG // 3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu
// SIG // 2D9IdQHZGN5tggz1bSNU5HhTdSRXud2f8449xvNo32X2
// SIG // pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4rPf5KYnD
// SIG // vBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMu
// SIG // LGt7bj8sCXgU6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG
// SIG // +jIa2Zb0j/aRAfbOxnT99kxybxCrdTDFNLB62FD+Cljd
// SIG // QDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJ
// SIG // VGTZc9d/HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRr
// SIG // akURR6nxt67I6IleT53S0Ex2tVdUCbFpAUR+fKFhbHP+
// SIG // CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8C
// SIG // wYKiexcdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVn
// SIG // K+ANuOaMmdbhIurwJ0I9JZTmdHRbatGePu1+oDEzfbzL
// SIG // 6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq
// SIG // ELQdVTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCB
// SIG // yzELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0
// SIG // b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1p
// SIG // Y3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWlj
// SIG // cm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UE
// SIG // CxMeblNoaWVsZCBUU1MgRVNOOjg5MDAtMDVFMC1EOTQ3
// SIG // MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBT
// SIG // ZXJ2aWNloiMKAQEwBwYFKw4DAhoDFQDuHayKTCaYsYxJ
// SIG // h+oWTx6uVPFw+aCBgzCBgKR+MHwxCzAJBgNVBAYTAlVT
// SIG // MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS
// SIG // ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y
// SIG // YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0
// SIG // YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA62Ej
// SIG // UjAiGA8yMDI1MDIyMDAzNDMxNFoYDzIwMjUwMjIxMDM0
// SIG // MzE0WjB3MD0GCisGAQQBhFkKBAExLzAtMAoCBQDrYSNS
// SIG // AgEAMAoCAQACAh5TAgH/MAcCAQACAhKqMAoCBQDrYnTS
// SIG // AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkK
// SIG // AwKgCjAIAgEAAgMHoSChCjAIAgEAAgMBhqAwDQYJKoZI
// SIG // hvcNAQELBQADggEBAMW2wEEoLaN6UVEgfYINB4zcO2c1
// SIG // 6CkIM6GXT6PTS70SEB3zn+jSoFjn1NGSGkvIEbZlWe4m
// SIG // BqnzZmGpCDvgIzPQYowiQG0WJFlyi+2R7HvczpJL9G7S
// SIG // PyfYhsRtYMtHBiBUVXyMDc0Bpmpq//tP31BNXWJEFh1i
// SIG // r4/h9pNHh5U/RXUxEtfTYksXuzkZqcH8iP3wsBDN7odu
// SIG // weDMTUJg/lbvDXl+HaPAlTfnBZdOmhhTJ8uxsbMYrJvN
// SIG // ANwoRlXhKvNjkVzktdDZQAI/pSCKBnoeRaWWgJq/NpYx
// SIG // aplzuTN4Sj1UE9lc6iU3+Lzzw7Y6g4sghQsghgePW9PP
// SIG // xiiQKukxggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJV
// SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH
// SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv
// SIG // cmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1T
// SIG // dGFtcCBQQ0EgMjAxMAITMwAAAe3hX8vV96VdcwABAAAB
// SIG // 7TANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkD
// SIG // MQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCB+
// SIG // FTC9qZo9yK2phxBsEy9ROGizxLboiDzvQ7FLhBinizCB
// SIG // +gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EII0uDWg0
// SIG // CFseKxK3A16l1wrIwrsSDrXZ6xSf0F4xbMo5MIGYMIGA
// SIG // pH4wfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp
// SIG // bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT
// SIG // FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd
// SIG // TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA
// SIG // AAHt4V/L1felXXMAAQAAAe0wIgQgp6Gmo9k0xa9ZJTjE
// SIG // 3zkoYIInwhKuVyTcRwfLyKN82RowDQYJKoZIhvcNAQEL
// SIG // BQAEggIATWa5WF4+qAogYe6Wpzr3QL0I7Lpk4jR+Q3Ue
// SIG // 2X4cMDRpE0WHiLlqawkeJngQKbl+vvJyqB2YvIzyJRo8
// SIG // f3V8JRfe1Ycq58U+dFzh7oz4LxyF7dUkN/6kFVDELNuo
// SIG // L5Gepb/dbVZpi1Gm44cVfd19VCFvPDWcrPi1b7GE2sl6
// SIG // HLxd3yJhKNf+geqanDIojA0bm9BFio8M7Ip+rNRrIOPl
// SIG // ye1U/l81RAmIKMYO000vqmw0UK/+qq+GPjeLqEdLsLeq
// SIG // cROJKO6HQKNG5+atHONi+byLUTnJFP9pEzxpOWiGf7U3
// SIG // dlCjuVcgWExUUIr7dE96VyB/YKgatpqF6YJ1ndWwhYN2
// SIG // wxd3ZdcmNp80QfOR/IKb93Wg1jl20Qh+nGYCuWV28qxB
// SIG // +I9YbL3NMiTL7yjeNkXGOFNLwfmBCwuMjHRpIZM/ljuB
// SIG // S9ibzvgBFNul0k0Q42Q5HDoPwuIuZ1SFFp5tMQ1phHyD
// SIG // m+UIuXyvRJjGFJgX4M2T7XMXT1vwXxm4zU5jxE9dZS1i
// SIG // 9ZbF6Y+XeTrnITMwYF+9wjNpMr5nQqktg1JLqb2Kz56j
// SIG // ac9JWn0j1MDyaB2qUrZJfhJD6PDK016VYCgiJmOHahZd
// SIG // 5CnC4K+hB7KkGMgRI0lpckST0oJcodDfWN7Q/Muby/sb
// SIG // dGPgM4YDpjpm3MZryEBMrtCQ+/Xx28o=
// SIG // End signature block