UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

944 lines (941 loc) 42 kB
import { Observable, of, ReplaySubject, throwError } from 'rxjs'; import { catchError, expand, filter, map, mergeMap, switchMap, take, tap } from 'rxjs/operators'; import { EnvironmentModule } from '../manifest/environment-modules'; import { RpcObservableElevateClient } from '../rpc/elevate/rpc-observable-elevate-client'; import { RpcObservableElevateServer } from '../rpc/elevate/rpc-observable-elevate-server'; import { RpcServiceForwarder } from '../rpc/rpc-forwarder'; import { CoreEnvironment } from './core-environment'; import { GatewayUrlBuilder } from './gateway-url-builder'; import { GatewayUrls } from './gateway-urls'; import { Http, HttpMethod } from './http'; import { headerConstants } from './http-constants'; import { Net } from './net'; /** * The Gateway Connection class for creating requests and calling the Gateway's REST API */ export class GatewayConnection extends RpcServiceForwarder { http; authorizationManager; static rpcCommands = { forbiddenReceived: 'forbiddenRecieved' }; /** * The IPv4 address for localhost */ localhostIpV4 = '127.0.0.1'; /** * The IPv6 address for localhost */ localhostIpV6 = '::1'; /** * The localhost name */ localhost = 'localhost'; /** * Time interval to check for internalGatewayStatus refresh. */ lastUpdatedInternalGatewayStatusInterval = 1000 * 60 * 10; // 10 minutes /** * internally maintained gateway URL. */ internalGatewayUrl; /** * internally maintained static version. */ internalStaticVersion; /** * gatewayUrl param is specified. */ internalGatewayUrlSpecified; /** * Last time internal gateway status was updated in milliseconds */ lastUpdatedInternalGatewayStatus; /** * Internally maintained gateway status. */ internalGatewayStatus; /** * The replay subject for gateway url to settle. */ gatewayUrlAwaiter = new ReplaySubject(1); /** * The RPC observable elevate client. */ elevateClient = null; /** * The RPC observable elevate server. */ elevateServer = null; /** * The elevate callback observable. */ elevateCallbackInternal = () => of(false); /** * The replay subject for navigation ready state. */ navigationReady = new ReplaySubject(1); /** * Sets the elevate callback observable. */ set elevateCallback(value) { this.elevateCallbackInternal = value; if (!this.elevateServer) { this.elevateServer = new RpcObservableElevateServer(this.rpc); this.elevateServer.register((_context) => { return this.elevateCallbackInternal() .pipe(catchError((error, _caught) => throwError(() => ({ error: Net.getErrorMessage(error) }))), map(result => ({ elevated: result }))); }); } } /** * Indicates that the gateway is disabled and therefore should not be called. */ get disabled() { const environment = MsftSme.self().Environment; return environment && environment.configuration.gateway.disabled; } /** * Gets the gateway URL to connect to. */ get gatewayUrl() { return this.internalGatewayUrl; } /** * Gets the gateway URL specified state. */ get staticVersion() { return this.internalStaticVersion; } /** * Gets the gateway URL specified state. */ get gatewayUrlSpecified() { return this.internalGatewayUrlSpecified; } /** * Gets the gateway URL observable while setting up. */ get gatewayUrlObservable() { return this.gatewayUrlAwaiter.asObservable(); } /** * Gets the navigation ready observable. */ get navigationReadyObservable() { return this.navigationReady.asObservable(); } /** * Sets the navigation ready status. */ set navigationReadyStatus(ready) { this.navigationReady.next(ready); } /** * Gets the gateway information. */ get gatewayInfo() { if (!this.internalGatewayUrl) { throw new Error(MsftSme.getStrings().MsftSmeShell.Core.Error.GatewayUrlNotConfigured.message); } // RegEx: ('http' or 'https') '://' (('<gatewayName1>'):('<port>') or ('<gatewayName2>')) // 0: url // 1: https or http // 2: <gatewayName1>:<port> or <gatewayName2> // 3: <gatewayName1> or undefined // 4: <port> or undefined // 5: <gatewayName2> const url = MsftSme.trimEnd(this.internalGatewayUrl.toLowerCase(), '/'); const match = url.match(/(http|https):\/\/((.+):(\d+)|(.+))/); if (!match) { throw new Error(MsftSme.getStrings().MsftSmeShell.Core.Error.GatewayUrlMalformed.message); } const secure = (match[1] === 'https'); const name = match[3] || match[2]; const port = parseInt(match[4], 10) || (secure ? 443 : 80); return { name, secure, port }; } /** * Gets the gateway node name to make a CIM/PowerShell query to the gateway node. */ get gatewayName() { // localhost will be used to locally query gateway node. if this causes any access problem, need to be replaced. return 'localhost'; } /** * Gets gateway status from cache or sets cache if it doesn't exist. */ get gatewayStatus() { if (!this.internalGatewayStatus || Date.now() - this.lastUpdatedInternalGatewayStatus > this.lastUpdatedInternalGatewayStatusInterval) { return this.getStatus(); } return of(this.internalGatewayStatus); } /** * Initializes a new instance of the Gateway class. * * @param http the Http object. * @param rpc the Rpc class. * @patam authorizationManager the authorization manager class object. */ constructor(http, rpc, authorizationManager) { super('gateway-connection', rpc); this.http = http; this.authorizationManager = authorizationManager; // restore the AAD token if exist becase ealier access of token is required for gateway calls. authorizationManager.signOnManager.applySignedHttpRequestToken(MsftSme.self().Environment.configuration?.signOn?.signedHttpRequestToken); } /** * Configure the gateway URL to connect to. */ configureGatewayEnvironment(url, urlSpecified, staticVersion) { // trim last "/" if (url[url.length - 1] === '/') { url = url.substring(0, url.length - 1); } this.internalGatewayUrl = url; this.internalGatewayUrlSpecified = urlSpecified, this.internalStaticVersion = staticVersion; this.gatewayUrlAwaiter.next(url); } /** * Update the url with static version option. * @param url the original URL including options. * @returns updated url with "version=" option if staticVersion present. */ addStaticVersion(url) { if (MsftSme.isNullOrWhiteSpace(this.staticVersion) || this.staticVersion.indexOf('staticVersion=') < 0) { return url; } const splitter = url.indexOf('?') > 0 ? '&' : '?'; return `${url}${splitter}staticVersion=${this.staticVersion}`; } /** * Makes a POST call to the gateway * * @param relativeUrl the relative Url after "/api" * @param body the body string JSON.stringfy'ed * @param request the gateway request object. */ post(relativeUrl, body, request) { const postRequest = this.createRequest(HttpMethod.Post, relativeUrl, body, request); return this.call(postRequest); } /** * Makes a GET call to the gateway * * @param relativeUrl the relative Url after "/api" * @param request the gateway request object. */ get(relativeUrl, request) { const getRequest = this.createRequest(HttpMethod.Get, relativeUrl, null, request); return this.call(getRequest); } /** * Makes a PUT call to the gateway * * @param relativeUrl the relative Url after "/api" * @param body the body string JSON.stringfy'ed * @param request the gateway request object. */ put(relativeUrl, body, request) { const putRequest = this.createRequest(HttpMethod.Put, relativeUrl, body, request); return this.call(putRequest); } /** * Makes a PATCH call to the gateway * * @param relativeUrl the relative Url after "/api" * @param body the body string JSON.stringfy'ed * @param request the gateway request object. */ patch(relativeUrl, body, request) { const patchRequest = this.createRequest(HttpMethod.Patch, relativeUrl, body, request); return this.call(patchRequest); } /** * Makes a DELETE call to the gateway * * @param relativeUrl the relative Url after "/api" * @param body the body string JSON.stringfy'ed * @param request the gateway request object. */ delete(relativeUrl, body, request) { const deleteRequest = this.createRequest(HttpMethod.Delete, relativeUrl, body, request); return this.call(deleteRequest); } /** * Makes a DELETE call to the gateway without waiting for the response. * * @param relativeUrl the relative Url after "/api" * @param request the gateway request object. */ deleteQuick(relativeUrl, headers) { headers[headerConstants.MODULE_NAME] = EnvironmentModule.getModuleName(); headers[headerConstants.MODULE_VERSION] = EnvironmentModule.getModuleVersion(); headers[headerConstants.ACCEPT_LANGUAGE] = CoreEnvironment.localizationManager.getLocaleId().neutral; if (this.staticVersion) { headers[headerConstants.STATIC_VERSION] = this.staticVersion; } if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) { this.authorizationManager.signOnManager.SetAadAuthorizationHeader(headers); } const url = Net.gatewayApi(this.gatewayUrl, relativeUrl); this.http.deleteQuick(url, headers); } /** * Creates a GatewayRequest. * * @param method the http method to use * @param relativeUrl the relative Url after "/api/" * @param body the body string JSON.stringfy'ed * @param request the gateway request object to extend. */ createRequest(method, relativeUrl, body, request) { const defaultMaxRetry = 3; request = MsftSme.deepAssign({}, request); // if request is undefined, default to empty object request = request || {}; request.headers = request.headers || {}; request.headers[headerConstants.MODULE_NAME] = EnvironmentModule.getModuleName(); request.headers[headerConstants.MODULE_VERSION] = EnvironmentModule.getModuleVersion(); request.headers[headerConstants.ACCEPT_LANGUAGE] = CoreEnvironment.localizationManager.getLocaleId().neutral; if (this.staticVersion) { request.headers[headerConstants.STATIC_VERSION] = this.staticVersion; } // use default retry options if none are provided const retryHandlers = []; if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) { this.authorizationManager.signOnManager.SetAadAuthorizationHeader(request.headers); retryHandlers.push({ canHandle: (code, error) => this.authorizationManager.signOnManager.canHandleUnauthorizedLogin(code, error), handle: (code, originalRequest, error) => this.authorizationManager.signOnManager.handleUnauthorizedLogin(code, originalRequest, error) }); } if (request.retryHandlers != null && request.retryHandlers.length > 0) { retryHandlers.push(...request.retryHandlers); } return Object.assign(request, { method: method, url: relativeUrl, // default to the passed in body, the request body, or an empty string body: body || request.body || '', // default to the request headers, or an empty object headers: request.headers, // for the next 2 props, default to true unless explicitly set to false withCredentials: request.withCredentials === false ? false : true, crossDomain: request.crossDomain === false ? false : true, createXHR: () => new XMLHttpRequest(), retryHandlers, maxRetryCount: request.maxRetryCount === 0 ? 0 : request.maxRetryCount || defaultMaxRetry }); } /** * Make a request. * * @param request the request to execute against the gateway. * @return Observable<any> the query result observable. */ call(request) { if (!this.gatewayUrl) { return this.gatewayUrlAwaiter.pipe(mergeMap(() => this.call(request))); } // create gateway url from current url if not set yet. if (!request.url || (!request.url.startsWith('http://') && !request.url.startsWith('https://'))) { request.url = Net.gatewayApi(this.gatewayUrl, request.url); } // create retry options from request const retryOptions = { handlers: (request.retryHandlers || []), maxRetry: request.maxRetryCount }; // create observable for our request const requestObservable = this.http.request(request, retryOptions) .pipe(map((response) => response ? response.response : {})); if (request.beforeCall) { return request.beforeCall(request).pipe(mergeMap(() => requestObservable)); } return requestObservable; } /** * Gets default secure request options. * * @returns updated request object. */ get defaultHttpSecureOptions() { const request = { ...{ headers: {} }, ...Http.defaultHttpOptions }; if (this.authorizationManager.signOnManager.isSignOnTokenEnabled) { this.authorizationManager.signOnManager.SetAadAuthorizationHeader(request.headers); } return request; } /** * Check if elevation is required from the error object. * * @param error the ajax error object. */ isElevationRequired(error) { const code = error.xhr && error.xhr.response && error.xhr.response.error && error.xhr.response.error.code; return code === 'ElevationRequired'; } /** * Elevate the gateway if it's desktop mode running. */ elevate() { if (!this.elevateClient) { this.elevateClient = new RpcObservableElevateClient(this.rpc); } return this.elevateClient.elevate().pipe(map(result => result.elevated)); } /** * Creates and returns a new URL builder for the current connection. */ url() { return new GatewayUrlBuilder(this.gatewayUrl); } /** * Clear the DNS cache. */ clearDnsCache() { const dnsCacheClearUrl = 'gateway/dnsCacheClear'; return this.delete(dnsCacheClearUrl) .pipe(map(_ => null)); } /** * Polling to check if the gateway is elevated. */ pollingGatewayElevated() { // user might not respond for elevation prompt, maximum waiting time is 2.5 min. // getElevatedStatus() takes 5000ms when the gateway is not responding. // 2.5 min = count [30] * 5000 msec. const uniQueId = MsftSme.getUniqueId(); const maxWaitingCount = 30; let count = maxWaitingCount; return this.getElevatedStatus() .pipe(expand(status => { // user accepted. // adds 5 calls for the gateway dead period. // < Restart Requested from UI > // 1st query: it shows success on slow performed system, the gateway is even not shutdown yet. // 2nd query: It could success still. // 3rd query: Maybe timeout because the gateway is not started yet. // 4rd query: Maybe timeout because the gateway is not started yet. // 5rd query: Maybe timeout because the gateway is down. // 25 = 30 - 5 const pollingStartCount = 25; if (((count <= pollingStartCount && (!status.error || status.isGatewayProcessElevated)) || status.completed) && (status.id === uniQueId)) { return of({ completed: true, id: uniQueId, isGatewayProcessElevated: status.isGatewayProcessElevated }); } // no response for more than 2.5 minutes. // gateway was stopped for long or user never responded to UAC prompt. if (count-- <= 0 && status.id === uniQueId) { return of({ completed: true, id: uniQueId, isGatewayProcessElevated: status.isGatewayProcessElevated }); } return this.getElevatedStatus(); }), filter(result => result.isGatewayProcessElevated || result.completed), take(1), map(result => result.isGatewayProcessElevated)); } /** * Perform gateway status query but cut off if it exceeds 2.5 seconds. */ getElevatedStatus() { // if the gateway is not responding for 5000ms, cancel the call. const callCancelTime = 5000; return new Observable(observer => { let subscription = null; let timer = setTimeout(() => { // handle pending timeout of the query when the gateway doesn't respond. if (subscription) { observer.next({ error: true, isGatewayProcessElevated: false, completed: undefined, id: undefined }); observer.complete(); subscription.unsubscribe(); subscription = null; timer = null; } }, callCancelTime); subscription = this.getStatus() .subscribe({ next: data => { observer.next({ error: false, isGatewayProcessElevated: data.isGatewayProcessElevated, completed: undefined, id: undefined }); observer.complete(); subscription.unsubscribe(); subscription = null; if (timer) { clearTimeout(timer); } }, error: () => { observer.next({ error: true, isGatewayProcessElevated: false, completed: undefined, id: undefined }); observer.complete(); subscription.unsubscribe(); subscription = null; if (timer) { clearTimeout(timer); } } }); }); } /** * Gets gateway machine if found in list of given nodes * @param nodes Node names or IPs to check * @returns Node name of gateway if found, null otherwise */ getGateway(nodes) { return this.gatewayStatus.pipe(map(status => { for (const node of nodes) { if (MsftSme.isNullOrUndefined(node)) { continue; } switch (node.toLocaleLowerCase()) { case this.localhostIpV4: case this.localhostIpV6: case this.localhost: case status.fullyQualifiedDNSName?.toLocaleLowerCase(): case status.name?.toLocaleLowerCase(): case status.machineName?.toLocaleLowerCase(): return node; } if (status.addressList?.find((address) => address === node)) { return node; } } return null; })); } /** * Check gateway condition. */ checkCondition() { const result = {}; return this.getStatus() .pipe(switchMap(gateway => { if (gateway.gatewayMode === 'Service') { result.isServiceMode = true; result.isGatewayProcessElevated = false; return this.getAccessCheck(); } result.isServiceMode = false; result.isGatewayProcessElevated = gateway.isGatewayProcessElevated; return of(true); }), map((isAdmin) => { result.isGatewayAdmin = !!isAdmin; return result; }), take(1)); } /** * Get gateway status. */ getStatus() { return this.get('gateway/status').pipe(tap(status => { this.lastUpdatedInternalGatewayStatus = Date.now(); this.internalGatewayStatus = status; })); } /** * Get user access check. */ getAccessCheck() { return this.get(GatewayUrls.accessCheck); } /** * Called on a child service instance when onForwardInit returns from the parent * Initialize telemetry from within here so we can leverage gateway status for telemetry metadata. * @param data The response from the forwardInit call */ onForwardInitResponse(data) { if (data.error) { // if there is an error, we cannot continue, so throw its throw data.error; } if (!MsftSme.self().Environment.configuration.gateway.disabled) { this.internalGatewayUrl = data.result.gatewayName; this.internalGatewayUrlSpecified = data.result.gatewayUrlSpecified; this.internalStaticVersion = data.result.staticVersion; } } /** * Called when a new instance of the service in another window is initialized and needs to synchronize with its parent * @param from The RpcRelationshipType that this request is from * @returns an observable for the all the values needed to initialize the service */ onForwardInit() { if (this.gatewayUrl) { return of({ gatewayName: this.gatewayUrl, gatewayUrlSpecified: this.gatewayUrlSpecified, staticVersion: this.staticVersion }); } else { // if gateway value hasn't been set yet, then wait for it. if (MsftSme.self().Environment.configuration.gateway.disabled) { return of(null); } return this.gatewayUrlAwaiter .pipe(map(url => ({ gatewayName: url, gatewayUrlSpecified: this.gatewayUrlSpecified, staticVersion: this.staticVersion }))); } } /** * Called when the forwarded services counterpart wants to get data from the parent * @param from The RpcRelationshipType that this request is from * @param name The name of the method to forward to * @param args The arguments of the method * @returns an observable for the result of the method call */ onForwardExecute(from, name) { // gatewayConnection does not allow any method calls at this time return this.nameNotFound(name); } /** * Called when the forwarded services counterpart sends a notify message * @param from The RpcRelationshipType that this request is from * @param name The name of the property to change * @param value The new value of the property * @returns an observable that completes when the property has been changed. */ onForwardNotify(from, name) { if (from === 1 /* RpcRelationshipType.Child */ && name === GatewayConnection.rpcCommands.forbiddenReceived) { // Deprecated noop version 1.1100.0 at 10/1/2020. Using ErrorMonitor. return of(null); } // gatewayConnection does not allow any other notifications at this time return this.nameNotFound(name); } } //# sourceMappingURL=gateway-connection.js.map // SIG // Begin signature block // SIG // MIIoOgYJKoZIhvcNAQcCoIIoKzCCKCcCAQExDzANBglg // SIG // hkgBZQMEAgEFADB3BgorBgEEAYI3AgEEoGkwZzAyBgor // SIG // BgEEAYI3AgEeMCQCAQEEEBDgyQbOONQRoqMAEEvTUJAC // SIG // AQACAQACAQACAQACAQAwMTANBglghkgBZQMEAgEFAAQg // SIG // ntTxCyHu9C6aEvUCPC3BZxZlfinFsnL5WD2cjix7cjqg // SIG // gg2FMIIGAzCCA+ugAwIBAgITMwAABAO91ZVdDzsYrQAA // SIG // AAAEAzANBgkqhkiG9w0BAQsFADB+MQswCQYDVQQGEwJV // SIG // UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH // SIG // UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBv // SIG // cmF0aW9uMSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBT // SIG // aWduaW5nIFBDQSAyMDExMB4XDTI0MDkxMjIwMTExM1oX // SIG // DTI1MDkxMTIwMTExM1owdDELMAkGA1UEBhMCVVMxEzAR // SIG // BgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1v // SIG // bmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlv // SIG // bjEeMBwGA1UEAxMVTWljcm9zb2Z0IENvcnBvcmF0aW9u // SIG // MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA // SIG // n3RnXcCDp20WFMoNNzt4s9fV12T5roRJlv+bshDfvJoM // SIG // ZfhyRnixgUfGAbrRlS1St/EcXFXD2MhRkF3CnMYIoeMO // SIG // MuMyYtxr2sC2B5bDRMUMM/r9I4GP2nowUthCWKFIS1RP // SIG // lM0YoVfKKMaH7bJii29sW+waBUulAKN2c+Gn5znaiOxR // SIG // qIu4OL8f9DCHYpME5+Teek3SL95sH5GQhZq7CqTdM0fB // SIG // w/FmLLx98SpBu7v8XapoTz6jJpyNozhcP/59mi/Fu4tT // SIG // 2rI2vD50Vx/0GlR9DNZ2py/iyPU7DG/3p1n1zluuRp3u // SIG // XKjDfVKH7xDbXcMBJid22a3CPbuC2QJLowIDAQABo4IB // SIG // gjCCAX4wHwYDVR0lBBgwFgYKKwYBBAGCN0wIAQYIKwYB // SIG // BQUHAwMwHQYDVR0OBBYEFOpuKgJKc+OuNYitoqxfHlrE // SIG // gXAZMFQGA1UdEQRNMEukSTBHMS0wKwYDVQQLEyRNaWNy // SIG // b3NvZnQgSXJlbGFuZCBPcGVyYXRpb25zIExpbWl0ZWQx // SIG // FjAUBgNVBAUTDTIzMDAxMis1MDI5MjYwHwYDVR0jBBgw // SIG // FoAUSG5k5VAF04KqFzc3IrVtqMp1ApUwVAYDVR0fBE0w // SIG // SzBJoEegRYZDaHR0cDovL3d3dy5taWNyb3NvZnQuY29t // SIG // L3BraW9wcy9jcmwvTWljQ29kU2lnUENBMjAxMV8yMDEx // SIG // LTA3LTA4LmNybDBhBggrBgEFBQcBAQRVMFMwUQYIKwYB // SIG // BQUHMAKGRWh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9w // SIG // a2lvcHMvY2VydHMvTWljQ29kU2lnUENBMjAxMV8yMDEx // SIG // LTA3LTA4LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3 // SIG // DQEBCwUAA4ICAQBRaP+hOC1+dSKhbqCr1LIvNEMrRiOQ // SIG // EkPc7D6QWtM+/IbrYiXesNeeCZHCMf3+6xASuDYQ+AyB // SIG // TX0YlXSOxGnBLOzgEukBxezbfnhUTTk7YB2/TxMUcuBC // SIG // P45zMM0CVTaJE8btloB6/3wbFrOhvQHCILx41jTd6kUq // SIG // 4bIBHah3NG0Q1H/FCCwHRGTjAbyiwq5n/pCTxLz5XYCu // SIG // 4RTvy/ZJnFXuuwZynowyju90muegCToTOwpHgE6yRcTv // SIG // Ri16LKCr68Ab8p8QINfFvqWoEwJCXn853rlkpp4k7qzw // SIG // lBNiZ71uw2pbzjQzrRtNbCFQAfmoTtsHFD2tmZvQIg1Q // SIG // VkzM/V1KCjHL54ItqKm7Ay4WyvqWK0VIEaTbdMtbMWbF // SIG // zq2hkRfJTNnFr7RJFeVC/k0DNaab+bpwx5FvCUvkJ3z2 // SIG // wfHWVUckZjEOGmP7cecefrF+rHpif/xW4nJUjMUiPsyD // SIG // btY2Hq3VMLgovj+qe0pkJgpYQzPukPm7RNhbabFNFvq+ // SIG // kXWBX/z/pyuo9qLZfTb697Vi7vll5s/DBjPtfMpyfpWG // SIG // 0phVnAI+0mM4gH09LCMJUERZMgu9bbCGVIQR7cT5YhlL // SIG // t+tpSDtC6XtAzq4PJbKZxFjpB5wk+SRJ1gm87olbfEV9 // SIG // SFdO7iL3jWbjgVi1Qs1iYxBmvh4WhLWr48uouzCCB3ow // SIG // ggVioAMCAQICCmEOkNIAAAAAAAMwDQYJKoZIhvcNAQEL // SIG // BQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNo // SIG // aW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK // SIG // ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMT // SIG // KU1pY3Jvc29mdCBSb290IENlcnRpZmljYXRlIEF1dGhv // SIG // cml0eSAyMDExMB4XDTExMDcwODIwNTkwOVoXDTI2MDcw // SIG // ODIxMDkwOVowfjELMAkGA1UEBhMCVVMxEzARBgNVBAgT // SIG // Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc // SIG // BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEoMCYG // SIG // A1UEAxMfTWljcm9zb2Z0IENvZGUgU2lnbmluZyBQQ0Eg // SIG // MjAxMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC // SIG // ggIBAKvw+nIQHC6t2G6qghBNNLrytlghn0IbKmvpWlCq // SIG // uAY4GgRJun/DDB7dN2vGEtgL8DjCmQawyDnVARQxQtOJ // SIG // DXlkh36UYCRsr55JnOloXtLfm1OyCizDr9mpK656Ca/X // SIG // llnKYBoF6WZ26DJSJhIv56sIUM+zRLdd2MQuA3WraPPL // SIG // bfM6XKEW9Ea64DhkrG5kNXimoGMPLdNAk/jj3gcN1Vx5 // SIG // pUkp5w2+oBN3vpQ97/vjK1oQH01WKKJ6cuASOrdJXtjt // SIG // 7UORg9l7snuGG9k+sYxd6IlPhBryoS9Z5JA7La4zWMW3 // SIG // Pv4y07MDPbGyr5I4ftKdgCz1TlaRITUlwzluZH9TupwP // SIG // rRkjhMv0ugOGjfdf8NBSv4yUh7zAIXQlXxgotswnKDgl // SIG // mDlKNs98sZKuHCOnqWbsYR9q4ShJnV+I4iVd0yFLPlLE // SIG // tVc/JAPw0XpbL9Uj43BdD1FGd7P4AOG8rAKCX9vAFbO9 // SIG // G9RVS+c5oQ/pI0m8GLhEfEXkwcNyeuBy5yTfv0aZxe/C // SIG // HFfbg43sTUkwp6uO3+xbn6/83bBm4sGXgXvt1u1L50kp // SIG // pxMopqd9Z4DmimJ4X7IvhNdXnFy/dygo8e1twyiPLI9A // SIG // N0/B4YVEicQJTMXUpUMvdJX3bvh4IFgsE11glZo+TzOE // SIG // 2rCIF96eTvSWsLxGoGyY0uDWiIwLAgMBAAGjggHtMIIB // SIG // 6TAQBgkrBgEEAYI3FQEEAwIBADAdBgNVHQ4EFgQUSG5k // SIG // 5VAF04KqFzc3IrVtqMp1ApUwGQYJKwYBBAGCNxQCBAwe // SIG // CgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB // SIG // /wQFMAMBAf8wHwYDVR0jBBgwFoAUci06AjGQQ7kUBU7h // SIG // 6qfHMdEjiTQwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDov // SIG // L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVj // SIG // dHMvTWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNy // SIG // bDBeBggrBgEFBQcBAQRSMFAwTgYIKwYBBQUHMAKGQmh0 // SIG // dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMv // SIG // TWljUm9vQ2VyQXV0MjAxMV8yMDExXzAzXzIyLmNydDCB // SIG // nwYDVR0gBIGXMIGUMIGRBgkrBgEEAYI3LgMwgYMwPwYI // SIG // KwYBBQUHAgEWM2h0dHA6Ly93d3cubWljcm9zb2Z0LmNv // SIG // bS9wa2lvcHMvZG9jcy9wcmltYXJ5Y3BzLmh0bTBABggr // SIG // BgEFBQcCAjA0HjIgHQBMAGUAZwBhAGwAXwBwAG8AbABp // SIG // AGMAeQBfAHMAdABhAHQAZQBtAGUAbgB0AC4gHTANBgkq // SIG // hkiG9w0BAQsFAAOCAgEAZ/KGpZjgVHkaLtPYdGcimwuW // SIG // EeFjkplCln3SeQyQwWVfLiw++MNy0W2D/r4/6ArKO79H // SIG // qaPzadtjvyI1pZddZYSQfYtGUFXYDJJ80hpLHPM8QotS // SIG // 0LD9a+M+By4pm+Y9G6XUtR13lDni6WTJRD14eiPzE32m // SIG // kHSDjfTLJgJGKsKKELukqQUMm+1o+mgulaAqPyprWElj // SIG // HwlpblqYluSD9MCP80Yr3vw70L01724lruWvJ+3Q3fMO // SIG // r5kol5hNDj0L8giJ1h/DMhji8MUtzluetEk5CsYKwsat // SIG // ruWy2dsViFFFWDgycScaf7H0J/jeLDogaZiyWYlobm+n // SIG // t3TDQAUGpgEqKD6CPxNNZgvAs0314Y9/HG8VfUWnduVA // SIG // KmWjw11SYobDHWM2l4bf2vP48hahmifhzaWX0O5dY0Hj // SIG // Wwechz4GdwbRBrF1HxS+YWG18NzGGwS+30HHDiju3mUv // SIG // 7Jf2oVyW2ADWoUa9WfOXpQlLSBCZgB/QACnFsZulP0V3 // SIG // HjXG0qKin3p6IvpIlR+r+0cjgPWe+L9rt0uX4ut1eBrs // SIG // 6jeZeRhL/9azI2h15q/6/IvrC4DqaTuv/DDtBEyO3991 // SIG // bWORPdGdVk5Pv4BXIqF4ETIheu9BCrE/+6jMpF3BoYib // SIG // V3FWTkhFwELJm3ZbCoBIa/15n8G9bW1qyVJzEw16UM0x // SIG // ghoNMIIaCQIBATCBlTB+MQswCQYDVQQGEwJVUzETMBEG // SIG // A1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u // SIG // ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u // SIG // MSgwJgYDVQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5n // SIG // IFBDQSAyMDExAhMzAAAEA73VlV0POxitAAAAAAQDMA0G // SIG // CWCGSAFlAwQCAQUAoIGuMBkGCSqGSIb3DQEJAzEMBgor // SIG // BgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE // SIG // AYI3AgEVMC8GCSqGSIb3DQEJBDEiBCCosZxrI+2hnvtT // SIG // 5p9g4Wc0kifLNDd50uH0UZzc1OFMmDBCBgorBgEEAYI3 // SIG // AgEMMTQwMqAUgBIATQBpAGMAcgBvAHMAbwBmAHShGoAY // SIG // aHR0cDovL3d3dy5taWNyb3NvZnQuY29tMA0GCSqGSIb3 // SIG // DQEBAQUABIIBAHtFajPeHbRQWbzkmqhU8fSkBKty0yBP // SIG // 8HA2Xksin03Eu/kha0xPlLk5Z6BQNDNpxld5bULhIjde // SIG // ITS/bCuSHF9ZuDImEcjtNL2xh3LlHfsp3JblWiZuyY1i // SIG // Xf2J8S8pm+gzoV4FnH0OUFnK/+q+290+vcC6tv1p7HWk // SIG // IlWlufi2sYqrQZfW6250VRFyMaIMxEf/QtRKKHY118d8 // SIG // 7aCL0VUlQxYebG+AEGVWIMwjDcvq/sJt0iOKfSqQiQ8x // SIG // 5xHiFW9sOKKsGmv2kbWB6S2rNPFTWBcsGl9XkQ3mDI0/ // SIG // x8rtJEXzbbwO+qW+hz5MWtQaIROiYrmzmbt9ScOrsgkY // SIG // UNOhgheXMIIXkwYKKwYBBAGCNwMDATGCF4Mwghd/Bgkq // SIG // hkiG9w0BBwKgghdwMIIXbAIBAzEPMA0GCWCGSAFlAwQC // SIG // AQUAMIIBUgYLKoZIhvcNAQkQAQSgggFBBIIBPTCCATkC // SIG // AQEGCisGAQQBhFkKAwEwMTANBglghkgBZQMEAgEFAAQg // SIG // fX/kXdSir/b2LhwaUNn0Z1+Pyl616RDBDTB57PJw9wQC // SIG // BmeuE6DXWxgTMjAyNTAyMjAxNTI4MzguMDkxWjAEgAIB // SIG // 9KCB0aSBzjCByzELMAkGA1UEBhMCVVMxEzARBgNVBAgT // SIG // Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc // SIG // BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMG // SIG // A1UECxMcTWljcm9zb2Z0IEFtZXJpY2EgT3BlcmF0aW9u // SIG // czEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjg5MDAt // SIG // MDVFMC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGlt // SIG // ZS1TdGFtcCBTZXJ2aWNloIIR7TCCByAwggUIoAMCAQIC // SIG // EzMAAAHt4V/L1felXXMAAQAAAe0wDQYJKoZIhvcNAQEL // SIG // BQAwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp // SIG // bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT // SIG // FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd // SIG // TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwHhcN // SIG // MjMxMjA2MTg0NTQxWhcNMjUwMzA1MTg0NTQxWjCByzEL // SIG // MAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24x // SIG // EDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv // SIG // c29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9z // SIG // b2Z0IEFtZXJpY2EgT3BlcmF0aW9uczEnMCUGA1UECxMe // SIG // blNoaWVsZCBUU1MgRVNOOjg5MDAtMDVFMC1EOTQ3MSUw // SIG // IwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2 // SIG // aWNlMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC // SIG // AgEAqDDCbJK66mqcnC8TwtR+8w+4PPDaWxGkOko3EyEW // SIG // 8wlcmEDbM/E2i9aahUxADy9V+6Iy+PxGhFvlIzambP2s // SIG // jMluGCKRT2T9seBQTFQnXbHhdovmjDIwx4tC3E0GcTNr // SIG // N5hTKwmQFkny2F2AyIphQc/I9KC1hst1YC5gUyjOMS6r // SIG // +w2VM/AdkqAJmxLaetp4EpdITqDe90hcBPmNuErxkDFo // SIG // cpKRvr1w8HKVr8A3vk4J6y0ewE0RVzeSUtunZtssukmB // SIG // TEWJzBN3TBwkP1ECEEDQvJy5iL3SpAKFhDF7SbBhKN0K // SIG // zNktkgb+D6R0c0bpM07T/lAHHhsTPScq8FED+TghJlum // SIG // HIRMkQ0sD+IVPX+wdAModeD8PbyaO43sDY3jDyJJp3si // SIG // 0otK7r9qMf8URrXCfcgTQuQWkZLY8+7LT2qI0fjwwNn7 // SIG // gbQqPMSpZLed5lG+wGPgmRx6oS5u+qXTBegR79k78JVQ // SIG // XkETdtl42lVUcAoI4CZzXsLez3o3K6VJ9Khy4C6vtQTd // SIG // Q82LpFpE6+8E9M5dIl6/jbalJFkjp1kX3vDdtbQerr91 // SIG // ZFvJxXQobW22Wc9uKXi7SRGbjazfF3/T0zzM2VwyQSNR // SIG // HIkf/dUHBqGRZlWxVW9q1CALNNfmZHsL24ZhlQ3n1/aG // SIG // RuPyuIBlLE701vq9SWTMVE9jMKkCAwEAAaOCAUkwggFF // SIG // MB0GA1UdDgQWBBTOG/Ds994QKgRHypQGX9DSoeAiGTAf // SIG // BgNVHSMEGDAWgBSfpxVdAF5iXYP05dJlpxtTNRnpcjBf // SIG // BgNVHR8EWDBWMFSgUqBQhk5odHRwOi8vd3d3Lm1pY3Jv // SIG // c29mdC5jb20vcGtpb3BzL2NybC9NaWNyb3NvZnQlMjBU // SIG // aW1lLVN0YW1wJTIwUENBJTIwMjAxMCgxKS5jcmwwbAYI // SIG // KwYBBQUHAQEEYDBeMFwGCCsGAQUFBzAChlBodHRwOi8v // SIG // d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01p // SIG // Y3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEw // SIG // KDEpLmNydDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM // SIG // MAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDANBgkq // SIG // hkiG9w0BAQsFAAOCAgEAndYCtkXfnhi9Hh4vohOv6g2P // SIG // LG27DuHpmp3KeijzfsauWQGrYgUeI5kUYZvvVYpNBaNA // SIG // y1ovzdvGxSO3V2MNPad7woqW48uBKIn5tDbne/+FN9Iv // SIG // fu0b1u1zkN68d+/lO76vZZOsmKRgjadI5SdfPPwrkT4K // SIG // iZ36uRHXmnx9gKBuOoSlk3gew7l2rBrerKSTnpxnnUq3 // SIG // t+DFmankyENK2jiLWZxbhg8uPsaA9akc9kFvrtoAh2hv // SIG // AEI4WFDOLk4vbepLbY+nO12pq9s61rnHg4c+7Ci7bS0y // SIG // e8LOWKwNiPHE5WzAH9iltBlYym2Bnfi2RnbhCu/+37OB // SIG // lJDKnOdRbDXRtZ/s4HO8x7tqBhnggYOLPGUdGRcse47I // SIG // JvbEhQikOQrGwL5a/+tDXZOU3jEfCbNpDVInLtgqmdN/ // SIG // N907L04JO4g9Si4H0tehxL4zepuFSiSoIyeziSc2m7Uu // SIG // CUIFJyayGX8qLJOA9fK2Z4vaVMDdN1oE5nddFk8ImTru // SIG // IPFJ+oinDzGP4hak7uJ7ZMxVMQQaWxRupNQiDWZqIqxF // SIG // pgrRt5cmdiHXZo7SHn05CLxlm+Ccc8+5dpvxNpBjosQy // SIG // R7GoWVZsLKDb4cuZLv4p1PvnVx88PoZb6k0hU/PayBVY // SIG // XJrFjwyTzUUkqTIaCd91dmWv5ZCnG5FDNEm0IEvarHcw // SIG // ggdxMIIFWaADAgECAhMzAAAAFcXna54Cm0mZAAAAAAAV // SIG // MA0GCSqGSIb3DQEBCwUAMIGIMQswCQYDVQQGEwJVUzET // SIG // MBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVk // SIG // bW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 // SIG // aW9uMTIwMAYDVQQDEylNaWNyb3NvZnQgUm9vdCBDZXJ0 // SIG // aWZpY2F0ZSBBdXRob3JpdHkgMjAxMDAeFw0yMTA5MzAx // SIG // ODIyMjVaFw0zMDA5MzAxODMyMjVaMHwxCzAJBgNVBAYT // SIG // AlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQH // SIG // EwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29y // SIG // cG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1l // SIG // LVN0YW1wIFBDQSAyMDEwMIICIjANBgkqhkiG9w0BAQEF // SIG // AAOCAg8AMIICCgKCAgEA5OGmTOe0ciELeaLL1yR5vQ7V // SIG // gtP97pwHB9KpbE51yMo1V/YBf2xK4OK9uT4XYDP/XE/H // SIG // ZveVU3Fa4n5KWv64NmeFRiMMtY0Tz3cywBAY6GB9alKD // SIG // RLemjkZrBxTzxXb1hlDcwUTIcVxRMTegCjhuje3XD9gm // SIG // U3w5YQJ6xKr9cmmvHaus9ja+NSZk2pg7uhp7M62AW36M // SIG // EBydUv626GIl3GoPz130/o5Tz9bshVZN7928jaTjkY+y // SIG // OSxRnOlwaQ3KNi1wjjHINSi947SHJMPgyY9+tVSP3PoF // SIG // VZhtaDuaRr3tpK56KTesy+uDRedGbsoy1cCGMFxPLOJi // SIG // ss254o2I5JasAUq7vnGpF1tnYN74kpEeHT39IM9zfUGa // SIG // RnXNxF803RKJ1v2lIH1+/NmeRd+2ci/bfV+Autuqfjbs // SIG // Nkz2K26oElHovwUDo9Fzpk03dJQcNIIP8BDyt0cY7afo // SIG // mXw/TNuvXsLz1dhzPUNOwTM5TI4CvEJoLhDqhFFG4tG9 // SIG // ahhaYQFzymeiXtcodgLiMxhy16cg8ML6EgrXY28MyTZk // SIG // i1ugpoMhXV8wdJGUlNi5UPkLiWHzNgY1GIRH29wb0f2y // SIG // 1BzFa/ZcUlFdEtsluq9QBXpsxREdcu+N+VLEhReTwDwV // SIG // 2xo3xwgVGD94q0W29R6HXtqPnhZyacaue7e3PmriLq0C // SIG // AwEAAaOCAd0wggHZMBIGCSsGAQQBgjcVAQQFAgMBAAEw // SIG // IwYJKwYBBAGCNxUCBBYEFCqnUv5kxJq+gpE8RjUpzxD/ // SIG // LwTuMB0GA1UdDgQWBBSfpxVdAF5iXYP05dJlpxtTNRnp // SIG // cjBcBgNVHSAEVTBTMFEGDCsGAQQBgjdMg30BATBBMD8G // SIG // CCsGAQUFBwIBFjNodHRwOi8vd3d3Lm1pY3Jvc29mdC5j // SIG // b20vcGtpb3BzL0RvY3MvUmVwb3NpdG9yeS5odG0wEwYD // SIG // VR0lBAwwCgYIKwYBBQUHAwgwGQYJKwYBBAGCNxQCBAwe // SIG // CgBTAHUAYgBDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB // SIG // /wQFMAMBAf8wHwYDVR0jBBgwFoAU1fZWy4/oolxiaNE9 // SIG // lJBb186aGMQwVgYDVR0fBE8wTTBLoEmgR4ZFaHR0cDov // SIG // L2NybC5taWNyb3NvZnQuY29tL3BraS9jcmwvcHJvZHVj // SIG // dHMvTWljUm9vQ2VyQXV0XzIwMTAtMDYtMjMuY3JsMFoG // SIG // CCsGAQUFBwEBBE4wTDBKBggrBgEFBQcwAoY+aHR0cDov // SIG // L3d3dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNS // SIG // b29DZXJBdXRfMjAxMC0wNi0yMy5jcnQwDQYJKoZIhvcN // SIG // AQELBQADggIBAJ1VffwqreEsH2cBMSRb4Z5yS/ypb+pc // SIG // FLY+TkdkeLEGk5c9MTO1OdfCcTY/2mRsfNB1OW27DzHk // SIG // wo/7bNGhlBgi7ulmZzpTTd2YurYeeNg2LpypglYAA7AF // SIG // vonoaeC6Ce5732pvvinLbtg/SHUB2RjebYIM9W0jVOR4 // SIG // U3UkV7ndn/OOPcbzaN9l9qRWqveVtihVJ9AkvUCgvxm2 // SIG // EhIRXT0n4ECWOKz3+SmJw7wXsFSFQrP8DJ6LGYnn8Atq // SIG // gcKBGUIZUnWKNsIdw2FzLixre24/LAl4FOmRsqlb30mj // SIG // dAy87JGA0j3mSj5mO0+7hvoyGtmW9I/2kQH2zsZ0/fZM // SIG // cm8Qq3UwxTSwethQ/gpY3UA8x1RtnWN0SCyxTkctwRQE // SIG // cb9k+SS+c23Kjgm9swFXSVRk2XPXfx5bRAGOWhmRaw2f // SIG // pCjcZxkoJLo4S5pu+yFUa2pFEUep8beuyOiJXk+d0tBM // SIG // drVXVAmxaQFEfnyhYWxz/gq77EFmPWn9y8FBSX5+k77L // SIG // +DvktxW/tM4+pTFRhLy/AsGConsXHRWJjXD+57XQKBqJ // SIG // C4822rpM+Zv/Cuk0+CQ1ZyvgDbjmjJnW4SLq8CdCPSWU // SIG // 5nR0W2rRnj7tfqAxM328y+l7vzhwRNGQ8cirOoo6CGJ/ // SIG // 2XBjU02N7oJtpQUQwXEGahC0HVUzWLOhcGbyoYIDUDCC // SIG // AjgCAQEwgfmhgdGkgc4wgcsxCzAJBgNVBAYTAlVTMRMw // SIG // EQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt // SIG // b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRp // SIG // b24xJTAjBgNVBAsTHE1pY3Jvc29mdCBBbWVyaWNhIE9w // SIG // ZXJhdGlvbnMxJzAlBgNVBAsTHm5TaGllbGQgVFNTIEVT // SIG // Tjo4OTAwLTA1RTAtRDk0NzElMCMGA1UEAxMcTWljcm9z // SIG // b2Z0IFRpbWUtU3RhbXAgU2VydmljZaIjCgEBMAcGBSsO // SIG // AwIaAxUA7h2sikwmmLGMSYfqFk8erlTxcPmggYMwgYCk // SIG // fjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGlu // SIG // Z3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMV // SIG // TWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQDEx1N // SIG // aWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDANBgkq // SIG // hkiG9w0BAQsFAAIFAOthI1IwIhgPMjAyNTAyMjAwMzQz // SIG // MTRaGA8yMDI1MDIyMTAzNDMxNFowdzA9BgorBgEEAYRZ // SIG // CgQBMS8wLTAKAgUA62EjUgIBADAKAgEAAgIeUwIB/zAH // SIG // AgEAAgISqjAKAgUA62J00gIBADA2BgorBgEEAYRZCgQC // SIG // MSgwJjAMBgorBgEEAYRZCgMCoAowCAIBAAIDB6EgoQow // SIG // CAIBAAIDAYagMA0GCSqGSIb3DQEBCwUAA4IBAQDFtsBB // SIG // KC2jelFRIH2CDQeM3DtnNegpCDOhl0+j00u9EhAd85/o // SIG // 0qBY59TRkhpLyBG2ZVnuJgap82ZhqQg74CMz0GKMIkBt // SIG // FiRZcovtkex73M6SS/Ru0j8n2IbEbWDLRwYgVFV8jA3N // SIG // AaZqav/7T99QTV1iRBYdYq+P4faTR4eVP0V1MRLX02JL // SIG // F7s5GanB/Ij98LAQze6HbsHgzE1CYP5W7w15fh2jwJU3 // SIG // 5wWXTpoYUyfLsbGzGKybzQDcKEZV4SrzY5Fc5LXQ2UAC // SIG // P6UgigZ6HkWlloCavzaWMWqZc7kzeEo9VBPZXOolN/i8 // SIG // 88O2OoOLIIULIIYHj1vTz8YokCrpMYIEDTCCBAkCAQEw // SIG // gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hp // SIG // bmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT // SIG // FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMd // SIG // TWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMA // SIG // AAHt4V/L1felXXMAAQAAAe0wDQYJYIZIAWUDBAIBBQCg // SIG // ggFKMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRABBDAv // SIG // BgkqhkiG9w0BCQQxIgQg/QN4PPgo7o8KmDbOjX4Qs/dq // SIG // ruK+UD5tWSqFiAXvO3wwgfoGCyqGSIb3DQEJEAIvMYHq // SIG // MIHnMIHkMIG9BCCNLg1oNAhbHisStwNepdcKyMK7Eg61 // SIG // 2esUn9BeMWzKOTCBmDCBgKR+MHwxCzAJBgNVBAYTAlVT // SIG // MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdS // SIG // ZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y // SIG // YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0 // SIG // YW1wIFBDQSAyMDEwAhMzAAAB7eFfy9X3pV1zAAEAAAHt // SIG // MCIEIKehpqPZNMWvWSU4xN85KGCCJ8ISrlck3EcHy8ij // SIG // fNkaMA0GCSqGSIb3DQEBCwUABIICAGlPCybScqnoBlSJ // SIG // 9JPpAqo21S2XOIpbr645B5Z7kl7obBRFewefP5F9SHrr // SIG // gqg9TNsGcAvcIQxoeTcDJ96ye4lyqc01iAf+mPyPYnr4 // SIG // rtcWHV2PuAgsOSvAhUd4UB5wq2Q5Z3f4Mb5yW3FURLib // SIG // v3cIIcb8CJdW62vKTZRyO3L5h+tIvtE+fClQUxFq3RYJ // SIG // g6mwQLhU2x7hTS1OgGCiOJLdDULOGgeb4w3gqvW223zx // SIG // 0IHBfKTa9VEmBtDessR5jcWYdxFcHtWVLuBbb1TPcEgn // SIG // Ei+yqppGlo8/VcN6l0Ck2qfoUEAs3SQojvGv49sAdSn2 // SIG // nX2XhpSgt/uDT2XSg8PtuSPH0dJ3hTbLzUSlYA03HtC/ // SIG // pbZrh5N07zNFt3mA3gzAWboAQVROPm8YFCAB0bP10Dfb // SIG // M9BG7S1R3FVfLgtu4A+KQueuU1W6hi6i+OIowexUnrj8 // SIG // tH7W7cVDy/NniBvZj5WLiXVCvbqZ6qTGKFqzA08iFU/p // SIG // CCdCpvcWnPFFJby41ab15AHGfP5e53+rX6Hy+CXXgior // SIG // IV8dc45J58xM26GUMjjuJNu9O3/zzO4tOlz0QT+8lba4 // SIG // i5qXzgF04oCdC1ji2HCYOXZilGmzmk0bUG4UK6RdarF9 // SIG // 4q3wjhc5YwImnV3aS90CpTZZeL1DeDzh0xeyox/dtP70 // SIG // UK/EFGKp // SIG // End signature block