@push.rocks/smartjmap 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.smartconfig.json +5 -2
- package/dist_ts/00_commitinfo_data.js +3 -3
- package/dist_ts/classes.jmapclient.d.ts +43 -13
- package/dist_ts/classes.jmapclient.js +326 -149
- package/dist_ts/classes.jmapserver.d.ts +154 -84
- package/dist_ts/classes.jmapserver.js +1788 -660
- package/dist_ts/classes.memorymailbackend.d.ts +109 -0
- package/dist_ts/classes.memorymailbackend.js +670 -0
- package/dist_ts/index.d.ts +2 -0
- package/dist_ts/index.js +3 -1
- package/dist_ts/interfaces.backend.d.ts +349 -0
- package/dist_ts/interfaces.backend.js +13 -0
- package/npmextra.json +4 -2
- package/package.json +8 -7
- package/readme.hints.md +25 -14
- package/readme.md +149 -18
- package/ts/00_commitinfo_data.ts +2 -2
- package/ts/classes.jmapclient.ts +414 -153
- package/ts/classes.jmapserver.ts +2389 -761
- package/ts/classes.memorymailbackend.ts +850 -0
- package/ts/index.ts +2 -0
- package/ts/interfaces.backend.ts +413 -0
|
@@ -1,4 +1,94 @@
|
|
|
1
|
-
import * as plugins from
|
|
1
|
+
import * as plugins from "./smartjmap.plugins.js";
|
|
2
|
+
import { JMAP_CORE_CAPABILITY, JMAP_MAIL_CAPABILITY, JMAP_SUBMISSION_CAPABILITY, } from "./classes.jmapclient.js";
|
|
3
|
+
import {} from "./interfaces.backend.js";
|
|
4
|
+
import { MemoryMailBackend } from "./classes.memorymailbackend.js";
|
|
5
|
+
/**
|
|
6
|
+
* Semantic capability marker for the bounded streaming-upload server surface.
|
|
7
|
+
* Consumers must check this exact value before relying on streaming backend
|
|
8
|
+
* uploads, upload concurrency limits, Bearer-only challenges, or error mapping.
|
|
9
|
+
*/
|
|
10
|
+
export const JMAP_SERVER_STREAMING_API_VERSION = 1;
|
|
11
|
+
/** The advertised — and enforced — RFC 8620 core limits. */
|
|
12
|
+
export const JMAP_SERVER_LIMITS = {
|
|
13
|
+
maxSizeUpload: 50_000_000,
|
|
14
|
+
maxConcurrentUpload: 4,
|
|
15
|
+
maxSizeRequest: 10_000_000,
|
|
16
|
+
maxConcurrentRequests: 4,
|
|
17
|
+
maxCallsInRequest: 16,
|
|
18
|
+
maxObjectsInGet: 500,
|
|
19
|
+
maxObjectsInSet: 500,
|
|
20
|
+
};
|
|
21
|
+
/** The session object never changes at runtime, so its state is constant. */
|
|
22
|
+
const SESSION_STATE = "0";
|
|
23
|
+
/** Default Email/get properties per RFC 8621 §4.2. */
|
|
24
|
+
const DEFAULT_EMAIL_PROPERTIES = [
|
|
25
|
+
"id",
|
|
26
|
+
"blobId",
|
|
27
|
+
"threadId",
|
|
28
|
+
"mailboxIds",
|
|
29
|
+
"keywords",
|
|
30
|
+
"size",
|
|
31
|
+
"receivedAt",
|
|
32
|
+
"messageId",
|
|
33
|
+
"inReplyTo",
|
|
34
|
+
"references",
|
|
35
|
+
"sender",
|
|
36
|
+
"from",
|
|
37
|
+
"to",
|
|
38
|
+
"cc",
|
|
39
|
+
"bcc",
|
|
40
|
+
"replyTo",
|
|
41
|
+
"subject",
|
|
42
|
+
"sentAt",
|
|
43
|
+
"hasAttachment",
|
|
44
|
+
"preview",
|
|
45
|
+
"bodyValues",
|
|
46
|
+
"textBody",
|
|
47
|
+
"htmlBody",
|
|
48
|
+
"attachments",
|
|
49
|
+
];
|
|
50
|
+
const KNOWN_EMAIL_PROPERTIES = new Set(DEFAULT_EMAIL_PROPERTIES);
|
|
51
|
+
const MAILBOX_PROPERTIES = [
|
|
52
|
+
"id",
|
|
53
|
+
"name",
|
|
54
|
+
"parentId",
|
|
55
|
+
"role",
|
|
56
|
+
"sortOrder",
|
|
57
|
+
"totalEmails",
|
|
58
|
+
"unreadEmails",
|
|
59
|
+
"totalThreads",
|
|
60
|
+
"unreadThreads",
|
|
61
|
+
"myRights",
|
|
62
|
+
"isSubscribed",
|
|
63
|
+
];
|
|
64
|
+
const KNOWN_MAILBOX_PROPERTIES = new Set(MAILBOX_PROPERTIES);
|
|
65
|
+
const SUPPORTED_EMAIL_FILTER_KEYS = new Set([
|
|
66
|
+
"inMailbox",
|
|
67
|
+
"text",
|
|
68
|
+
"subject",
|
|
69
|
+
"from",
|
|
70
|
+
"to",
|
|
71
|
+
"before",
|
|
72
|
+
"after",
|
|
73
|
+
"hasKeyword",
|
|
74
|
+
"notKeyword",
|
|
75
|
+
]);
|
|
76
|
+
const DEFAULT_MAILBOX_RIGHTS = {
|
|
77
|
+
mayReadItems: true,
|
|
78
|
+
mayAddItems: true,
|
|
79
|
+
mayRemoveItems: true,
|
|
80
|
+
maySetSeen: true,
|
|
81
|
+
maySetKeywords: true,
|
|
82
|
+
mayCreateChild: true,
|
|
83
|
+
mayRename: true,
|
|
84
|
+
mayDelete: true,
|
|
85
|
+
maySubmit: true,
|
|
86
|
+
};
|
|
87
|
+
const textEncoder = new TextEncoder();
|
|
88
|
+
/** Ensures bytes are backed by a plain ArrayBuffer so they satisfy BodyInit. */
|
|
89
|
+
const asBodyBytes = (data) => data.buffer instanceof ArrayBuffer
|
|
90
|
+
? data
|
|
91
|
+
: new Uint8Array(data);
|
|
2
92
|
/** Error type used inside method dispatch; rendered as a JMAP `error` method response. */
|
|
3
93
|
class JmapServerMethodError extends Error {
|
|
4
94
|
constructor(type, description) {
|
|
@@ -6,868 +96,1906 @@ class JmapServerMethodError extends Error {
|
|
|
6
96
|
this.type = type;
|
|
7
97
|
}
|
|
8
98
|
}
|
|
99
|
+
class JmapRequestBodyError extends Error {
|
|
100
|
+
constructor(reason) {
|
|
101
|
+
super(reason);
|
|
102
|
+
this.reason = reason;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** UTF-8-safe truncation: cuts at a codepoint boundary at or below maxBytes. */
|
|
106
|
+
const truncateUtf8 = (value, maxBytes) => {
|
|
107
|
+
const bytes = textEncoder.encode(value);
|
|
108
|
+
if (bytes.length <= maxBytes) {
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
let end = maxBytes;
|
|
112
|
+
while (end > 0 && (bytes[end] & 0b1100_0000) === 0b1000_0000) {
|
|
113
|
+
end--;
|
|
114
|
+
}
|
|
115
|
+
return new TextDecoder().decode(bytes.subarray(0, end));
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Evaluates an RFC 6901 JSON pointer with the RFC 8620 §3.7 extension: a `*`
|
|
119
|
+
* token applied to an array maps the rest of the pointer over every item,
|
|
120
|
+
* flattening one array level. Throws on any unresolvable path.
|
|
121
|
+
*/
|
|
122
|
+
const evalJsonPointer = (root, pointer) => {
|
|
123
|
+
if (pointer === "") {
|
|
124
|
+
return root;
|
|
125
|
+
}
|
|
126
|
+
if (!pointer.startsWith("/")) {
|
|
127
|
+
throw new Error(`Invalid JSON pointer "${pointer}".`);
|
|
128
|
+
}
|
|
129
|
+
const tokens = pointer.slice(1).split("/");
|
|
130
|
+
const evaluate = (value, index) => {
|
|
131
|
+
if (index === tokens.length) {
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
const token = tokens[index].replaceAll("~1", "/").replaceAll("~0", "~");
|
|
135
|
+
if (Array.isArray(value)) {
|
|
136
|
+
if (token === "*") {
|
|
137
|
+
const results = value.map((item) => evaluate(item, index + 1));
|
|
138
|
+
return results.some((result) => Array.isArray(result))
|
|
139
|
+
? results.flatMap((result) => (Array.isArray(result) ? result : [result]))
|
|
140
|
+
: results;
|
|
141
|
+
}
|
|
142
|
+
const arrayIndex = Number(token);
|
|
143
|
+
if (!Number.isInteger(arrayIndex) || arrayIndex < 0 ||
|
|
144
|
+
arrayIndex >= value.length) {
|
|
145
|
+
throw new Error(`JSON pointer index "${token}" is out of range.`);
|
|
146
|
+
}
|
|
147
|
+
return evaluate(value[arrayIndex], index + 1);
|
|
148
|
+
}
|
|
149
|
+
if (value !== null && typeof value === "object" && token in value) {
|
|
150
|
+
return evaluate(value[token], index + 1);
|
|
151
|
+
}
|
|
152
|
+
throw new Error(`JSON pointer token "${token}" does not resolve.`);
|
|
153
|
+
};
|
|
154
|
+
return evaluate(root, 0);
|
|
155
|
+
};
|
|
9
156
|
/**
|
|
10
|
-
* A
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
157
|
+
* A JMAP server core (RFC 8620) with the RFC 8621 mail method surface,
|
|
158
|
+
* dispatching all storage into a pluggable `IJmapMailBackend`.
|
|
159
|
+
*
|
|
160
|
+
* The primary API is the web-standard `fetchHandler(request)` — mount it in
|
|
161
|
+
* any Request/Response runtime (Deno, Bun, service workers, Node ≥18). The
|
|
162
|
+
* `start(port)`/`stop()` pair wraps it in a node:http server for convenience.
|
|
163
|
+
*
|
|
164
|
+
* Endpoints: session (`/.well-known/jmap`, `/jmap/session`), API
|
|
165
|
+
* (`/jmap/api`), upload (`/jmap/upload/{accountId}`), download
|
|
166
|
+
* (`/jmap/download/{accountId}/{blobId}/{name}?type=`), and event source
|
|
167
|
+
* (`/jmap/eventsource` — SSE StateChange pushes per RFC 8620 §7.3).
|
|
168
|
+
*
|
|
169
|
+
* With no options this behaves as the offline test helper: an in-memory
|
|
170
|
+
* backend plus a static credential registry (`addUser`/`addBearerToken`).
|
|
14
171
|
*/
|
|
15
172
|
export class JmapServer {
|
|
16
|
-
constructor() {
|
|
17
|
-
this.
|
|
173
|
+
constructor(options = {}) {
|
|
174
|
+
this.registry = new Map();
|
|
175
|
+
this.httpServer = null;
|
|
18
176
|
this.sockets = new Set();
|
|
19
|
-
this.eventStreams = new
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
this.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
177
|
+
this.eventStreams = new Set();
|
|
178
|
+
this.changeFeedUnsubscribe = null;
|
|
179
|
+
this.cleanupErrors = [];
|
|
180
|
+
this.activeApiRequests = 0;
|
|
181
|
+
this.activeUploadRequests = 0;
|
|
182
|
+
this.activeUploadsByPrincipal = new Map();
|
|
183
|
+
this.activeNodeRequests = new Set();
|
|
184
|
+
this.nodeRequestControllers = new Set();
|
|
185
|
+
this.stopping = false;
|
|
186
|
+
this.options = options;
|
|
187
|
+
this.backend = options.backend ?? new MemoryMailBackend();
|
|
188
|
+
const authenticationChallenges = options.authenticationChallenges ?? [
|
|
189
|
+
'Bearer realm="jmap"',
|
|
190
|
+
'Basic realm="jmap"',
|
|
191
|
+
];
|
|
192
|
+
if (authenticationChallenges.length === 0 ||
|
|
193
|
+
authenticationChallenges.some((challenge) => typeof challenge !== "string" || !challenge.trim() ||
|
|
194
|
+
/[\r\n]/.test(challenge))) {
|
|
195
|
+
throw new Error("authenticationChallenges must contain safe non-empty challenge values.");
|
|
196
|
+
}
|
|
197
|
+
this.authenticationChallenges = authenticationChallenges
|
|
198
|
+
.map((value) => value.trim())
|
|
199
|
+
.join(", ");
|
|
200
|
+
this.limits = { ...JMAP_SERVER_LIMITS, ...options.limits };
|
|
201
|
+
for (const [name, value] of Object.entries(this.limits)) {
|
|
202
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
203
|
+
throw new Error(`JMAP limit ${name} must be a positive safe integer.`);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
this.maxConcurrentUploadServer = options.maxConcurrentUploadServer ??
|
|
207
|
+
this.limits.maxConcurrentUpload;
|
|
208
|
+
if (!Number.isSafeInteger(this.maxConcurrentUploadServer) ||
|
|
209
|
+
this.maxConcurrentUploadServer < this.limits.maxConcurrentUpload) {
|
|
210
|
+
throw new Error("maxConcurrentUploadServer must be a safe integer at least as large as maxConcurrentUpload.");
|
|
211
|
+
}
|
|
29
212
|
}
|
|
30
213
|
// ======================
|
|
31
|
-
//
|
|
214
|
+
// default auth registry
|
|
32
215
|
// ======================
|
|
216
|
+
/**
|
|
217
|
+
* Registers Basic credentials in the default authenticator's registry.
|
|
218
|
+
* Only consulted when no custom `authenticate` option is set. Account data
|
|
219
|
+
* itself lives in the backend (the memory backend auto-creates accounts).
|
|
220
|
+
*/
|
|
33
221
|
addUser(username, password) {
|
|
34
|
-
if (this.
|
|
222
|
+
if (this.registry.has(username)) {
|
|
35
223
|
throw new Error(`User "${username}" already exists.`);
|
|
36
224
|
}
|
|
37
|
-
|
|
38
|
-
this.users.set(username, {
|
|
39
|
-
username,
|
|
40
|
-
password,
|
|
41
|
-
bearerTokens: new Set(),
|
|
42
|
-
accountId: `account_${username}`,
|
|
43
|
-
mailboxes: new Map(),
|
|
44
|
-
emails: new Map(),
|
|
45
|
-
blobs: new Map(),
|
|
46
|
-
submissions: new Map(),
|
|
47
|
-
identities: [{ id: 'identity_1', name: username, email, mayDelete: false }],
|
|
48
|
-
state: 0,
|
|
49
|
-
changes: [],
|
|
50
|
-
idCounter: 0,
|
|
51
|
-
});
|
|
225
|
+
this.registry.set(username, { password, bearerTokens: new Set() });
|
|
52
226
|
}
|
|
53
|
-
/** Registers a valid Bearer token for a user. */
|
|
227
|
+
/** Registers a valid Bearer token for a user in the default authenticator. */
|
|
54
228
|
addBearerToken(username, token) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
createMailbox(username, name, role) {
|
|
59
|
-
const user = this.requireUser(username);
|
|
60
|
-
for (const mailbox of user.mailboxes.values()) {
|
|
61
|
-
if (mailbox.name === name) {
|
|
62
|
-
throw new Error(`Mailbox "${name}" already exists for user "${username}".`);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const id = `mailbox_${++user.idCounter}`;
|
|
66
|
-
user.mailboxes.set(id, {
|
|
67
|
-
id,
|
|
68
|
-
name,
|
|
69
|
-
role: role ?? null,
|
|
70
|
-
parentId: null,
|
|
71
|
-
sortOrder: user.mailboxes.size,
|
|
72
|
-
});
|
|
73
|
-
return id;
|
|
74
|
-
}
|
|
75
|
-
/** Seeds an email into a user's mailbox; bumps state and pushes a StateChange. Returns the email id. */
|
|
76
|
-
addEmail(username, mailboxName, input) {
|
|
77
|
-
const user = this.requireUser(username);
|
|
78
|
-
const mailbox = Array.from(user.mailboxes.values()).find((candidate) => candidate.name === mailboxName || candidate.role === mailboxName);
|
|
79
|
-
if (!mailbox) {
|
|
80
|
-
throw new Error(`Mailbox "${mailboxName}" does not exist for user "${username}".`);
|
|
81
|
-
}
|
|
82
|
-
const from = Array.isArray(input.from) ? input.from : [input.from];
|
|
83
|
-
const to = Array.isArray(input.to) ? input.to : [input.to];
|
|
84
|
-
const id = `email_${++user.idCounter}`;
|
|
85
|
-
const receivedAt = input.receivedAt ?? new Date().toISOString();
|
|
86
|
-
const textBody = input.textBody ?? '';
|
|
87
|
-
// raw message blob for Email/get blobId + downloads
|
|
88
|
-
const blobId = `blob_${id}`;
|
|
89
|
-
const rawLines = [
|
|
90
|
-
`From: ${from.map((address) => address.email).join(', ')}`,
|
|
91
|
-
`To: ${to.map((address) => address.email).join(', ')}`,
|
|
92
|
-
`Subject: ${input.subject ?? ''}`,
|
|
93
|
-
`Date: ${receivedAt}`,
|
|
94
|
-
'',
|
|
95
|
-
textBody,
|
|
96
|
-
];
|
|
97
|
-
user.blobs.set(blobId, {
|
|
98
|
-
data: Buffer.from(rawLines.join('\r\n'), 'utf8'),
|
|
99
|
-
type: 'message/rfc822',
|
|
100
|
-
name: `${id}.eml`,
|
|
101
|
-
});
|
|
102
|
-
const bodyValues = {
|
|
103
|
-
text: { value: textBody, isTruncated: false },
|
|
104
|
-
};
|
|
105
|
-
const textBodyParts = [{ partId: 'text', type: 'text/plain', size: textBody.length }];
|
|
106
|
-
const htmlBodyParts = [];
|
|
107
|
-
if (typeof input.htmlBody === 'string') {
|
|
108
|
-
bodyValues.html = { value: input.htmlBody, isTruncated: false };
|
|
109
|
-
htmlBodyParts.push({ partId: 'html', type: 'text/html', size: input.htmlBody.length });
|
|
110
|
-
}
|
|
111
|
-
const attachmentParts = [];
|
|
112
|
-
for (const [index, attachment] of (input.attachments ?? []).entries()) {
|
|
113
|
-
const attachmentBlobId = `blob_${id}_att${index + 1}`;
|
|
114
|
-
const data = Buffer.from(attachment.content);
|
|
115
|
-
user.blobs.set(attachmentBlobId, {
|
|
116
|
-
data,
|
|
117
|
-
type: attachment.type,
|
|
118
|
-
name: attachment.name,
|
|
119
|
-
});
|
|
120
|
-
attachmentParts.push({
|
|
121
|
-
partId: null,
|
|
122
|
-
blobId: attachmentBlobId,
|
|
123
|
-
name: attachment.name,
|
|
124
|
-
type: attachment.type,
|
|
125
|
-
size: data.length,
|
|
126
|
-
disposition: 'attachment',
|
|
127
|
-
});
|
|
229
|
+
const entry = this.registry.get(username);
|
|
230
|
+
if (!entry) {
|
|
231
|
+
throw new Error(`User "${username}" does not exist.`);
|
|
128
232
|
}
|
|
129
|
-
|
|
130
|
-
id,
|
|
131
|
-
blobId,
|
|
132
|
-
threadId: `thread_${id}`,
|
|
133
|
-
mailboxIds: { [mailbox.id]: true },
|
|
134
|
-
keywords: input.keywords ?? {},
|
|
135
|
-
size: textBody.length,
|
|
136
|
-
receivedAt,
|
|
137
|
-
sentAt: receivedAt,
|
|
138
|
-
subject: input.subject ?? null,
|
|
139
|
-
from,
|
|
140
|
-
to,
|
|
141
|
-
cc: input.cc ?? null,
|
|
142
|
-
bcc: input.bcc ?? null,
|
|
143
|
-
replyTo: null,
|
|
144
|
-
hasAttachment: attachmentParts.length > 0,
|
|
145
|
-
preview: textBody.slice(0, 100),
|
|
146
|
-
bodyValues,
|
|
147
|
-
textBody: textBodyParts,
|
|
148
|
-
htmlBody: htmlBodyParts,
|
|
149
|
-
attachments: attachmentParts,
|
|
150
|
-
};
|
|
151
|
-
user.emails.set(id, email);
|
|
152
|
-
this.bumpState(user, { created: [id] });
|
|
153
|
-
return id;
|
|
233
|
+
entry.bearerTokens.add(token);
|
|
154
234
|
}
|
|
155
235
|
// ======================
|
|
156
|
-
// lifecycle
|
|
236
|
+
// lifecycle (node wrapper)
|
|
157
237
|
// ======================
|
|
158
|
-
/** Starts
|
|
238
|
+
/** Starts a node:http server around fetchHandler. Resolves with the bound port (pass 0 for ephemeral). */
|
|
159
239
|
start(port) {
|
|
240
|
+
if (this.httpServer) {
|
|
241
|
+
throw new Error("JmapServer is already started.");
|
|
242
|
+
}
|
|
243
|
+
this.stopping = false;
|
|
244
|
+
const server = plugins.http.createServer((req, res) => {
|
|
245
|
+
if (this.stopping) {
|
|
246
|
+
res.writeHead(503, {
|
|
247
|
+
"content-type": "application/problem+json",
|
|
248
|
+
"connection": "close",
|
|
249
|
+
});
|
|
250
|
+
res.end(JSON.stringify({
|
|
251
|
+
type: "about:blank",
|
|
252
|
+
status: 503,
|
|
253
|
+
detail: "JMAP server is shutting down.",
|
|
254
|
+
}));
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const requestAbortController = new AbortController();
|
|
258
|
+
this.nodeRequestControllers.add(requestAbortController);
|
|
259
|
+
let requestTask;
|
|
260
|
+
requestTask = this.handleNodeRequest(req, res, requestAbortController)
|
|
261
|
+
.finally(() => {
|
|
262
|
+
this.nodeRequestControllers.delete(requestAbortController);
|
|
263
|
+
this.activeNodeRequests.delete(requestTask);
|
|
264
|
+
});
|
|
265
|
+
this.activeNodeRequests.add(requestTask);
|
|
266
|
+
void requestTask;
|
|
267
|
+
});
|
|
268
|
+
const onConnection = (socket) => {
|
|
269
|
+
this.sockets.add(socket);
|
|
270
|
+
socket.on("close", () => {
|
|
271
|
+
this.sockets.delete(socket);
|
|
272
|
+
});
|
|
273
|
+
};
|
|
274
|
+
server.on("connection", onConnection);
|
|
275
|
+
this.httpServer = server;
|
|
160
276
|
return new Promise((resolve, reject) => {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
277
|
+
const onStartupError = (error) => {
|
|
278
|
+
server.off("listening", onListening);
|
|
279
|
+
server.off("connection", onConnection);
|
|
280
|
+
if (this.httpServer === server) {
|
|
281
|
+
this.httpServer = null;
|
|
282
|
+
}
|
|
283
|
+
try {
|
|
284
|
+
server.close(() => undefined);
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// The failed listener never reached the listening state.
|
|
288
|
+
}
|
|
289
|
+
reject(error);
|
|
290
|
+
};
|
|
291
|
+
const onListening = () => {
|
|
292
|
+
server.off("error", onStartupError);
|
|
293
|
+
server.on("error", (error) => {
|
|
294
|
+
this.cleanupErrors.push(error);
|
|
295
|
+
});
|
|
296
|
+
const address = server.address();
|
|
297
|
+
const boundPort = typeof address === "object" && address
|
|
298
|
+
? address.port
|
|
299
|
+
: port;
|
|
165
300
|
resolve(boundPort);
|
|
166
|
-
}
|
|
301
|
+
};
|
|
302
|
+
server.once("error", onStartupError);
|
|
303
|
+
server.once("listening", onListening);
|
|
304
|
+
server.listen(port);
|
|
167
305
|
});
|
|
168
306
|
}
|
|
169
|
-
/**
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
307
|
+
/**
|
|
308
|
+
* Stops the server: closes all event streams (clearing their ping timers
|
|
309
|
+
* and the backend change-feed subscription), destroys open connections,
|
|
310
|
+
* and closes the node listener when one was started.
|
|
311
|
+
*/
|
|
312
|
+
async stop() {
|
|
313
|
+
this.stopping = true;
|
|
314
|
+
const server = this.httpServer;
|
|
315
|
+
this.httpServer = null;
|
|
316
|
+
const listenerClosed = server
|
|
317
|
+
? new Promise((resolve) => {
|
|
318
|
+
try {
|
|
319
|
+
server.close(() => resolve());
|
|
320
|
+
}
|
|
321
|
+
catch {
|
|
322
|
+
resolve();
|
|
323
|
+
}
|
|
324
|
+
})
|
|
325
|
+
: Promise.resolve();
|
|
326
|
+
for (const stream of Array.from(this.eventStreams)) {
|
|
327
|
+
this.closeStream(stream);
|
|
328
|
+
}
|
|
329
|
+
for (const controller of this.nodeRequestControllers) {
|
|
330
|
+
if (!controller.signal.aborted) {
|
|
331
|
+
controller.abort(new Error("JMAP server is shutting down."));
|
|
177
332
|
}
|
|
178
333
|
}
|
|
179
|
-
this.eventStreams.clear();
|
|
180
334
|
for (const socket of this.sockets) {
|
|
181
335
|
socket.destroy();
|
|
182
336
|
}
|
|
183
337
|
this.sockets.clear();
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
338
|
+
await listenerClosed;
|
|
339
|
+
while (this.activeNodeRequests.size) {
|
|
340
|
+
await Promise.allSettled([...this.activeNodeRequests]);
|
|
341
|
+
}
|
|
342
|
+
if (this.cleanupErrors.length) {
|
|
343
|
+
const errors = this.cleanupErrors.splice(0);
|
|
344
|
+
throw new AggregateError(errors, "JmapServer cleanup failed");
|
|
345
|
+
}
|
|
189
346
|
}
|
|
190
347
|
// ======================
|
|
191
|
-
//
|
|
348
|
+
// web-standard core
|
|
192
349
|
// ======================
|
|
193
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Handles a JMAP request end to end and returns the Response. This is the
|
|
352
|
+
* runtime-agnostic core — mount it directly as a Deno/Bun fetch handler.
|
|
353
|
+
*/
|
|
354
|
+
async fetchHandler(request) {
|
|
194
355
|
try {
|
|
195
|
-
const
|
|
196
|
-
if (!
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
356
|
+
const principal = await this.authenticatePrincipal(request);
|
|
357
|
+
if (!principal) {
|
|
358
|
+
await this.cancelRequestBody(request, "authentication rejected");
|
|
359
|
+
return this.problemResponse(401, "about:blank", "Authentication required", {
|
|
360
|
+
"www-authenticate": this.authenticationChallenges,
|
|
200
361
|
});
|
|
201
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 401, detail: 'Authentication required' }));
|
|
202
|
-
return;
|
|
203
362
|
}
|
|
204
|
-
const
|
|
363
|
+
const account = await this.backend.resolveAccount(principal);
|
|
364
|
+
if (!account) {
|
|
365
|
+
await this.cancelRequestBody(request, "account rejected");
|
|
366
|
+
return this.problemResponse(403, "about:blank", "No account for this principal");
|
|
367
|
+
}
|
|
368
|
+
const url = new URL(request.url);
|
|
205
369
|
const pathname = url.pathname;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
370
|
+
const method = request.method.toUpperCase();
|
|
371
|
+
if (method === "GET" &&
|
|
372
|
+
(pathname === "/.well-known/jmap" || pathname === "/jmap/session")) {
|
|
373
|
+
return this.handleSession(account, principal);
|
|
209
374
|
}
|
|
210
|
-
if (
|
|
211
|
-
|
|
212
|
-
req.on('data', (chunk) => {
|
|
213
|
-
body += chunk;
|
|
214
|
-
});
|
|
215
|
-
req.on('end', () => {
|
|
216
|
-
this.handleApi(user, body, res);
|
|
217
|
-
});
|
|
218
|
-
return;
|
|
375
|
+
if (method === "POST" && pathname === "/jmap/api") {
|
|
376
|
+
return this.handleApi(account, request);
|
|
219
377
|
}
|
|
220
|
-
if (
|
|
221
|
-
this.
|
|
222
|
-
return;
|
|
378
|
+
if (method === "POST" && pathname.startsWith("/jmap/upload/")) {
|
|
379
|
+
return this.handleUpload(account, principal, pathname, request);
|
|
223
380
|
}
|
|
224
|
-
if (
|
|
225
|
-
this.handleDownload(
|
|
226
|
-
return;
|
|
381
|
+
if (method === "GET" && pathname.startsWith("/jmap/download/")) {
|
|
382
|
+
return this.handleDownload(account, pathname, url);
|
|
227
383
|
}
|
|
228
|
-
|
|
229
|
-
|
|
384
|
+
if (method === "GET" && pathname === "/jmap/eventsource") {
|
|
385
|
+
return this.handleEventSource(account, url);
|
|
386
|
+
}
|
|
387
|
+
await this.cancelRequestBody(request, "route rejected");
|
|
388
|
+
return this.problemResponse(404, "about:blank", "Not found");
|
|
230
389
|
}
|
|
231
390
|
catch (error) {
|
|
232
391
|
const message = error instanceof Error ? error.message : String(error);
|
|
233
|
-
|
|
234
|
-
res.writeHead(500, { 'content-type': 'application/problem+json' });
|
|
235
|
-
}
|
|
236
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 500, detail: message }));
|
|
392
|
+
return this.problemResponse(500, "about:blank", message);
|
|
237
393
|
}
|
|
238
394
|
}
|
|
239
|
-
|
|
240
|
-
|
|
395
|
+
// ======================
|
|
396
|
+
// authentication
|
|
397
|
+
// ======================
|
|
398
|
+
async authenticatePrincipal(request) {
|
|
399
|
+
if (this.options.authenticate) {
|
|
400
|
+
return this.options.authenticate(request);
|
|
401
|
+
}
|
|
402
|
+
const header = request.headers.get("authorization");
|
|
241
403
|
if (!header) {
|
|
242
404
|
return null;
|
|
243
405
|
}
|
|
244
|
-
const spaceIndex = header.indexOf(
|
|
406
|
+
const spaceIndex = header.indexOf(" ");
|
|
245
407
|
if (spaceIndex === -1) {
|
|
246
408
|
return null;
|
|
247
409
|
}
|
|
248
410
|
const scheme = header.slice(0, spaceIndex).toLowerCase();
|
|
249
411
|
const value = header.slice(spaceIndex + 1).trim();
|
|
250
|
-
if (scheme ===
|
|
251
|
-
for (const
|
|
252
|
-
if (
|
|
253
|
-
return
|
|
412
|
+
if (scheme === "bearer") {
|
|
413
|
+
for (const [username, entry] of this.registry) {
|
|
414
|
+
if (entry.bearerTokens.has(value)) {
|
|
415
|
+
return { username };
|
|
254
416
|
}
|
|
255
417
|
}
|
|
256
418
|
return null;
|
|
257
419
|
}
|
|
258
|
-
if (scheme ===
|
|
259
|
-
|
|
260
|
-
|
|
420
|
+
if (scheme === "basic") {
|
|
421
|
+
let decoded;
|
|
422
|
+
try {
|
|
423
|
+
const binary = atob(value);
|
|
424
|
+
decoded = new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
|
|
425
|
+
}
|
|
426
|
+
catch {
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
const colonIndex = decoded.indexOf(":");
|
|
261
430
|
if (colonIndex === -1) {
|
|
262
431
|
return null;
|
|
263
432
|
}
|
|
264
433
|
const username = decoded.slice(0, colonIndex);
|
|
265
434
|
const password = decoded.slice(colonIndex + 1);
|
|
266
|
-
const
|
|
267
|
-
if (
|
|
268
|
-
return
|
|
435
|
+
const entry = this.registry.get(username);
|
|
436
|
+
if (entry && entry.password === password) {
|
|
437
|
+
return { username };
|
|
269
438
|
}
|
|
270
439
|
return null;
|
|
271
440
|
}
|
|
272
441
|
return null;
|
|
273
442
|
}
|
|
274
|
-
|
|
443
|
+
// ======================
|
|
444
|
+
// session
|
|
445
|
+
// ======================
|
|
446
|
+
handleSession(account, principal) {
|
|
275
447
|
const session = {
|
|
276
448
|
capabilities: {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
maxSizeRequest: 10_000_000,
|
|
281
|
-
maxConcurrentRequests: 4,
|
|
282
|
-
maxCallsInRequest: 16,
|
|
283
|
-
maxObjectsInGet: 500,
|
|
284
|
-
maxObjectsInSet: 500,
|
|
285
|
-
collationAlgorithms: ['i;ascii-numeric', 'i;ascii-casemap'],
|
|
449
|
+
[JMAP_CORE_CAPABILITY]: {
|
|
450
|
+
...this.limits,
|
|
451
|
+
collationAlgorithms: ["i;ascii-casemap"],
|
|
286
452
|
},
|
|
287
|
-
|
|
288
|
-
|
|
453
|
+
[JMAP_MAIL_CAPABILITY]: {},
|
|
454
|
+
[JMAP_SUBMISSION_CAPABILITY]: {},
|
|
289
455
|
},
|
|
290
456
|
accounts: {
|
|
291
|
-
[
|
|
292
|
-
name:
|
|
293
|
-
isPersonal: true,
|
|
294
|
-
isReadOnly: false,
|
|
457
|
+
[account.accountId]: {
|
|
458
|
+
name: account.name,
|
|
459
|
+
isPersonal: account.isPersonal ?? true,
|
|
460
|
+
isReadOnly: account.isReadOnly ?? false,
|
|
295
461
|
accountCapabilities: {
|
|
296
|
-
|
|
297
|
-
|
|
462
|
+
[JMAP_MAIL_CAPABILITY]: {
|
|
463
|
+
maxMailboxesPerEmail: null,
|
|
464
|
+
maxMailboxDepth: null,
|
|
465
|
+
maxSizeMailboxName: 490,
|
|
466
|
+
maxSizeAttachmentsPerEmail: this.limits.maxSizeUpload,
|
|
467
|
+
emailQuerySortOptions: ["receivedAt"],
|
|
468
|
+
mayCreateTopLevelMailbox: false,
|
|
469
|
+
},
|
|
470
|
+
[JMAP_SUBMISSION_CAPABILITY]: {
|
|
471
|
+
maxDelayedSend: 0,
|
|
472
|
+
submissionExtensions: {},
|
|
473
|
+
},
|
|
298
474
|
},
|
|
299
475
|
},
|
|
300
476
|
},
|
|
301
477
|
primaryAccounts: {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
478
|
+
[JMAP_CORE_CAPABILITY]: account.accountId,
|
|
479
|
+
[JMAP_MAIL_CAPABILITY]: account.accountId,
|
|
480
|
+
[JMAP_SUBMISSION_CAPABILITY]: account.accountId,
|
|
305
481
|
},
|
|
306
|
-
username:
|
|
307
|
-
apiUrl:
|
|
308
|
-
downloadUrl:
|
|
309
|
-
uploadUrl:
|
|
310
|
-
eventSourceUrl:
|
|
311
|
-
state:
|
|
482
|
+
username: principal.username,
|
|
483
|
+
apiUrl: this.buildUrl("/jmap/api"),
|
|
484
|
+
downloadUrl: this.buildUrl("/jmap/download/{accountId}/{blobId}/{name}?type={type}"),
|
|
485
|
+
uploadUrl: this.buildUrl("/jmap/upload/{accountId}"),
|
|
486
|
+
eventSourceUrl: this.buildUrl("/jmap/eventsource?types={types}&closeafter={closeafter}&ping={ping}"),
|
|
487
|
+
state: SESSION_STATE,
|
|
312
488
|
};
|
|
313
|
-
|
|
314
|
-
res.end(JSON.stringify(session));
|
|
489
|
+
return this.jsonResponse(200, session);
|
|
315
490
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
}));
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
330
|
-
if (!Array.isArray(parsed?.methodCalls)) {
|
|
331
|
-
res.writeHead(400, { 'content-type': 'application/problem+json' });
|
|
332
|
-
res.end(JSON.stringify({
|
|
333
|
-
type: 'urn:ietf:params:jmap:error:notRequest',
|
|
334
|
-
status: 400,
|
|
335
|
-
detail: 'The request body is not a valid JMAP request object.',
|
|
336
|
-
}));
|
|
337
|
-
return;
|
|
491
|
+
buildUrl(path) {
|
|
492
|
+
const base = this.options.baseUrl;
|
|
493
|
+
return base ? `${base.replace(/\/+$/, "")}${path}` : path;
|
|
494
|
+
}
|
|
495
|
+
// ======================
|
|
496
|
+
// api endpoint
|
|
497
|
+
// ======================
|
|
498
|
+
async handleApi(account, request) {
|
|
499
|
+
if (this.activeApiRequests >= this.limits.maxConcurrentRequests) {
|
|
500
|
+
await this.cancelRequestBody(request, "request concurrency limit reached");
|
|
501
|
+
return this.limitResponse(429, "maxConcurrentRequests", "Too many concurrent requests.");
|
|
338
502
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
const [methodName, args, callId] = call;
|
|
503
|
+
this.activeApiRequests++;
|
|
504
|
+
try {
|
|
505
|
+
let bytes;
|
|
343
506
|
try {
|
|
344
|
-
|
|
345
|
-
methodResponses.push([methodName, result, callId]);
|
|
507
|
+
bytes = await this.readRequestBodyBounded(request, this.limits.maxSizeRequest);
|
|
346
508
|
}
|
|
347
509
|
catch (error) {
|
|
348
|
-
if (error instanceof
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
510
|
+
if (error instanceof JmapRequestBodyError) {
|
|
511
|
+
if (error.reason === "invalidLength") {
|
|
512
|
+
return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
|
|
513
|
+
}
|
|
514
|
+
return this.limitResponse(400, "maxSizeRequest", `The request is larger than ${this.limits.maxSizeRequest} bytes.`);
|
|
515
|
+
}
|
|
516
|
+
throw error;
|
|
517
|
+
}
|
|
518
|
+
let parsed;
|
|
519
|
+
try {
|
|
520
|
+
parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
521
|
+
}
|
|
522
|
+
catch {
|
|
523
|
+
return this.problemResponse(400, "urn:ietf:params:jmap:error:notJSON", "The request body is not valid JSON.");
|
|
524
|
+
}
|
|
525
|
+
if (!parsed ||
|
|
526
|
+
typeof parsed !== "object" ||
|
|
527
|
+
!Array.isArray(parsed.using) ||
|
|
528
|
+
!Array.isArray(parsed.methodCalls)) {
|
|
529
|
+
return this.problemResponse(400, "urn:ietf:params:jmap:error:notRequest", "The request body is not a valid JMAP request object.");
|
|
530
|
+
}
|
|
531
|
+
const knownCapabilities = new Set([
|
|
532
|
+
JMAP_CORE_CAPABILITY,
|
|
533
|
+
JMAP_MAIL_CAPABILITY,
|
|
534
|
+
JMAP_SUBMISSION_CAPABILITY,
|
|
535
|
+
]);
|
|
536
|
+
const using = new Set(parsed.using);
|
|
537
|
+
for (const capability of using) {
|
|
538
|
+
if (!knownCapabilities.has(capability)) {
|
|
539
|
+
return this.problemResponse(400, "urn:ietf:params:jmap:error:unknownCapability", `The capability "${capability}" is not supported by this server.`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (parsed.methodCalls.length > this.limits.maxCallsInRequest) {
|
|
543
|
+
return this.limitResponse(400, "maxCallsInRequest", `The request has more than ${this.limits.maxCallsInRequest} method calls.`);
|
|
544
|
+
}
|
|
545
|
+
const createdIds = new Map(Object.entries((parsed.createdIds ?? {})));
|
|
546
|
+
const methodResponses = [];
|
|
547
|
+
let mutated = false;
|
|
548
|
+
for (const call of parsed.methodCalls) {
|
|
549
|
+
if (!Array.isArray(call) || typeof call[0] !== "string" ||
|
|
550
|
+
typeof call[2] !== "string") {
|
|
551
|
+
return this.problemResponse(400, "urn:ietf:params:jmap:error:notRequest", "Each method call must be a [name, arguments, callId] tuple.");
|
|
552
|
+
}
|
|
553
|
+
const [methodName, rawArgs, callId] = call;
|
|
554
|
+
try {
|
|
555
|
+
const args = this.resolveBackReferences(rawArgs ?? {}, methodResponses);
|
|
556
|
+
const results = await this.dispatchMethod(account, methodName, args, using, createdIds);
|
|
557
|
+
for (const entry of results) {
|
|
558
|
+
methodResponses.push([entry.name, entry.result, callId]);
|
|
559
|
+
if (entry.mutated) {
|
|
560
|
+
mutated = true;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
354
563
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
564
|
+
catch (error) {
|
|
565
|
+
if (error instanceof JmapServerMethodError) {
|
|
566
|
+
methodResponses.push([
|
|
567
|
+
"error",
|
|
568
|
+
{ type: error.type, description: error.message },
|
|
569
|
+
callId,
|
|
570
|
+
]);
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
const message = error instanceof Error
|
|
574
|
+
? error.message
|
|
575
|
+
: String(error);
|
|
576
|
+
methodResponses.push(["error", {
|
|
577
|
+
type: "serverFail",
|
|
578
|
+
description: message,
|
|
579
|
+
}, callId]);
|
|
580
|
+
}
|
|
358
581
|
}
|
|
359
582
|
}
|
|
583
|
+
if (mutated) {
|
|
584
|
+
await this.pushAfterMutation(account);
|
|
585
|
+
}
|
|
586
|
+
const responseBody = {
|
|
587
|
+
methodResponses,
|
|
588
|
+
sessionState: SESSION_STATE,
|
|
589
|
+
};
|
|
590
|
+
if (parsed.createdIds !== undefined) {
|
|
591
|
+
responseBody.createdIds = Object.fromEntries(createdIds);
|
|
592
|
+
}
|
|
593
|
+
return this.jsonResponse(200, responseBody);
|
|
360
594
|
}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
handleEventSource(user, req, res) {
|
|
365
|
-
res.writeHead(200, {
|
|
366
|
-
'content-type': 'text/event-stream',
|
|
367
|
-
'cache-control': 'no-cache',
|
|
368
|
-
connection: 'keep-alive',
|
|
369
|
-
});
|
|
370
|
-
res.write(': jmap event stream\n\n');
|
|
371
|
-
this.eventStreams.set(res, user);
|
|
372
|
-
req.on('close', () => {
|
|
373
|
-
this.eventStreams.delete(res);
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
handleDownload(user, pathname, url, res) {
|
|
377
|
-
// /jmap/download/{accountId}/{blobId}/{name}
|
|
378
|
-
const segments = pathname.split('/').filter((segment) => segment.length > 0);
|
|
379
|
-
const accountId = decodeURIComponent(segments[2] ?? '');
|
|
380
|
-
const blobId = decodeURIComponent(segments[3] ?? '');
|
|
381
|
-
if (accountId !== user.accountId) {
|
|
382
|
-
res.writeHead(404, { 'content-type': 'application/problem+json' });
|
|
383
|
-
res.end(JSON.stringify({ type: 'about:blank', status: 404, detail: 'Unknown account' }));
|
|
384
|
-
return;
|
|
595
|
+
finally {
|
|
596
|
+
this.activeApiRequests--;
|
|
385
597
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Resolves `#argument` ResultReference objects (RFC 8620 §3.7) against the
|
|
601
|
+
* responses of earlier method calls in the same request.
|
|
602
|
+
*/
|
|
603
|
+
resolveBackReferences(args, priorResponses) {
|
|
604
|
+
const resolved = {};
|
|
605
|
+
for (const [key, value] of Object.entries(args)) {
|
|
606
|
+
if (!key.startsWith("#")) {
|
|
607
|
+
resolved[key] = value;
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
const name = key.slice(1);
|
|
611
|
+
if (name in args) {
|
|
612
|
+
throw new JmapServerMethodError("invalidArguments", `The arguments contain both "${name}" and "#${name}".`);
|
|
613
|
+
}
|
|
614
|
+
if (!value ||
|
|
615
|
+
typeof value !== "object" ||
|
|
616
|
+
typeof value.resultOf !== "string" ||
|
|
617
|
+
typeof value.name !== "string" ||
|
|
618
|
+
typeof value.path !== "string") {
|
|
619
|
+
throw new JmapServerMethodError("invalidResultReference", `"#${name}" is not a valid ResultReference object.`);
|
|
620
|
+
}
|
|
621
|
+
const source = priorResponses.find((entry) => entry[2] === value.resultOf && entry[0] === value.name);
|
|
622
|
+
if (!source) {
|
|
623
|
+
throw new JmapServerMethodError("invalidResultReference", `No response found for resultOf "${value.resultOf}" and name "${value.name}".`);
|
|
624
|
+
}
|
|
625
|
+
try {
|
|
626
|
+
resolved[name] = evalJsonPointer(source[1], value.path);
|
|
627
|
+
}
|
|
628
|
+
catch (error) {
|
|
629
|
+
throw new JmapServerMethodError("invalidResultReference", error instanceof Error ? error.message : String(error));
|
|
630
|
+
}
|
|
391
631
|
}
|
|
392
|
-
|
|
393
|
-
res.writeHead(200, { 'content-type': type, 'content-length': blob.data.length });
|
|
394
|
-
res.end(blob.data);
|
|
632
|
+
return resolved;
|
|
395
633
|
}
|
|
396
634
|
// ======================
|
|
397
|
-
//
|
|
635
|
+
// method dispatch
|
|
398
636
|
// ======================
|
|
399
|
-
dispatchMethod(
|
|
637
|
+
async dispatchMethod(account, methodName, args, using, createdIds) {
|
|
638
|
+
const requiredCapability = {
|
|
639
|
+
"Core/echo": JMAP_CORE_CAPABILITY,
|
|
640
|
+
"Mailbox/get": JMAP_MAIL_CAPABILITY,
|
|
641
|
+
"Mailbox/query": JMAP_MAIL_CAPABILITY,
|
|
642
|
+
"Mailbox/changes": JMAP_MAIL_CAPABILITY,
|
|
643
|
+
"Thread/get": JMAP_MAIL_CAPABILITY,
|
|
644
|
+
"Email/get": JMAP_MAIL_CAPABILITY,
|
|
645
|
+
"Email/query": JMAP_MAIL_CAPABILITY,
|
|
646
|
+
"Email/changes": JMAP_MAIL_CAPABILITY,
|
|
647
|
+
"Email/queryChanges": JMAP_MAIL_CAPABILITY,
|
|
648
|
+
"Email/set": JMAP_MAIL_CAPABILITY,
|
|
649
|
+
"Identity/get": JMAP_SUBMISSION_CAPABILITY,
|
|
650
|
+
"EmailSubmission/set": JMAP_SUBMISSION_CAPABILITY,
|
|
651
|
+
};
|
|
652
|
+
const capability = requiredCapability[methodName];
|
|
653
|
+
if (!capability) {
|
|
654
|
+
throw new JmapServerMethodError("unknownMethod", `Unknown method "${methodName}".`);
|
|
655
|
+
}
|
|
656
|
+
if (!using.has(capability)) {
|
|
657
|
+
throw new JmapServerMethodError("unknownMethod", `Method "${methodName}" requires the capability "${capability}" in "using".`);
|
|
658
|
+
}
|
|
659
|
+
if (methodName !== "Core/echo") {
|
|
660
|
+
this.requireAccountId(account, args);
|
|
661
|
+
}
|
|
400
662
|
switch (methodName) {
|
|
401
|
-
case
|
|
402
|
-
return args;
|
|
403
|
-
case
|
|
404
|
-
return
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
case
|
|
414
|
-
return
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
663
|
+
case "Core/echo":
|
|
664
|
+
return [{ name: methodName, result: args }];
|
|
665
|
+
case "Mailbox/get":
|
|
666
|
+
return [{
|
|
667
|
+
name: methodName,
|
|
668
|
+
result: await this.methodMailboxGet(account, args),
|
|
669
|
+
}];
|
|
670
|
+
case "Mailbox/query":
|
|
671
|
+
return [{
|
|
672
|
+
name: methodName,
|
|
673
|
+
result: await this.methodMailboxQuery(account, args),
|
|
674
|
+
}];
|
|
675
|
+
case "Mailbox/changes":
|
|
676
|
+
return [{
|
|
677
|
+
name: methodName,
|
|
678
|
+
result: await this.methodMailboxChanges(account, args),
|
|
679
|
+
}];
|
|
680
|
+
case "Thread/get":
|
|
681
|
+
return [{
|
|
682
|
+
name: methodName,
|
|
683
|
+
result: await this.methodThreadGet(account, args),
|
|
684
|
+
}];
|
|
685
|
+
case "Email/get":
|
|
686
|
+
return [{
|
|
687
|
+
name: methodName,
|
|
688
|
+
result: await this.methodEmailGet(account, args),
|
|
689
|
+
}];
|
|
690
|
+
case "Email/query":
|
|
691
|
+
return [{
|
|
692
|
+
name: methodName,
|
|
693
|
+
result: await this.methodEmailQuery(account, args),
|
|
694
|
+
}];
|
|
695
|
+
case "Email/changes":
|
|
696
|
+
return [{
|
|
697
|
+
name: methodName,
|
|
698
|
+
result: await this.methodEmailChanges(account, args),
|
|
699
|
+
}];
|
|
700
|
+
case "Email/queryChanges":
|
|
701
|
+
// Explicitly unsupported in phase 1: clients fall back to Email/query.
|
|
702
|
+
throw new JmapServerMethodError("cannotCalculateChanges", "Email/queryChanges is not supported; re-run the query instead.");
|
|
703
|
+
case "Email/set": {
|
|
704
|
+
const result = await this.methodEmailSet(account, args, createdIds);
|
|
705
|
+
return [{
|
|
706
|
+
name: methodName,
|
|
707
|
+
result,
|
|
708
|
+
mutated: result.newState !== result.oldState,
|
|
709
|
+
}];
|
|
710
|
+
}
|
|
711
|
+
case "Identity/get":
|
|
712
|
+
return [{
|
|
713
|
+
name: methodName,
|
|
714
|
+
result: await this.methodIdentityGet(account, args),
|
|
715
|
+
}];
|
|
716
|
+
case "EmailSubmission/set":
|
|
717
|
+
return this.methodEmailSubmissionSet(account, args, createdIds);
|
|
419
718
|
default:
|
|
420
|
-
throw new JmapServerMethodError(
|
|
719
|
+
throw new JmapServerMethodError("unknownMethod", `Unknown method "${methodName}".`);
|
|
421
720
|
}
|
|
422
721
|
}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
const notFound = [];
|
|
427
|
-
if (args.ids == null) {
|
|
428
|
-
list = all;
|
|
722
|
+
requireAccountId(account, args) {
|
|
723
|
+
if (typeof args.accountId !== "string") {
|
|
724
|
+
throw new JmapServerMethodError("invalidArguments", "accountId is required.");
|
|
429
725
|
}
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
726
|
+
if (args.accountId !== account.accountId) {
|
|
727
|
+
throw new JmapServerMethodError("accountNotFound", `Account "${args.accountId}" is not accessible with these credentials.`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
// ======================
|
|
731
|
+
// mailbox methods
|
|
732
|
+
// ======================
|
|
733
|
+
async methodMailboxGet(account, args) {
|
|
734
|
+
let ids = null;
|
|
735
|
+
if (args.ids !== null && args.ids !== undefined) {
|
|
736
|
+
if (!Array.isArray(args.ids)) {
|
|
737
|
+
throw new JmapServerMethodError("invalidArguments", "ids must be an array of ids or null.");
|
|
738
|
+
}
|
|
739
|
+
if (args.ids.length > this.limits.maxObjectsInGet) {
|
|
740
|
+
throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
|
|
440
741
|
}
|
|
742
|
+
ids = args.ids;
|
|
441
743
|
}
|
|
442
|
-
const
|
|
443
|
-
|
|
444
|
-
|
|
744
|
+
const properties = this.validateProperties(args.properties, KNOWN_MAILBOX_PROPERTIES);
|
|
745
|
+
const result = await this.backend.getMailboxes(account.accountId, ids);
|
|
746
|
+
const list = result.list.map((mailbox) => {
|
|
747
|
+
const full = {
|
|
445
748
|
...mailbox,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
totalThreads: emails.length,
|
|
449
|
-
unreadThreads: emails.filter((email) => !email.keywords?.$seen).length,
|
|
450
|
-
myRights: {
|
|
451
|
-
mayReadItems: true,
|
|
452
|
-
mayAddItems: true,
|
|
453
|
-
mayRemoveItems: true,
|
|
454
|
-
maySetSeen: true,
|
|
455
|
-
maySetKeywords: true,
|
|
456
|
-
mayCreateChild: true,
|
|
457
|
-
mayRename: true,
|
|
458
|
-
mayDelete: true,
|
|
459
|
-
maySubmit: true,
|
|
460
|
-
},
|
|
461
|
-
isSubscribed: true,
|
|
749
|
+
isSubscribed: mailbox.isSubscribed ?? true,
|
|
750
|
+
myRights: mailbox.myRights ?? { ...DEFAULT_MAILBOX_RIGHTS },
|
|
462
751
|
};
|
|
752
|
+
return this.projectObject(full, properties ?? MAILBOX_PROPERTIES);
|
|
463
753
|
});
|
|
464
754
|
return {
|
|
465
|
-
accountId:
|
|
466
|
-
state:
|
|
467
|
-
list
|
|
468
|
-
notFound,
|
|
755
|
+
accountId: account.accountId,
|
|
756
|
+
state: result.state,
|
|
757
|
+
list,
|
|
758
|
+
notFound: result.notFound,
|
|
469
759
|
};
|
|
470
760
|
}
|
|
471
|
-
methodMailboxQuery(
|
|
472
|
-
const filter = args.filter ?? {};
|
|
473
|
-
|
|
474
|
-
|
|
761
|
+
async methodMailboxQuery(account, args) {
|
|
762
|
+
const filter = (args.filter ?? {});
|
|
763
|
+
if ("operator" in filter) {
|
|
764
|
+
throw new JmapServerMethodError("unsupportedFilter", "FilterOperator is not supported for Mailbox/query.");
|
|
765
|
+
}
|
|
766
|
+
for (const key of Object.keys(filter)) {
|
|
767
|
+
if (!["role", "name", "parentId"].includes(key)) {
|
|
768
|
+
throw new JmapServerMethodError("unsupportedFilter", `Mailbox filter condition "${key}" is not supported.`);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
for (const comparator of (args.sort ?? [])) {
|
|
772
|
+
if (!["name", "sortOrder"].includes(comparator.property)) {
|
|
773
|
+
throw new JmapServerMethodError("unsupportedSort", `Mailbox sort property "${comparator.property}" is not supported.`);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
const result = await this.backend.getMailboxes(account.accountId, null);
|
|
777
|
+
let mailboxes = result.list;
|
|
778
|
+
if (typeof filter.role === "string") {
|
|
475
779
|
mailboxes = mailboxes.filter((mailbox) => mailbox.role === filter.role);
|
|
476
780
|
}
|
|
477
|
-
if (typeof filter.name ===
|
|
781
|
+
if (typeof filter.name === "string") {
|
|
478
782
|
mailboxes = mailboxes.filter((mailbox) => mailbox.name === filter.name);
|
|
479
783
|
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
784
|
+
if ("parentId" in filter) {
|
|
785
|
+
mailboxes = mailboxes.filter((mailbox) => mailbox.parentId === filter.parentId);
|
|
786
|
+
}
|
|
787
|
+
const comparators = (args.sort ?? []);
|
|
788
|
+
if (comparators.length) {
|
|
789
|
+
mailboxes = [...mailboxes].sort((a, b) => {
|
|
790
|
+
for (const comparator of comparators) {
|
|
791
|
+
const direction = comparator.isAscending === false ? -1 : 1;
|
|
792
|
+
const property = comparator.property;
|
|
793
|
+
const left = a[property] ?? 0;
|
|
794
|
+
const right = b[property] ?? 0;
|
|
795
|
+
if (left < right) {
|
|
796
|
+
return -direction;
|
|
797
|
+
}
|
|
798
|
+
if (left > right) {
|
|
799
|
+
return direction;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return 0;
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
const position = this.validatePosition(args);
|
|
806
|
+
let ids = mailboxes.map((mailbox) => mailbox.id).slice(position);
|
|
807
|
+
if (typeof args.limit === "number") {
|
|
808
|
+
ids = ids.slice(0, args.limit);
|
|
809
|
+
}
|
|
810
|
+
const response = {
|
|
811
|
+
accountId: account.accountId,
|
|
812
|
+
queryState: result.state,
|
|
484
813
|
canCalculateChanges: false,
|
|
485
|
-
position
|
|
814
|
+
position,
|
|
486
815
|
ids,
|
|
487
|
-
total: ids.length,
|
|
488
816
|
};
|
|
817
|
+
if (args.calculateTotal === true) {
|
|
818
|
+
response.total = mailboxes.length;
|
|
819
|
+
}
|
|
820
|
+
return response;
|
|
821
|
+
}
|
|
822
|
+
async methodMailboxChanges(account, args) {
|
|
823
|
+
const { sinceState, maxChanges } = this.validateChangesArgs(args);
|
|
824
|
+
const changes = await this.backend.getMailboxChanges(account.accountId, sinceState, maxChanges);
|
|
825
|
+
if (!changes) {
|
|
826
|
+
throw new JmapServerMethodError("cannotCalculateChanges", `Cannot calculate mailbox changes since state "${sinceState}".`);
|
|
827
|
+
}
|
|
828
|
+
return { accountId: account.accountId, ...changes };
|
|
489
829
|
}
|
|
490
|
-
|
|
830
|
+
// ======================
|
|
831
|
+
// thread methods
|
|
832
|
+
// ======================
|
|
833
|
+
async methodThreadGet(account, args) {
|
|
491
834
|
if (!Array.isArray(args.ids)) {
|
|
492
|
-
throw new JmapServerMethodError(
|
|
835
|
+
throw new JmapServerMethodError("invalidArguments", "Thread/get requires an ids array.");
|
|
493
836
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
for (const id of args.ids) {
|
|
497
|
-
const email = user.emails.get(id);
|
|
498
|
-
if (email) {
|
|
499
|
-
// Returned as a full superset of the requestable properties;
|
|
500
|
-
// property projection is intentionally not implemented.
|
|
501
|
-
list.push({ ...email });
|
|
502
|
-
}
|
|
503
|
-
else {
|
|
504
|
-
notFound.push(id);
|
|
505
|
-
}
|
|
837
|
+
if (args.ids.length > this.limits.maxObjectsInGet) {
|
|
838
|
+
throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
|
|
506
839
|
}
|
|
840
|
+
// Result-reference chains like Email/get -> /list/*/threadId commonly
|
|
841
|
+
// contain duplicates; deduplicate so each thread is returned once.
|
|
842
|
+
const ids = Array.from(new Set(args.ids));
|
|
843
|
+
const result = await this.backend.getThreads(account.accountId, ids);
|
|
507
844
|
return {
|
|
508
|
-
accountId:
|
|
509
|
-
state:
|
|
510
|
-
list,
|
|
511
|
-
notFound,
|
|
845
|
+
accountId: account.accountId,
|
|
846
|
+
state: result.state,
|
|
847
|
+
list: result.list,
|
|
848
|
+
notFound: result.notFound,
|
|
512
849
|
};
|
|
513
850
|
}
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
emails = emails.filter((email) => String(email.subject ?? '').toLowerCase().includes(filter.subject.toLowerCase()));
|
|
522
|
-
}
|
|
523
|
-
if (typeof filter.text === 'string') {
|
|
524
|
-
const needle = filter.text.toLowerCase();
|
|
525
|
-
emails = emails.filter((email) => String(email.subject ?? '').toLowerCase().includes(needle) ||
|
|
526
|
-
String(email.bodyValues?.text?.value ?? '').toLowerCase().includes(needle));
|
|
527
|
-
}
|
|
528
|
-
const sort = Array.isArray(args.sort) && args.sort.length ? args.sort[0] : null;
|
|
529
|
-
if (sort?.property === 'receivedAt') {
|
|
530
|
-
emails.sort((a, b) => {
|
|
531
|
-
const comparison = String(a.receivedAt ?? '').localeCompare(String(b.receivedAt ?? ''));
|
|
532
|
-
return sort.isAscending === false ? -comparison : comparison;
|
|
533
|
-
});
|
|
851
|
+
// ======================
|
|
852
|
+
// email methods
|
|
853
|
+
// ======================
|
|
854
|
+
async methodEmailGet(account, args) {
|
|
855
|
+
if (args.ids === null || args.ids === undefined) {
|
|
856
|
+
// RFC 8621 allows rejecting "fetch all" for the potentially huge Email type.
|
|
857
|
+
throw new JmapServerMethodError("requestTooLarge", "Email/get requires an explicit ids array on this server.");
|
|
534
858
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
if (
|
|
539
|
-
|
|
859
|
+
if (!Array.isArray(args.ids)) {
|
|
860
|
+
throw new JmapServerMethodError("invalidArguments", "Email/get requires an ids array.");
|
|
861
|
+
}
|
|
862
|
+
if (args.ids.length > this.limits.maxObjectsInGet) {
|
|
863
|
+
throw new JmapServerMethodError("requestTooLarge", `ids exceeds maxObjectsInGet (${this.limits.maxObjectsInGet}).`);
|
|
540
864
|
}
|
|
865
|
+
const properties = this.validateProperties(args.properties, KNOWN_EMAIL_PROPERTIES);
|
|
866
|
+
const result = await this.backend.getEmails(account.accountId, args.ids, properties);
|
|
867
|
+
const effectiveProperties = properties ?? DEFAULT_EMAIL_PROPERTIES;
|
|
868
|
+
const list = result.list.map((record) => {
|
|
869
|
+
const projected = this.projectObject(record, effectiveProperties);
|
|
870
|
+
if (effectiveProperties.includes("bodyValues")) {
|
|
871
|
+
projected.bodyValues = this.buildBodyValues(record, args);
|
|
872
|
+
}
|
|
873
|
+
return projected;
|
|
874
|
+
});
|
|
541
875
|
return {
|
|
542
|
-
accountId:
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
ids,
|
|
547
|
-
total,
|
|
876
|
+
accountId: account.accountId,
|
|
877
|
+
state: result.state,
|
|
878
|
+
list,
|
|
879
|
+
notFound: result.notFound,
|
|
548
880
|
};
|
|
549
881
|
}
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
882
|
+
/** Applies the Email/get body-value fetch flags and maxBodyValueBytes truncation. */
|
|
883
|
+
buildBodyValues(record, args) {
|
|
884
|
+
const wanted = new Set();
|
|
885
|
+
if (args.fetchAllBodyValues === true) {
|
|
886
|
+
for (const partId of Object.keys(record.bodyValues)) {
|
|
887
|
+
wanted.add(partId);
|
|
888
|
+
}
|
|
554
889
|
}
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
continue;
|
|
890
|
+
if (args.fetchTextBodyValues === true) {
|
|
891
|
+
for (const part of record.textBody) {
|
|
892
|
+
if (part.partId != null) {
|
|
893
|
+
wanted.add(part.partId);
|
|
894
|
+
}
|
|
561
895
|
}
|
|
562
|
-
|
|
563
|
-
|
|
896
|
+
}
|
|
897
|
+
if (args.fetchHTMLBodyValues === true) {
|
|
898
|
+
for (const part of record.htmlBody) {
|
|
899
|
+
if (part.partId != null) {
|
|
900
|
+
wanted.add(part.partId);
|
|
901
|
+
}
|
|
564
902
|
}
|
|
565
|
-
|
|
566
|
-
|
|
903
|
+
}
|
|
904
|
+
const maxBytes = typeof args.maxBodyValueBytes === "number" && args.maxBodyValueBytes > 0
|
|
905
|
+
? args.maxBodyValueBytes
|
|
906
|
+
: null;
|
|
907
|
+
const result = {};
|
|
908
|
+
for (const partId of wanted) {
|
|
909
|
+
const bodyValue = record.bodyValues[partId];
|
|
910
|
+
if (!bodyValue) {
|
|
911
|
+
continue;
|
|
567
912
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
913
|
+
let value = bodyValue.value;
|
|
914
|
+
let isTruncated = bodyValue.isTruncated === true;
|
|
915
|
+
if (maxBytes !== null) {
|
|
916
|
+
const truncated = truncateUtf8(value, maxBytes);
|
|
917
|
+
if (truncated.length < value.length) {
|
|
918
|
+
value = truncated;
|
|
919
|
+
isTruncated = true;
|
|
572
920
|
}
|
|
573
|
-
else {
|
|
574
|
-
destroyed.add(id);
|
|
575
|
-
}
|
|
576
|
-
updated.delete(id);
|
|
577
921
|
}
|
|
922
|
+
result[partId] = { value, isTruncated };
|
|
578
923
|
}
|
|
579
|
-
|
|
580
|
-
|
|
924
|
+
return result;
|
|
925
|
+
}
|
|
926
|
+
async methodEmailQuery(account, args) {
|
|
927
|
+
const filter = (args.filter ?? {});
|
|
928
|
+
if ("operator" in filter) {
|
|
929
|
+
throw new JmapServerMethodError("unsupportedFilter", "FilterOperator is not supported; use a flat FilterCondition.");
|
|
581
930
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
931
|
+
for (const key of Object.keys(filter)) {
|
|
932
|
+
if (!SUPPORTED_EMAIL_FILTER_KEYS.has(key)) {
|
|
933
|
+
throw new JmapServerMethodError("unsupportedFilter", `Email filter condition "${key}" is not supported.`);
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
const sort = (args.sort ?? []);
|
|
937
|
+
for (const comparator of sort) {
|
|
938
|
+
if (comparator.property !== "receivedAt") {
|
|
939
|
+
throw new JmapServerMethodError("unsupportedSort", `Email sort property "${comparator.property}" is not supported.`);
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
if (args.anchor !== undefined && args.anchor !== null) {
|
|
943
|
+
throw new JmapServerMethodError("invalidArguments", "anchor is not supported.");
|
|
944
|
+
}
|
|
945
|
+
const position = this.validatePosition(args);
|
|
946
|
+
const result = await this.backend.queryEmails(account.accountId, {
|
|
947
|
+
filter: filter,
|
|
948
|
+
sort: sort,
|
|
949
|
+
position,
|
|
950
|
+
limit: typeof args.limit === "number" ? args.limit : null,
|
|
951
|
+
calculateTotal: args.calculateTotal === true,
|
|
952
|
+
});
|
|
953
|
+
const response = {
|
|
954
|
+
accountId: account.accountId,
|
|
955
|
+
queryState: result.queryState,
|
|
956
|
+
canCalculateChanges: false,
|
|
957
|
+
position: result.position,
|
|
958
|
+
ids: result.ids,
|
|
590
959
|
};
|
|
960
|
+
if (args.calculateTotal === true) {
|
|
961
|
+
response.total = result.total ?? 0;
|
|
962
|
+
}
|
|
963
|
+
return response;
|
|
591
964
|
}
|
|
592
|
-
|
|
593
|
-
const
|
|
594
|
-
const
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
const
|
|
602
|
-
const
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
threadId: email.threadId,
|
|
613
|
-
size: email.size,
|
|
614
|
-
};
|
|
965
|
+
async methodEmailChanges(account, args) {
|
|
966
|
+
const { sinceState, maxChanges } = this.validateChangesArgs(args);
|
|
967
|
+
const changes = await this.backend.getEmailChanges(account.accountId, sinceState, maxChanges);
|
|
968
|
+
if (!changes) {
|
|
969
|
+
throw new JmapServerMethodError("cannotCalculateChanges", `Cannot calculate changes since state "${sinceState}".`);
|
|
970
|
+
}
|
|
971
|
+
return { accountId: account.accountId, ...changes };
|
|
972
|
+
}
|
|
973
|
+
async methodEmailSet(account, args, createdIds) {
|
|
974
|
+
const createEntries = Object.entries((args.create ?? {}));
|
|
975
|
+
const updateEntries = Object.entries((args.update ?? {}));
|
|
976
|
+
const destroyIds = (args.destroy ?? []);
|
|
977
|
+
if (createEntries.length + updateEntries.length + destroyIds.length >
|
|
978
|
+
this.limits.maxObjectsInSet) {
|
|
979
|
+
throw new JmapServerMethodError("requestTooLarge", `The set request exceeds maxObjectsInSet (${this.limits.maxObjectsInSet}).`);
|
|
980
|
+
}
|
|
981
|
+
if (typeof args.ifInState === "string") {
|
|
982
|
+
const current = await this.backend.getEmails(account.accountId, []);
|
|
983
|
+
if (current.state !== args.ifInState) {
|
|
984
|
+
throw new JmapServerMethodError("stateMismatch", `ifInState "${args.ifInState}" does not match the current state "${current.state}".`);
|
|
615
985
|
}
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
986
|
+
}
|
|
987
|
+
const backendRequest = {};
|
|
988
|
+
const notUpdatedEarly = {};
|
|
989
|
+
if (createEntries.length) {
|
|
990
|
+
backendRequest.create = {};
|
|
991
|
+
for (const [creationId, spec] of createEntries) {
|
|
992
|
+
backendRequest.create[creationId] = spec;
|
|
619
993
|
}
|
|
620
994
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
995
|
+
if (updateEntries.length) {
|
|
996
|
+
backendRequest.update = {};
|
|
997
|
+
for (const [id, patch] of updateEntries) {
|
|
998
|
+
try {
|
|
999
|
+
backendRequest.update[id] = this.parseEmailUpdatePatch(patch);
|
|
1000
|
+
}
|
|
1001
|
+
catch (error) {
|
|
1002
|
+
notUpdatedEarly[id] = error instanceof JmapServerMethodError
|
|
1003
|
+
? { type: error.type, description: error.message }
|
|
1004
|
+
: { type: "invalidPatch", description: String(error) };
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
if (destroyIds.length) {
|
|
1009
|
+
backendRequest.destroy = destroyIds;
|
|
1010
|
+
}
|
|
1011
|
+
const result = await this.backend.setEmails(account.accountId, backendRequest);
|
|
1012
|
+
const created = {};
|
|
1013
|
+
for (const [creationId, record] of Object.entries(result.created)) {
|
|
1014
|
+
createdIds.set(creationId, record.id);
|
|
1015
|
+
created[creationId] = {
|
|
1016
|
+
id: record.id,
|
|
1017
|
+
blobId: record.blobId,
|
|
1018
|
+
threadId: record.threadId,
|
|
1019
|
+
size: record.size,
|
|
1020
|
+
};
|
|
1021
|
+
}
|
|
1022
|
+
const updated = {};
|
|
1023
|
+
for (const id of result.updated) {
|
|
1024
|
+
updated[id] = null;
|
|
1025
|
+
}
|
|
1026
|
+
return {
|
|
1027
|
+
accountId: account.accountId,
|
|
1028
|
+
oldState: result.oldState,
|
|
1029
|
+
newState: result.newState,
|
|
1030
|
+
created,
|
|
1031
|
+
notCreated: result.notCreated,
|
|
1032
|
+
updated,
|
|
1033
|
+
notUpdated: { ...result.notUpdated, ...notUpdatedEarly },
|
|
1034
|
+
destroyed: result.destroyed,
|
|
1035
|
+
notDestroyed: result.notDestroyed,
|
|
1036
|
+
};
|
|
1037
|
+
}
|
|
1038
|
+
/**
|
|
1039
|
+
* Normalizes an Email/set update patch (RFC 8620 §5.3): full `keywords`/
|
|
1040
|
+
* `mailboxIds` replacements and single-key JSON-pointer patches
|
|
1041
|
+
* (`keywords/$seen`, `mailboxIds/<id>`). Email properties other than these
|
|
1042
|
+
* two are immutable (RFC 8621 §4.6).
|
|
1043
|
+
*/
|
|
1044
|
+
parseEmailUpdatePatch(patch) {
|
|
1045
|
+
const update = {};
|
|
1046
|
+
const unescape = (token) => token.replaceAll("~1", "/").replaceAll("~0", "~");
|
|
1047
|
+
for (const [path, value] of Object.entries(patch)) {
|
|
1048
|
+
if (path === "keywords" || path === "mailboxIds") {
|
|
1049
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
1050
|
+
throw new JmapServerMethodError("invalidProperties", `"${path}" must be an object.`);
|
|
1051
|
+
}
|
|
1052
|
+
const normalized = {};
|
|
1053
|
+
for (const [key, entryValue] of Object.entries(value)) {
|
|
1054
|
+
if (entryValue !== true) {
|
|
1055
|
+
throw new JmapServerMethodError("invalidProperties", `Values in "${path}" must be true; remove entries instead of setting them false.`);
|
|
1056
|
+
}
|
|
1057
|
+
normalized[key] = true;
|
|
1058
|
+
}
|
|
1059
|
+
update[path] = normalized;
|
|
625
1060
|
continue;
|
|
626
1061
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
updated[id] = null;
|
|
1062
|
+
const slashIndex = path.indexOf("/");
|
|
1063
|
+
if (slashIndex === -1) {
|
|
1064
|
+
throw new JmapServerMethodError("invalidProperties", `Email property "${path}" is immutable or unknown.`);
|
|
631
1065
|
}
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
1066
|
+
const property = path.slice(0, slashIndex);
|
|
1067
|
+
const rest = path.slice(slashIndex + 1);
|
|
1068
|
+
if ((property !== "keywords" && property !== "mailboxIds") ||
|
|
1069
|
+
rest.includes("/") || !rest) {
|
|
1070
|
+
throw new JmapServerMethodError("invalidPatch", `Unsupported patch path "${path}".`);
|
|
635
1071
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
1072
|
+
const key = unescape(rest);
|
|
1073
|
+
const normalizedValue = value === true
|
|
1074
|
+
? true
|
|
1075
|
+
: value === null || value === false
|
|
1076
|
+
? null
|
|
1077
|
+
: undefined;
|
|
1078
|
+
if (normalizedValue === undefined) {
|
|
1079
|
+
throw new JmapServerMethodError("invalidPatch", `Patch value for "${path}" must be true or null.`);
|
|
1080
|
+
}
|
|
1081
|
+
if (property === "keywords") {
|
|
1082
|
+
update.keywordsPatch = update.keywordsPatch ?? {};
|
|
1083
|
+
update.keywordsPatch[key] = normalizedValue;
|
|
641
1084
|
}
|
|
642
1085
|
else {
|
|
643
|
-
|
|
1086
|
+
update.mailboxIdsPatch = update.mailboxIdsPatch ?? {};
|
|
1087
|
+
update.mailboxIdsPatch[key] = normalizedValue;
|
|
644
1088
|
}
|
|
645
1089
|
}
|
|
646
|
-
if (
|
|
647
|
-
|
|
648
|
-
created: changedCreated,
|
|
649
|
-
updated: changedUpdated,
|
|
650
|
-
destroyed: changedDestroyed,
|
|
651
|
-
});
|
|
1090
|
+
if (update.keywords && update.keywordsPatch) {
|
|
1091
|
+
throw new JmapServerMethodError("invalidPatch", 'A patch must not set "keywords" and patch "keywords/..." at the same time.');
|
|
652
1092
|
}
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
created,
|
|
658
|
-
notCreated,
|
|
659
|
-
updated,
|
|
660
|
-
notUpdated,
|
|
661
|
-
destroyed,
|
|
662
|
-
notDestroyed,
|
|
663
|
-
};
|
|
1093
|
+
if (update.mailboxIds && update.mailboxIdsPatch) {
|
|
1094
|
+
throw new JmapServerMethodError("invalidPatch", 'A patch must not set "mailboxIds" and patch "mailboxIds/..." at the same time.');
|
|
1095
|
+
}
|
|
1096
|
+
return update;
|
|
664
1097
|
}
|
|
665
|
-
|
|
1098
|
+
// ======================
|
|
1099
|
+
// identity + submission methods
|
|
1100
|
+
// ======================
|
|
1101
|
+
async methodIdentityGet(account, args) {
|
|
1102
|
+
const result = await this.backend.getIdentities(account.accountId);
|
|
1103
|
+
let list = result.list;
|
|
1104
|
+
const notFound = [];
|
|
1105
|
+
if (Array.isArray(args.ids)) {
|
|
1106
|
+
const wanted = new Set(args.ids);
|
|
1107
|
+
list = list.filter((identity) => wanted.has(identity.id));
|
|
1108
|
+
for (const id of wanted) {
|
|
1109
|
+
if (!list.some((identity) => identity.id === id)) {
|
|
1110
|
+
notFound.push(id);
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
666
1114
|
return {
|
|
667
|
-
accountId:
|
|
668
|
-
state:
|
|
669
|
-
list
|
|
670
|
-
notFound
|
|
1115
|
+
accountId: account.accountId,
|
|
1116
|
+
state: result.state,
|
|
1117
|
+
list,
|
|
1118
|
+
notFound,
|
|
671
1119
|
};
|
|
672
1120
|
}
|
|
673
|
-
methodEmailSubmissionSet(
|
|
1121
|
+
async methodEmailSubmissionSet(account, args, createdIds) {
|
|
674
1122
|
const created = {};
|
|
675
1123
|
const notCreated = {};
|
|
1124
|
+
const notUpdated = {};
|
|
1125
|
+
const notDestroyed = {};
|
|
1126
|
+
/** creationId -> { submissionId, emailId } for onSuccess* resolution. */
|
|
1127
|
+
const createdSubmissions = new Map();
|
|
1128
|
+
const identitiesResult = await this.backend.getIdentities(account.accountId);
|
|
676
1129
|
for (const [creationId, spec] of Object.entries((args.create ?? {}))) {
|
|
677
1130
|
let emailId = spec.emailId;
|
|
678
|
-
if (typeof emailId ===
|
|
1131
|
+
if (typeof emailId === "string" && emailId.startsWith("#")) {
|
|
679
1132
|
const resolved = createdIds.get(emailId.slice(1));
|
|
680
1133
|
if (!resolved) {
|
|
681
1134
|
notCreated[creationId] = {
|
|
682
|
-
type:
|
|
1135
|
+
type: "invalidProperties",
|
|
683
1136
|
description: `Unknown creation id reference "${emailId}".`,
|
|
684
1137
|
};
|
|
685
1138
|
continue;
|
|
686
1139
|
}
|
|
687
1140
|
emailId = resolved;
|
|
688
1141
|
}
|
|
689
|
-
|
|
1142
|
+
const emailResult = await this.backend.getEmails(account.accountId, [
|
|
1143
|
+
emailId,
|
|
1144
|
+
]);
|
|
1145
|
+
const email = emailResult.list[0];
|
|
1146
|
+
if (!email) {
|
|
690
1147
|
notCreated[creationId] = {
|
|
691
|
-
type:
|
|
1148
|
+
type: "invalidProperties",
|
|
692
1149
|
description: `Email "${emailId}" does not exist.`,
|
|
693
1150
|
};
|
|
694
1151
|
continue;
|
|
695
1152
|
}
|
|
696
|
-
const identity =
|
|
1153
|
+
const identity = identitiesResult.list.find((candidate) => candidate.id === spec.identityId);
|
|
697
1154
|
if (!identity) {
|
|
698
1155
|
notCreated[creationId] = {
|
|
699
|
-
type:
|
|
1156
|
+
type: "invalidProperties",
|
|
700
1157
|
description: `Identity "${spec.identityId}" does not exist.`,
|
|
701
1158
|
};
|
|
702
1159
|
continue;
|
|
703
1160
|
}
|
|
704
|
-
const
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
1161
|
+
const envelope = this.resolveEnvelope(spec.envelope, identity.email, email);
|
|
1162
|
+
if (!envelope.rcptTo.length) {
|
|
1163
|
+
notCreated[creationId] = {
|
|
1164
|
+
type: "noRecipients",
|
|
1165
|
+
description: "The email has no to/cc/bcc recipients and no envelope was given.",
|
|
1166
|
+
};
|
|
1167
|
+
continue;
|
|
1168
|
+
}
|
|
1169
|
+
const blob = await this.backend.getBlob(account.accountId, email.blobId);
|
|
1170
|
+
if (!blob) {
|
|
1171
|
+
notCreated[creationId] = {
|
|
1172
|
+
type: "invalidProperties",
|
|
1173
|
+
description: `Raw message blob "${email.blobId}" does not exist.`,
|
|
1174
|
+
};
|
|
1175
|
+
continue;
|
|
1176
|
+
}
|
|
1177
|
+
try {
|
|
1178
|
+
const submission = await this.backend.submitEmail(account.accountId, {
|
|
1179
|
+
emailId,
|
|
1180
|
+
identityId: identity.id,
|
|
1181
|
+
envelope,
|
|
1182
|
+
message: blob.data,
|
|
1183
|
+
});
|
|
1184
|
+
createdSubmissions.set(creationId, {
|
|
1185
|
+
submissionId: submission.id,
|
|
1186
|
+
emailId,
|
|
1187
|
+
});
|
|
1188
|
+
created[creationId] = {
|
|
1189
|
+
id: submission.id,
|
|
1190
|
+
undoStatus: submission.undoStatus,
|
|
1191
|
+
sendAt: submission.sendAt,
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
catch (error) {
|
|
1195
|
+
notCreated[creationId] = {
|
|
1196
|
+
type: "forbiddenToSend",
|
|
1197
|
+
description: error instanceof Error ? error.message : String(error),
|
|
1198
|
+
};
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
for (const id of Object.keys((args.update ?? {}))) {
|
|
1202
|
+
notUpdated[id] = {
|
|
1203
|
+
type: "forbidden",
|
|
1204
|
+
description: "EmailSubmission updates are not supported.",
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
for (const id of (args.destroy ?? [])) {
|
|
1208
|
+
notDestroyed[id] = {
|
|
1209
|
+
type: "forbidden",
|
|
1210
|
+
description: "EmailSubmission destroys are not supported.",
|
|
711
1211
|
};
|
|
712
|
-
|
|
713
|
-
|
|
1212
|
+
}
|
|
1213
|
+
const responses = [
|
|
1214
|
+
{
|
|
1215
|
+
name: "EmailSubmission/set",
|
|
1216
|
+
result: {
|
|
1217
|
+
accountId: account.accountId,
|
|
1218
|
+
oldState: null,
|
|
1219
|
+
newState: "0",
|
|
1220
|
+
created,
|
|
1221
|
+
notCreated,
|
|
1222
|
+
updated: {},
|
|
1223
|
+
notUpdated,
|
|
1224
|
+
destroyed: [],
|
|
1225
|
+
notDestroyed,
|
|
1226
|
+
},
|
|
1227
|
+
mutated: createdSubmissions.size > 0,
|
|
1228
|
+
},
|
|
1229
|
+
];
|
|
1230
|
+
// onSuccessUpdateEmail / onSuccessDestroyEmail (RFC 8621 §7.5): apply an
|
|
1231
|
+
// implicit Email/set for successfully created submissions and append its
|
|
1232
|
+
// response after the EmailSubmission/set response.
|
|
1233
|
+
const resolveSubmissionRef = (reference) => {
|
|
1234
|
+
if (reference.startsWith("#")) {
|
|
1235
|
+
return createdSubmissions.get(reference.slice(1)) ?? null;
|
|
1236
|
+
}
|
|
1237
|
+
for (const entry of createdSubmissions.values()) {
|
|
1238
|
+
if (entry.submissionId === reference) {
|
|
1239
|
+
return entry;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
return null;
|
|
1243
|
+
};
|
|
1244
|
+
const implicitSet = { accountId: account.accountId };
|
|
1245
|
+
let hasImplicitSet = false;
|
|
1246
|
+
if (args.onSuccessUpdateEmail && typeof args.onSuccessUpdateEmail === "object") {
|
|
1247
|
+
const update = {};
|
|
1248
|
+
for (const [reference, patch] of Object.entries(args.onSuccessUpdateEmail)) {
|
|
1249
|
+
const entry = resolveSubmissionRef(reference);
|
|
1250
|
+
if (entry) {
|
|
1251
|
+
update[entry.emailId] = patch;
|
|
1252
|
+
hasImplicitSet = true;
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
implicitSet.update = update;
|
|
1256
|
+
}
|
|
1257
|
+
if (Array.isArray(args.onSuccessDestroyEmail)) {
|
|
1258
|
+
const destroy = [];
|
|
1259
|
+
for (const reference of args.onSuccessDestroyEmail) {
|
|
1260
|
+
const entry = resolveSubmissionRef(reference);
|
|
1261
|
+
if (entry) {
|
|
1262
|
+
destroy.push(entry.emailId);
|
|
1263
|
+
hasImplicitSet = true;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
implicitSet.destroy = destroy;
|
|
1267
|
+
}
|
|
1268
|
+
if (hasImplicitSet) {
|
|
1269
|
+
const result = await this.methodEmailSet(account, implicitSet, createdIds);
|
|
1270
|
+
responses.push({
|
|
1271
|
+
name: "Email/set",
|
|
1272
|
+
result,
|
|
1273
|
+
mutated: result.newState !== result.oldState,
|
|
1274
|
+
});
|
|
1275
|
+
}
|
|
1276
|
+
return responses;
|
|
1277
|
+
}
|
|
1278
|
+
/** Uses the client-provided envelope or derives it from the email's addresses. */
|
|
1279
|
+
resolveEnvelope(specEnvelope, identityEmail, email) {
|
|
1280
|
+
if (specEnvelope &&
|
|
1281
|
+
typeof specEnvelope === "object" &&
|
|
1282
|
+
specEnvelope.mailFrom?.email &&
|
|
1283
|
+
Array.isArray(specEnvelope.rcptTo)) {
|
|
1284
|
+
return {
|
|
1285
|
+
mailFrom: { email: String(specEnvelope.mailFrom.email) },
|
|
1286
|
+
rcptTo: specEnvelope.rcptTo
|
|
1287
|
+
.filter((recipient) => typeof recipient?.email === "string")
|
|
1288
|
+
.map((recipient) => ({ email: recipient.email })),
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const recipients = new Set();
|
|
1292
|
+
for (const list of [email.to, email.cc, email.bcc]) {
|
|
1293
|
+
for (const address of list ?? []) {
|
|
1294
|
+
recipients.add(address.email);
|
|
1295
|
+
}
|
|
714
1296
|
}
|
|
715
1297
|
return {
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
newState: String(user.state),
|
|
719
|
-
created,
|
|
720
|
-
notCreated,
|
|
721
|
-
updated: {},
|
|
722
|
-
notUpdated: {},
|
|
723
|
-
destroyed: [],
|
|
724
|
-
notDestroyed: {},
|
|
1298
|
+
mailFrom: { email: email.from?.[0]?.email ?? identityEmail },
|
|
1299
|
+
rcptTo: Array.from(recipients).map((address) => ({ email: address })),
|
|
725
1300
|
};
|
|
726
1301
|
}
|
|
727
1302
|
// ======================
|
|
728
|
-
//
|
|
1303
|
+
// upload + download
|
|
729
1304
|
// ======================
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
1305
|
+
async cancelRequestBody(request, reason) {
|
|
1306
|
+
try {
|
|
1307
|
+
if (request.body && !request.body.locked) {
|
|
1308
|
+
await request.body.cancel(reason);
|
|
1309
|
+
}
|
|
734
1310
|
}
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
user.blobs.set(blobId, {
|
|
774
|
-
data: Buffer.from(rawLines.join('\r\n'), 'utf8'),
|
|
775
|
-
type: 'message/rfc822',
|
|
776
|
-
name: `${id}.eml`,
|
|
777
|
-
});
|
|
778
|
-
const normalizedBodyValues = {};
|
|
779
|
-
for (const [partId, bodyValue] of Object.entries(bodyValues)) {
|
|
780
|
-
normalizedBodyValues[partId] = { value: bodyValue.value ?? '', isTruncated: false };
|
|
1311
|
+
catch {
|
|
1312
|
+
// The runtime or peer may already have closed the transport stream.
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
async readRequestBodyBounded(request, maxBytes) {
|
|
1316
|
+
const declaredLength = request.headers.get("content-length");
|
|
1317
|
+
if (declaredLength !== null) {
|
|
1318
|
+
if (!/^\d+$/.test(declaredLength) ||
|
|
1319
|
+
!Number.isSafeInteger(Number(declaredLength))) {
|
|
1320
|
+
await this.cancelRequestBody(request, "invalid content length");
|
|
1321
|
+
throw new JmapRequestBodyError("invalidLength");
|
|
1322
|
+
}
|
|
1323
|
+
if (Number(declaredLength) > maxBytes) {
|
|
1324
|
+
await this.cancelRequestBody(request, "request body too large");
|
|
1325
|
+
throw new JmapRequestBodyError("tooLarge");
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (!request.body) {
|
|
1329
|
+
return new Uint8Array();
|
|
1330
|
+
}
|
|
1331
|
+
const reader = request.body.getReader();
|
|
1332
|
+
const chunks = [];
|
|
1333
|
+
let total = 0;
|
|
1334
|
+
try {
|
|
1335
|
+
while (true) {
|
|
1336
|
+
const { done, value } = await reader.read();
|
|
1337
|
+
if (done)
|
|
1338
|
+
break;
|
|
1339
|
+
total += value.byteLength;
|
|
1340
|
+
if (total > maxBytes) {
|
|
1341
|
+
await reader.cancel("request body too large");
|
|
1342
|
+
throw new JmapRequestBodyError("tooLarge");
|
|
1343
|
+
}
|
|
1344
|
+
chunks.push(value);
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
finally {
|
|
1348
|
+
reader.releaseLock();
|
|
781
1349
|
}
|
|
1350
|
+
const data = new Uint8Array(total);
|
|
1351
|
+
let offset = 0;
|
|
1352
|
+
for (const chunk of chunks) {
|
|
1353
|
+
data.set(chunk, offset);
|
|
1354
|
+
offset += chunk.byteLength;
|
|
1355
|
+
}
|
|
1356
|
+
return data;
|
|
1357
|
+
}
|
|
1358
|
+
createExactUploadBody(request, expectedSize) {
|
|
1359
|
+
const abortController = new AbortController();
|
|
1360
|
+
let reader = null;
|
|
1361
|
+
let bytesRead = 0;
|
|
1362
|
+
let complete = false;
|
|
1363
|
+
let cancelled = false;
|
|
1364
|
+
const cancel = async (reason) => {
|
|
1365
|
+
if (cancelled || complete)
|
|
1366
|
+
return;
|
|
1367
|
+
cancelled = true;
|
|
1368
|
+
abortController.abort(reason);
|
|
1369
|
+
try {
|
|
1370
|
+
if (reader) {
|
|
1371
|
+
await reader.cancel(reason);
|
|
1372
|
+
}
|
|
1373
|
+
else if (request.body && !request.body.locked) {
|
|
1374
|
+
await request.body.cancel(reason);
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
catch {
|
|
1378
|
+
// The peer or consumer may already have closed the stream.
|
|
1379
|
+
}
|
|
1380
|
+
};
|
|
1381
|
+
const onRequestAbort = () => {
|
|
1382
|
+
void cancel(request.signal.reason ?? new Error("Request aborted."));
|
|
1383
|
+
};
|
|
1384
|
+
request.signal.addEventListener("abort", onRequestAbort, { once: true });
|
|
1385
|
+
if (request.signal.aborted)
|
|
1386
|
+
onRequestAbort();
|
|
1387
|
+
const stream = new ReadableStream({
|
|
1388
|
+
async pull(controller) {
|
|
1389
|
+
if (cancelled) {
|
|
1390
|
+
controller.error(abortController.signal.reason ?? new Error("Upload cancelled."));
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
if (!request.body) {
|
|
1394
|
+
if (expectedSize === 0) {
|
|
1395
|
+
complete = true;
|
|
1396
|
+
controller.close();
|
|
1397
|
+
}
|
|
1398
|
+
else {
|
|
1399
|
+
const error = new JmapRequestBodyError("lengthMismatch");
|
|
1400
|
+
abortController.abort(error);
|
|
1401
|
+
controller.error(error);
|
|
1402
|
+
}
|
|
1403
|
+
return;
|
|
1404
|
+
}
|
|
1405
|
+
reader ??= request.body.getReader();
|
|
1406
|
+
const { done, value } = await reader.read();
|
|
1407
|
+
if (done) {
|
|
1408
|
+
if (bytesRead !== expectedSize) {
|
|
1409
|
+
const error = new JmapRequestBodyError("lengthMismatch");
|
|
1410
|
+
abortController.abort(error);
|
|
1411
|
+
controller.error(error);
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
complete = true;
|
|
1415
|
+
controller.close();
|
|
1416
|
+
return;
|
|
1417
|
+
}
|
|
1418
|
+
bytesRead += value.byteLength;
|
|
1419
|
+
if (bytesRead > expectedSize) {
|
|
1420
|
+
const error = new JmapRequestBodyError("lengthMismatch");
|
|
1421
|
+
await cancel(error);
|
|
1422
|
+
controller.error(error);
|
|
1423
|
+
return;
|
|
1424
|
+
}
|
|
1425
|
+
controller.enqueue(value);
|
|
1426
|
+
},
|
|
1427
|
+
cancel,
|
|
1428
|
+
}, { highWaterMark: 0 });
|
|
782
1429
|
return {
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
size: textValue.length,
|
|
789
|
-
receivedAt,
|
|
790
|
-
sentAt: receivedAt,
|
|
791
|
-
subject: spec.subject ?? null,
|
|
792
|
-
from,
|
|
793
|
-
to,
|
|
794
|
-
cc: spec.cc ?? null,
|
|
795
|
-
bcc: spec.bcc ?? null,
|
|
796
|
-
replyTo: spec.replyTo ?? null,
|
|
797
|
-
hasAttachment: false,
|
|
798
|
-
preview: textValue.slice(0, 100),
|
|
799
|
-
bodyValues: normalizedBodyValues,
|
|
800
|
-
textBody: textBodyParts,
|
|
801
|
-
htmlBody: htmlBodyParts,
|
|
802
|
-
attachments: [],
|
|
1430
|
+
stream,
|
|
1431
|
+
signal: abortController.signal,
|
|
1432
|
+
isComplete: () => complete,
|
|
1433
|
+
cancel,
|
|
1434
|
+
dispose: () => request.signal.removeEventListener("abort", onRequestAbort),
|
|
803
1435
|
};
|
|
804
1436
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
1437
|
+
mappedUploadErrorResponse(error) {
|
|
1438
|
+
const problem = this.options.mapUploadError?.(error);
|
|
1439
|
+
if (!problem)
|
|
1440
|
+
return null;
|
|
1441
|
+
if (!Number.isInteger(problem.status) || problem.status < 400 ||
|
|
1442
|
+
problem.status > 599 ||
|
|
1443
|
+
!problem.detail) {
|
|
1444
|
+
throw new Error("mapUploadError returned an invalid upload problem.");
|
|
1445
|
+
}
|
|
1446
|
+
const body = {
|
|
1447
|
+
type: problem.type ?? "about:blank",
|
|
1448
|
+
status: problem.status,
|
|
1449
|
+
detail: problem.detail,
|
|
1450
|
+
...(problem.limit ? { limit: problem.limit } : {}),
|
|
1451
|
+
};
|
|
1452
|
+
const headers = {
|
|
1453
|
+
"content-type": "application/problem+json",
|
|
1454
|
+
};
|
|
1455
|
+
if (problem.retryAfterSeconds !== undefined) {
|
|
1456
|
+
headers["retry-after"] = String(problem.retryAfterSeconds);
|
|
1457
|
+
}
|
|
1458
|
+
return new Response(JSON.stringify(body), {
|
|
1459
|
+
status: problem.status,
|
|
1460
|
+
headers,
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
requestBodyErrorResponse(error, limit) {
|
|
1464
|
+
if (error.reason === "invalidLength") {
|
|
1465
|
+
return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
|
|
1466
|
+
}
|
|
1467
|
+
if (error.reason === "lengthMismatch") {
|
|
1468
|
+
return this.problemResponse(400, "about:blank", "The request body does not match Content-Length.");
|
|
1469
|
+
}
|
|
1470
|
+
const maximum = limit === "maxSizeUpload"
|
|
1471
|
+
? this.limits.maxSizeUpload
|
|
1472
|
+
: this.limits.maxSizeRequest;
|
|
1473
|
+
return this.limitResponse(400, limit, `The request is larger than ${maximum} bytes.`);
|
|
1474
|
+
}
|
|
1475
|
+
async handleStreamingUpload(account, request, type) {
|
|
1476
|
+
const contentLength = request.headers.get("content-length");
|
|
1477
|
+
if (contentLength === null) {
|
|
1478
|
+
await this.cancelRequestBody(request, "content length required");
|
|
1479
|
+
return this.problemResponse(411, "about:blank", "Content-Length is required.");
|
|
1480
|
+
}
|
|
1481
|
+
if (!/^\d+$/.test(contentLength) ||
|
|
1482
|
+
!Number.isSafeInteger(Number(contentLength))) {
|
|
1483
|
+
await this.cancelRequestBody(request, "invalid content length");
|
|
1484
|
+
return this.problemResponse(400, "about:blank", "Invalid Content-Length header.");
|
|
1485
|
+
}
|
|
1486
|
+
const declaredSize = Number(contentLength);
|
|
1487
|
+
if (declaredSize > this.limits.maxSizeUpload) {
|
|
1488
|
+
await this.cancelRequestBody(request, "request body too large");
|
|
1489
|
+
return this.limitResponse(400, "maxSizeUpload", `The upload is larger than ${this.limits.maxSizeUpload} bytes.`);
|
|
1490
|
+
}
|
|
1491
|
+
if (!request.body && declaredSize !== 0) {
|
|
1492
|
+
return this.problemResponse(400, "about:blank", "The request body does not match Content-Length.");
|
|
1493
|
+
}
|
|
1494
|
+
const body = this.createExactUploadBody(request, declaredSize);
|
|
1495
|
+
const upload = {
|
|
1496
|
+
stream: body.stream,
|
|
1497
|
+
size: declaredSize,
|
|
1498
|
+
type,
|
|
1499
|
+
signal: body.signal,
|
|
1500
|
+
};
|
|
1501
|
+
try {
|
|
1502
|
+
const result = await this.backend.uploadBlobStream(account.accountId, upload);
|
|
1503
|
+
if (!body.isComplete()) {
|
|
1504
|
+
await body.cancel(new JmapRequestBodyError("lengthMismatch"));
|
|
1505
|
+
return this.problemResponse(400, "about:blank", "The upload backend did not consume the exact request body.");
|
|
1506
|
+
}
|
|
1507
|
+
if (result.size !== declaredSize) {
|
|
1508
|
+
throw new Error(`Upload backend reported ${result.size} bytes for a ${declaredSize}-byte request.`);
|
|
1509
|
+
}
|
|
1510
|
+
return this.jsonResponse(200, {
|
|
1511
|
+
accountId: account.accountId,
|
|
1512
|
+
blobId: result.blobId,
|
|
1513
|
+
type,
|
|
1514
|
+
size: result.size,
|
|
1515
|
+
});
|
|
1516
|
+
}
|
|
1517
|
+
catch (error) {
|
|
1518
|
+
await body.cancel(error);
|
|
1519
|
+
if (error instanceof JmapRequestBodyError) {
|
|
1520
|
+
return this.requestBodyErrorResponse(error, "maxSizeUpload");
|
|
1521
|
+
}
|
|
1522
|
+
const mapped = this.mappedUploadErrorResponse(error);
|
|
1523
|
+
if (mapped)
|
|
1524
|
+
return mapped;
|
|
1525
|
+
throw error;
|
|
1526
|
+
}
|
|
1527
|
+
finally {
|
|
1528
|
+
body.dispose();
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
async handleUpload(account, principal, pathname, request) {
|
|
1532
|
+
const segments = pathname.split("/").filter((segment) => segment.length > 0);
|
|
1533
|
+
const accountId = decodeURIComponent(segments[2] ?? "");
|
|
1534
|
+
if (accountId !== account.accountId) {
|
|
1535
|
+
await this.cancelRequestBody(request, "unknown account");
|
|
1536
|
+
return this.problemResponse(404, "about:blank", "Unknown account");
|
|
1537
|
+
}
|
|
1538
|
+
const principalUploads = this.activeUploadsByPrincipal.get(principal.username) ?? 0;
|
|
1539
|
+
if (principalUploads >= this.limits.maxConcurrentUpload ||
|
|
1540
|
+
this.activeUploadRequests >= this.maxConcurrentUploadServer) {
|
|
1541
|
+
await this.cancelRequestBody(request, "upload concurrency limit reached");
|
|
1542
|
+
return this.limitResponse(429, "maxConcurrentUpload", "Too many concurrent uploads.");
|
|
1543
|
+
}
|
|
1544
|
+
this.activeUploadRequests++;
|
|
1545
|
+
this.activeUploadsByPrincipal.set(principal.username, principalUploads + 1);
|
|
1546
|
+
try {
|
|
1547
|
+
const type = request.headers.get("content-type") ??
|
|
1548
|
+
"application/octet-stream";
|
|
1549
|
+
if (typeof this.backend.uploadBlobStream === "function") {
|
|
1550
|
+
return await this.handleStreamingUpload(account, request, type);
|
|
1551
|
+
}
|
|
1552
|
+
let data;
|
|
1553
|
+
try {
|
|
1554
|
+
data = await this.readRequestBodyBounded(request, this.limits.maxSizeUpload);
|
|
1555
|
+
}
|
|
1556
|
+
catch (error) {
|
|
1557
|
+
if (error instanceof JmapRequestBodyError) {
|
|
1558
|
+
return this.requestBodyErrorResponse(error, "maxSizeUpload");
|
|
1559
|
+
}
|
|
1560
|
+
throw error;
|
|
1561
|
+
}
|
|
1562
|
+
try {
|
|
1563
|
+
const { blobId, size } = await this.backend.uploadBlob(account.accountId, data, type);
|
|
1564
|
+
return this.jsonResponse(200, {
|
|
1565
|
+
accountId: account.accountId,
|
|
1566
|
+
blobId,
|
|
1567
|
+
type,
|
|
1568
|
+
size,
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
catch (error) {
|
|
1572
|
+
const mapped = this.mappedUploadErrorResponse(error);
|
|
1573
|
+
if (mapped)
|
|
1574
|
+
return mapped;
|
|
1575
|
+
throw error;
|
|
1576
|
+
}
|
|
1577
|
+
}
|
|
1578
|
+
finally {
|
|
1579
|
+
this.activeUploadRequests--;
|
|
1580
|
+
const remainingPrincipalUploads = (this.activeUploadsByPrincipal.get(principal.username) ?? 1) - 1;
|
|
1581
|
+
if (remainingPrincipalUploads <= 0) {
|
|
1582
|
+
this.activeUploadsByPrincipal.delete(principal.username);
|
|
1583
|
+
}
|
|
1584
|
+
else {
|
|
1585
|
+
this.activeUploadsByPrincipal.set(principal.username, remainingPrincipalUploads);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
async handleDownload(account, pathname, url) {
|
|
1590
|
+
// /jmap/download/{accountId}/{blobId}/{name}
|
|
1591
|
+
const segments = pathname.split("/").filter((segment) => segment.length > 0);
|
|
1592
|
+
const accountId = decodeURIComponent(segments[2] ?? "");
|
|
1593
|
+
const blobId = decodeURIComponent(segments[3] ?? "");
|
|
1594
|
+
const name = decodeURIComponent(segments[4] ?? "blob");
|
|
1595
|
+
if (accountId !== account.accountId) {
|
|
1596
|
+
return this.problemResponse(404, "about:blank", "Unknown account");
|
|
1597
|
+
}
|
|
1598
|
+
const blob = await this.backend.getBlob(account.accountId, blobId);
|
|
1599
|
+
if (!blob) {
|
|
1600
|
+
return this.problemResponse(404, "about:blank", "Unknown blob");
|
|
1601
|
+
}
|
|
1602
|
+
const type = url.searchParams.get("type") ?? blob.type;
|
|
1603
|
+
return new Response(asBodyBytes(blob.data), {
|
|
1604
|
+
status: 200,
|
|
1605
|
+
headers: {
|
|
1606
|
+
"content-type": type,
|
|
1607
|
+
"content-length": String(blob.data.length),
|
|
1608
|
+
"content-disposition": `attachment; filename="${name.replaceAll('"', "")}"`,
|
|
1609
|
+
},
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
// ======================
|
|
1613
|
+
// event source (SSE)
|
|
1614
|
+
// ======================
|
|
1615
|
+
handleEventSource(account, url) {
|
|
1616
|
+
const typesParam = url.searchParams.get("types") ?? "*";
|
|
1617
|
+
const types = typesParam === "*" || typesParam === "" ? null : new Set(typesParam
|
|
1618
|
+
.split(",")
|
|
1619
|
+
.map((entry) => entry.trim())
|
|
1620
|
+
.filter((entry) => entry.length > 0));
|
|
1621
|
+
const closeAfterState = url.searchParams.get("closeafter") === "state";
|
|
1622
|
+
const pingRaw = Number(url.searchParams.get("ping") ?? "0");
|
|
1623
|
+
const pingSeconds = Number.isFinite(pingRaw) && pingRaw > 0
|
|
1624
|
+
? Math.max(1, Math.floor(pingRaw))
|
|
1625
|
+
: 0;
|
|
1626
|
+
const state = {
|
|
1627
|
+
accountId: account.accountId,
|
|
1628
|
+
types,
|
|
1629
|
+
closeAfterState,
|
|
1630
|
+
controller: null,
|
|
1631
|
+
pingTimer: null,
|
|
1632
|
+
lastSent: new Map(),
|
|
1633
|
+
closed: false,
|
|
1634
|
+
};
|
|
1635
|
+
const stream = new ReadableStream({
|
|
1636
|
+
start: (controller) => {
|
|
1637
|
+
state.controller = controller;
|
|
1638
|
+
controller.enqueue(textEncoder.encode(": jmap event stream\n\n"));
|
|
1639
|
+
if (pingSeconds > 0) {
|
|
1640
|
+
state.pingTimer = setInterval(() => {
|
|
1641
|
+
this.writeToStream(state, `event: ping\ndata: {"interval":${pingSeconds}}\n\n`);
|
|
1642
|
+
}, pingSeconds * 1000);
|
|
815
1643
|
}
|
|
816
|
-
|
|
817
|
-
|
|
1644
|
+
try {
|
|
1645
|
+
this.registerStream(state);
|
|
818
1646
|
}
|
|
1647
|
+
catch (error) {
|
|
1648
|
+
// a throwing backend.subscribeToChanges must not strand the ping timer
|
|
1649
|
+
this.unregisterStream(state);
|
|
1650
|
+
throw error;
|
|
1651
|
+
}
|
|
1652
|
+
},
|
|
1653
|
+
cancel: () => {
|
|
1654
|
+
this.unregisterStream(state);
|
|
1655
|
+
},
|
|
1656
|
+
});
|
|
1657
|
+
return new Response(stream, {
|
|
1658
|
+
status: 200,
|
|
1659
|
+
headers: {
|
|
1660
|
+
"content-type": "text/event-stream",
|
|
1661
|
+
"cache-control": "no-cache",
|
|
1662
|
+
},
|
|
1663
|
+
});
|
|
1664
|
+
}
|
|
1665
|
+
registerStream(state) {
|
|
1666
|
+
if (!this.changeFeedUnsubscribe) {
|
|
1667
|
+
this.changeFeedUnsubscribe = this.backend.subscribeToChanges((change) => {
|
|
1668
|
+
this.pushStateChange(change.accountId, change.changed);
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
this.eventStreams.add(state);
|
|
1672
|
+
}
|
|
1673
|
+
unregisterStream(state) {
|
|
1674
|
+
state.closed = true;
|
|
1675
|
+
if (state.pingTimer) {
|
|
1676
|
+
clearInterval(state.pingTimer);
|
|
1677
|
+
state.pingTimer = null;
|
|
1678
|
+
}
|
|
1679
|
+
this.eventStreams.delete(state);
|
|
1680
|
+
if (!this.eventStreams.size && this.changeFeedUnsubscribe) {
|
|
1681
|
+
const unsubscribe = this.changeFeedUnsubscribe;
|
|
1682
|
+
this.changeFeedUnsubscribe = null;
|
|
1683
|
+
try {
|
|
1684
|
+
unsubscribe();
|
|
1685
|
+
}
|
|
1686
|
+
catch (error) {
|
|
1687
|
+
this.cleanupErrors.push(error);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
closeStream(state) {
|
|
1692
|
+
this.unregisterStream(state);
|
|
1693
|
+
try {
|
|
1694
|
+
state.controller?.close();
|
|
1695
|
+
}
|
|
1696
|
+
catch {
|
|
1697
|
+
// already closed or errored
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
writeToStream(state, payload) {
|
|
1701
|
+
if (state.closed || !state.controller) {
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
try {
|
|
1705
|
+
state.controller.enqueue(textEncoder.encode(payload));
|
|
1706
|
+
}
|
|
1707
|
+
catch {
|
|
1708
|
+
this.closeStream(state);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
/**
|
|
1712
|
+
* Pushes a StateChange to matching event streams. Per-type states are
|
|
1713
|
+
* deduplicated per stream, so a mutation notified both by the backend
|
|
1714
|
+
* change feed and by the post-request push is delivered once.
|
|
1715
|
+
*/
|
|
1716
|
+
pushStateChange(accountId, changed) {
|
|
1717
|
+
for (const state of Array.from(this.eventStreams)) {
|
|
1718
|
+
if (state.accountId !== accountId) {
|
|
819
1719
|
continue;
|
|
820
1720
|
}
|
|
821
|
-
|
|
822
|
-
for (const
|
|
823
|
-
if (
|
|
824
|
-
|
|
1721
|
+
const filtered = {};
|
|
1722
|
+
for (const [type, typeState] of Object.entries(changed)) {
|
|
1723
|
+
if (state.types && !state.types.has(type)) {
|
|
1724
|
+
continue;
|
|
825
1725
|
}
|
|
826
|
-
|
|
1726
|
+
if (state.lastSent.get(type) === typeState) {
|
|
1727
|
+
continue;
|
|
1728
|
+
}
|
|
1729
|
+
filtered[type] = typeState;
|
|
827
1730
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
delete target[leaf];
|
|
1731
|
+
if (!Object.keys(filtered).length) {
|
|
1732
|
+
continue;
|
|
831
1733
|
}
|
|
832
|
-
|
|
833
|
-
|
|
1734
|
+
for (const [type, typeState] of Object.entries(filtered)) {
|
|
1735
|
+
state.lastSent.set(type, typeState);
|
|
1736
|
+
}
|
|
1737
|
+
const stateChange = {
|
|
1738
|
+
"@type": "StateChange",
|
|
1739
|
+
changed: { [accountId]: filtered },
|
|
1740
|
+
};
|
|
1741
|
+
this.writeToStream(state, `event: state\ndata: ${JSON.stringify(stateChange)}\n\n`);
|
|
1742
|
+
if (state.closeAfterState) {
|
|
1743
|
+
this.closeStream(state);
|
|
834
1744
|
}
|
|
835
1745
|
}
|
|
836
1746
|
}
|
|
837
|
-
/**
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
1747
|
+
/**
|
|
1748
|
+
* Emits a StateChange after a mutating JMAP request, covering backends
|
|
1749
|
+
* whose change feed only reports out-of-band mutations. Deduplicated
|
|
1750
|
+
* against feed-driven pushes via the per-stream state tracking.
|
|
1751
|
+
*/
|
|
1752
|
+
async pushAfterMutation(account) {
|
|
1753
|
+
if (!this.eventStreams.size) {
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
const [emails, mailboxes, threads] = await Promise.all([
|
|
1757
|
+
this.backend.getEmails(account.accountId, []),
|
|
1758
|
+
this.backend.getMailboxes(account.accountId, []),
|
|
1759
|
+
this.backend.getThreads(account.accountId, []),
|
|
1760
|
+
]);
|
|
1761
|
+
this.pushStateChange(account.accountId, {
|
|
1762
|
+
Email: emails.state,
|
|
1763
|
+
Thread: threads.state,
|
|
1764
|
+
Mailbox: mailboxes.state,
|
|
845
1765
|
});
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
1766
|
+
}
|
|
1767
|
+
// ======================
|
|
1768
|
+
// node req/res adapter
|
|
1769
|
+
// ======================
|
|
1770
|
+
nodeRequestBody(req) {
|
|
1771
|
+
let closed = false;
|
|
1772
|
+
let cleanup = () => { };
|
|
1773
|
+
return new ReadableStream({
|
|
1774
|
+
start(controller) {
|
|
1775
|
+
req.pause();
|
|
1776
|
+
const onData = (chunk) => {
|
|
1777
|
+
if (closed)
|
|
1778
|
+
return;
|
|
1779
|
+
controller.enqueue(new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
1780
|
+
if ((controller.desiredSize ?? 0) <= 0)
|
|
1781
|
+
req.pause();
|
|
1782
|
+
};
|
|
1783
|
+
const onEnd = () => {
|
|
1784
|
+
if (closed)
|
|
1785
|
+
return;
|
|
1786
|
+
closed = true;
|
|
1787
|
+
cleanup();
|
|
1788
|
+
controller.close();
|
|
1789
|
+
};
|
|
1790
|
+
const onAborted = () => {
|
|
1791
|
+
if (closed)
|
|
1792
|
+
return;
|
|
1793
|
+
closed = true;
|
|
1794
|
+
cleanup();
|
|
1795
|
+
controller.error(new Error("Request body stream was aborted."));
|
|
1796
|
+
};
|
|
1797
|
+
const onError = (error) => {
|
|
1798
|
+
if (closed)
|
|
1799
|
+
return;
|
|
1800
|
+
closed = true;
|
|
1801
|
+
cleanup();
|
|
1802
|
+
controller.error(error);
|
|
1803
|
+
};
|
|
1804
|
+
cleanup = () => {
|
|
1805
|
+
req.off("data", onData);
|
|
1806
|
+
req.off("end", onEnd);
|
|
1807
|
+
req.off("aborted", onAborted);
|
|
1808
|
+
req.off("error", onError);
|
|
1809
|
+
};
|
|
1810
|
+
req.on("data", onData);
|
|
1811
|
+
req.once("end", onEnd);
|
|
1812
|
+
req.once("aborted", onAborted);
|
|
1813
|
+
req.once("error", onError);
|
|
857
1814
|
},
|
|
1815
|
+
pull() {
|
|
1816
|
+
if (!closed)
|
|
1817
|
+
req.resume();
|
|
1818
|
+
},
|
|
1819
|
+
cancel() {
|
|
1820
|
+
if (closed)
|
|
1821
|
+
return;
|
|
1822
|
+
closed = true;
|
|
1823
|
+
cleanup();
|
|
1824
|
+
// Drain without buffering so the response can reuse the connection.
|
|
1825
|
+
req.resume();
|
|
1826
|
+
},
|
|
1827
|
+
});
|
|
1828
|
+
}
|
|
1829
|
+
async handleNodeRequest(req, res, requestAbortController) {
|
|
1830
|
+
const abortRequest = (reason) => {
|
|
1831
|
+
if (!requestAbortController.signal.aborted) {
|
|
1832
|
+
requestAbortController.abort(reason);
|
|
1833
|
+
}
|
|
858
1834
|
};
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
1835
|
+
const onRequestAborted = () => {
|
|
1836
|
+
abortRequest(new Error("Node request was aborted by the client."));
|
|
1837
|
+
};
|
|
1838
|
+
const onRequestError = (error) => {
|
|
1839
|
+
abortRequest(error);
|
|
1840
|
+
};
|
|
1841
|
+
const onRequestClose = () => {
|
|
1842
|
+
// IncomingMessage emits close after normal completion too. Only a
|
|
1843
|
+
// close before the complete HTTP message is a transport abort.
|
|
1844
|
+
if (!req.complete)
|
|
1845
|
+
onRequestAborted();
|
|
1846
|
+
};
|
|
1847
|
+
const onResponseClose = () => {
|
|
1848
|
+
if (!res.writableEnded) {
|
|
1849
|
+
abortRequest(new Error("Node response connection closed before completion."));
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
req.once("aborted", onRequestAborted);
|
|
1853
|
+
req.once("error", onRequestError);
|
|
1854
|
+
req.once("close", onRequestClose);
|
|
1855
|
+
res.once("close", onResponseClose);
|
|
1856
|
+
try {
|
|
1857
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
1858
|
+
const headers = new Headers();
|
|
1859
|
+
const skippedHeaders = new Set([
|
|
1860
|
+
"connection",
|
|
1861
|
+
"expect",
|
|
1862
|
+
"keep-alive",
|
|
1863
|
+
"proxy-connection",
|
|
1864
|
+
"transfer-encoding",
|
|
1865
|
+
"upgrade",
|
|
1866
|
+
]);
|
|
1867
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
1868
|
+
if (value === undefined || skippedHeaders.has(key.toLowerCase())) {
|
|
1869
|
+
continue;
|
|
1870
|
+
}
|
|
1871
|
+
headers.set(key, Array.isArray(value) ? value.join(", ") : value);
|
|
1872
|
+
}
|
|
1873
|
+
const host = req.headers.host ?? "127.0.0.1";
|
|
1874
|
+
const requestInit = {
|
|
1875
|
+
method,
|
|
1876
|
+
headers,
|
|
1877
|
+
signal: requestAbortController.signal,
|
|
1878
|
+
};
|
|
1879
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
1880
|
+
requestInit.body = this.nodeRequestBody(req);
|
|
1881
|
+
requestInit.duplex = "half";
|
|
1882
|
+
}
|
|
1883
|
+
const request = new Request(`http://${host}${req.url ?? "/"}`, requestInit);
|
|
1884
|
+
const response = await this.fetchHandler(request);
|
|
1885
|
+
const responseHeaders = {};
|
|
1886
|
+
response.headers.forEach((value, key) => {
|
|
1887
|
+
responseHeaders[key] = value;
|
|
1888
|
+
});
|
|
1889
|
+
res.writeHead(response.status, responseHeaders);
|
|
1890
|
+
if (!response.body) {
|
|
1891
|
+
res.end();
|
|
1892
|
+
return;
|
|
863
1893
|
}
|
|
1894
|
+
const reader = response.body.getReader();
|
|
1895
|
+
let clientClosed = false;
|
|
1896
|
+
res.on("close", () => {
|
|
1897
|
+
clientClosed = true;
|
|
1898
|
+
// Cancelling the reader triggers the stream's cancel handler, which
|
|
1899
|
+
// releases any per-stream resources (SSE registration, ping timer).
|
|
1900
|
+
void reader.cancel().catch(() => { });
|
|
1901
|
+
});
|
|
864
1902
|
try {
|
|
865
|
-
|
|
1903
|
+
while (true) {
|
|
1904
|
+
const { done, value } = await reader.read();
|
|
1905
|
+
if (done || clientClosed || res.destroyed) {
|
|
1906
|
+
break;
|
|
1907
|
+
}
|
|
1908
|
+
res.write(value);
|
|
1909
|
+
}
|
|
866
1910
|
}
|
|
867
1911
|
catch {
|
|
868
|
-
|
|
1912
|
+
// stream cancelled or connection gone
|
|
1913
|
+
}
|
|
1914
|
+
if (!res.destroyed) {
|
|
1915
|
+
res.end();
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
catch (error) {
|
|
1919
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1920
|
+
if (!res.headersSent) {
|
|
1921
|
+
res.writeHead(500, { "content-type": "application/problem+json" });
|
|
869
1922
|
}
|
|
1923
|
+
res.end(JSON.stringify({ type: "about:blank", status: 500, detail: message }));
|
|
870
1924
|
}
|
|
1925
|
+
finally {
|
|
1926
|
+
req.off("aborted", onRequestAborted);
|
|
1927
|
+
req.off("error", onRequestError);
|
|
1928
|
+
req.off("close", onRequestClose);
|
|
1929
|
+
res.off("close", onResponseClose);
|
|
1930
|
+
}
|
|
1931
|
+
}
|
|
1932
|
+
// ======================
|
|
1933
|
+
// shared validators + responses
|
|
1934
|
+
// ======================
|
|
1935
|
+
validateProperties(requested, known) {
|
|
1936
|
+
if (requested === null || requested === undefined) {
|
|
1937
|
+
return null;
|
|
1938
|
+
}
|
|
1939
|
+
if (!Array.isArray(requested)) {
|
|
1940
|
+
throw new JmapServerMethodError("invalidArguments", "properties must be an array or null.");
|
|
1941
|
+
}
|
|
1942
|
+
for (const property of requested) {
|
|
1943
|
+
if (typeof property !== "string" || !known.has(property)) {
|
|
1944
|
+
throw new JmapServerMethodError("invalidArguments", `Unknown property "${String(property)}".`);
|
|
1945
|
+
}
|
|
1946
|
+
}
|
|
1947
|
+
return requested.includes("id") ? requested : ["id", ...requested];
|
|
1948
|
+
}
|
|
1949
|
+
projectObject(source, properties) {
|
|
1950
|
+
const projected = {};
|
|
1951
|
+
for (const property of properties) {
|
|
1952
|
+
projected[property] = source[property] === undefined
|
|
1953
|
+
? null
|
|
1954
|
+
: source[property];
|
|
1955
|
+
}
|
|
1956
|
+
return projected;
|
|
1957
|
+
}
|
|
1958
|
+
validatePosition(args) {
|
|
1959
|
+
if (args.position === undefined || args.position === null) {
|
|
1960
|
+
return 0;
|
|
1961
|
+
}
|
|
1962
|
+
if (!Number.isInteger(args.position) || args.position < 0) {
|
|
1963
|
+
throw new JmapServerMethodError("invalidArguments", "position must be a non-negative integer.");
|
|
1964
|
+
}
|
|
1965
|
+
return args.position;
|
|
1966
|
+
}
|
|
1967
|
+
validateChangesArgs(args) {
|
|
1968
|
+
if (typeof args.sinceState !== "string") {
|
|
1969
|
+
throw new JmapServerMethodError("invalidArguments", "sinceState is required.");
|
|
1970
|
+
}
|
|
1971
|
+
let maxChanges;
|
|
1972
|
+
if (args.maxChanges !== undefined && args.maxChanges !== null) {
|
|
1973
|
+
if (!Number.isInteger(args.maxChanges) || args.maxChanges <= 0) {
|
|
1974
|
+
throw new JmapServerMethodError("invalidArguments", "maxChanges must be a positive integer.");
|
|
1975
|
+
}
|
|
1976
|
+
maxChanges = args.maxChanges;
|
|
1977
|
+
}
|
|
1978
|
+
return { sinceState: args.sinceState, maxChanges };
|
|
1979
|
+
}
|
|
1980
|
+
jsonResponse(status, body) {
|
|
1981
|
+
return new Response(JSON.stringify(body), {
|
|
1982
|
+
status,
|
|
1983
|
+
headers: { "content-type": "application/json" },
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
problemResponse(status, type, detail, extraHeaders = {}) {
|
|
1987
|
+
return new Response(JSON.stringify({ type, status, detail }), {
|
|
1988
|
+
status,
|
|
1989
|
+
headers: { "content-type": "application/problem+json", ...extraHeaders },
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1992
|
+
limitResponse(status, limit, detail) {
|
|
1993
|
+
return new Response(JSON.stringify({
|
|
1994
|
+
type: "urn:ietf:params:jmap:error:limit",
|
|
1995
|
+
limit,
|
|
1996
|
+
status,
|
|
1997
|
+
detail,
|
|
1998
|
+
}), { status, headers: { "content-type": "application/problem+json" } });
|
|
871
1999
|
}
|
|
872
2000
|
}
|
|
873
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFtRWxELDBGQUEwRjtBQUMxRixNQUFNLHFCQUFzQixTQUFRLEtBQUs7SUFDdkMsWUFBbUIsSUFBWSxFQUFFLFdBQW9CO1FBQ25ELEtBQUssQ0FBQyxXQUFXLElBQUksSUFBSSxDQUFDLENBQUM7UUFEVixTQUFJLEdBQUosSUFBSSxDQUFRO0lBRS9CLENBQUM7Q0FDRjtBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFNckI7UUFMTyxVQUFLLEdBQWlDLElBQUksR0FBRyxFQUFFLENBQUM7UUFFL0MsWUFBTyxHQUE0QixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQzdDLGlCQUFZLEdBQXNELElBQUksR0FBRyxFQUFFLENBQUM7UUFHbEYsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRTtZQUNuRCxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUMvQixDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLFlBQVksRUFBRSxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3RDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRTtnQkFDdEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDOUIsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsbUJBQW1CO0lBQ25CLHlCQUF5QjtJQUVsQixPQUFPLENBQUMsUUFBZ0IsRUFBRSxRQUFnQjtRQUMvQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLEtBQUssQ0FBQyxTQUFTLFFBQVEsbUJBQW1CLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLFFBQVEsY0FBYyxDQUFDO1FBQzVFLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRTtZQUN2QixRQUFRO1lBQ1IsUUFBUTtZQUNSLFlBQVksRUFBRSxJQUFJLEdBQUcsRUFBRTtZQUN2QixTQUFTLEVBQUUsV0FBVyxRQUFRLEVBQUU7WUFDaEMsU0FBUyxFQUFFLElBQUksR0FBRyxFQUFFO1lBQ3BCLE1BQU0sRUFBRSxJQUFJLEdBQUcsRUFBRTtZQUNqQixLQUFLLEVBQUUsSUFBSSxHQUFHLEVBQUU7WUFDaEIsV0FBVyxFQUFFLElBQUksR0FBRyxFQUFFO1lBQ3RCLFVBQVUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFDM0UsS0FBSyxFQUFFLENBQUM7WUFDUixPQUFPLEVBQUUsRUFBRTtZQUNYLFNBQVMsRUFBRSxDQUFDO1NBQ2IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELGlEQUFpRDtJQUMxQyxjQUFjLENBQUMsUUFBZ0IsRUFBRSxLQUFhO1FBQ25ELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUVNLGFBQWEsQ0FBQyxRQUFnQixFQUFFLElBQVksRUFBRSxJQUFhO1FBQ2hFLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDeEMsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7WUFDOUMsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLFlBQVksSUFBSSw4QkFBOEIsUUFBUSxJQUFJLENBQUMsQ0FBQztZQUM5RSxDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sRUFBRSxHQUFHLFdBQVcsRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFO1lBQ3JCLEVBQUU7WUFDRixJQUFJO1lBQ0osSUFBSSxFQUFFLElBQUksSUFBSSxJQUFJO1lBQ2xCLFFBQVEsRUFBRSxJQUFJO1lBQ2QsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSTtTQUMvQixDQUFDLENBQUM7UUFDSCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFFRCx3R0FBd0c7SUFDakcsUUFBUSxDQUFDLFFBQWdCLEVBQUUsV0FBbUIsRUFBRSxLQUE0QjtRQUNqRixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FDdEQsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssV0FBVyxJQUFJLFNBQVMsQ0FBQyxJQUFJLEtBQUssV0FBVyxDQUNoRixDQUFDO1FBQ0YsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2IsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLFdBQVcsOEJBQThCLFFBQVEsSUFBSSxDQUFDLENBQUM7UUFDckYsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNuRSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDM0QsTUFBTSxFQUFFLEdBQUcsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QyxNQUFNLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLElBQUksSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDaEUsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUM7UUFFdEMsb0RBQW9EO1FBQ3BELE1BQU0sTUFBTSxHQUFHLFFBQVEsRUFBRSxFQUFFLENBQUM7UUFDNUIsTUFBTSxRQUFRLEdBQUc7WUFDZixTQUFTLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDMUQsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3RELFlBQVksS0FBSyxDQUFDLE9BQU8sSUFBSSxFQUFFLEVBQUU7WUFDakMsU0FBUyxVQUFVLEVBQUU7WUFDckIsRUFBRTtZQUNGLFFBQVE7U0FDVCxDQUFDO1FBQ0YsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFO1lBQ3JCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO1lBQ2hELElBQUksRUFBRSxnQkFBZ0I7WUFDdEIsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNO1NBQ2xCLENBQUMsQ0FBQztRQUVILE1BQU0sVUFBVSxHQUE0RDtZQUMxRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUU7U0FDOUMsQ0FBQztRQUNGLE1BQU0sYUFBYSxHQUFHLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxZQUFZLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3RGLE1BQU0sYUFBYSxHQUErQixFQUFFLENBQUM7UUFDckQsSUFBSSxPQUFPLEtBQUssQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdkMsVUFBVSxDQUFDLElBQUksR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRSxhQUFhLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDekYsQ0FBQztRQUVELE1BQU0sZUFBZSxHQUErQixFQUFFLENBQUM7UUFDdkQsS0FBSyxNQUFNLENBQUMsS0FBSyxFQUFFLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDO1lBQ3RFLE1BQU0sZ0JBQWdCLEdBQUcsUUFBUSxFQUFFLE9BQU8sS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQWMsQ0FBQyxDQUFDO1lBQ3BELElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLGdCQUFnQixFQUFFO2dCQUMvQixJQUFJO2dCQUNKLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtnQkFDckIsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO2FBQ3RCLENBQUMsQ0FBQztZQUNILGVBQWUsQ0FBQyxJQUFJLENBQUM7Z0JBQ25CLE1BQU0sRUFBRSxJQUFJO2dCQUNaLE1BQU0sRUFBRSxnQkFBZ0I7Z0JBQ3hCLElBQUksRUFBRSxVQUFVLENBQUMsSUFBSTtnQkFDckIsSUFBSSxFQUFFLFVBQVUsQ0FBQyxJQUFJO2dCQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLE1BQU07Z0JBQ2pCLFdBQVcsRUFBRSxZQUFZO2FBQzFCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFFRCxNQUFNLEtBQUssR0FBd0I7WUFDakMsRUFBRTtZQUNGLE1BQU07WUFDTixRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUU7WUFDeEIsVUFBVSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFO1lBQ2xDLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUSxJQUFJLEVBQUU7WUFDOUIsSUFBSSxFQUFFLFFBQVEsQ0FBQyxNQUFNO1lBQ3JCLFVBQVU7WUFDVixNQUFNLEVBQUUsVUFBVTtZQUNsQixPQUFPLEVBQUUsS0FBSyxDQUFDLE9BQU8sSUFBSSxJQUFJO1lBQzlCLElBQUk7WUFDSixFQUFFO1lBQ0YsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFLElBQUksSUFBSTtZQUNwQixHQUFHLEVBQUUsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJO1lBQ3RCLE9BQU8sRUFBRSxJQUFJO1lBQ2IsYUFBYSxFQUFFLGVBQWUsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUN6QyxPQUFPLEVBQUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDO1lBQy9CLFVBQVU7WUFDVixRQUFRLEVBQUUsYUFBYTtZQUN2QixRQUFRLEVBQUUsYUFBYTtZQUN2QixXQUFXLEVBQUUsZUFBZTtTQUM3QixDQUFDO1FBQ0YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzNCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3hDLE9BQU8sRUFBRSxDQUFDO0lBQ1osQ0FBQztJQUVELHlCQUF5QjtJQUN6QixZQUFZO0lBQ1oseUJBQXlCO0lBRXpCLHNGQUFzRjtJQUMvRSxLQUFLLENBQUMsSUFBWTtRQUN2QixPQUFPLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO1lBQ3JDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO2dCQUM1QixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUN0QyxNQUFNLFNBQVMsR0FDYixPQUFPLE9BQU8sS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBQy9ELE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNyQixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELG1GQUFtRjtJQUM1RSxJQUFJO1FBQ1QsS0FBSyxNQUFNLFFBQVEsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDO2dCQUNILFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUNqQixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLHdCQUF3QjtZQUMxQixDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDMUIsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUU7Z0JBQ3JCLE9BQU8sRUFBRSxDQUFDO1lBQ1osQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsZ0JBQWdCO0lBQ2hCLHlCQUF5QjtJQUVqQixhQUFhLENBQUMsR0FBaUMsRUFBRSxHQUFnQztRQUN2RixJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3BDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDVixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRTtvQkFDakIsa0JBQWtCLEVBQUUseUNBQXlDO29CQUM3RCxjQUFjLEVBQUUsMEJBQTBCO2lCQUMzQyxDQUFDLENBQUM7Z0JBQ0gsR0FBRyxDQUFDLEdBQUcsQ0FDTCxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSx5QkFBeUIsRUFBRSxDQUFDLENBQ3hGLENBQUM7Z0JBQ0YsT0FBTztZQUNULENBQUM7WUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLEdBQUcsRUFBRSxrQkFBa0IsQ0FBQyxDQUFDO1lBQ3hELE1BQU0sUUFBUSxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUM7WUFFOUIsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLEtBQUssSUFBSSxDQUFDLFFBQVEsS0FBSyxtQkFBbUIsSUFBSSxRQUFRLEtBQUssZUFBZSxDQUFDLEVBQUUsQ0FBQztnQkFDL0YsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQzlCLE9BQU87WUFDVCxDQUFDO1lBQ0QsSUFBSSxHQUFHLENBQUMsTUFBTSxLQUFLLE1BQU0sSUFBSSxRQUFRLEtBQUssV0FBVyxFQUFFLENBQUM7Z0JBQ3RELElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztnQkFDZCxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO29CQUN2QixJQUFJLElBQUksS0FBSyxDQUFDO2dCQUNoQixDQUFDLENBQUMsQ0FBQztnQkFDSCxHQUFHLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUU7b0JBQ2pCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDbEMsQ0FBQyxDQUFDLENBQUM7Z0JBQ0gsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLFFBQVEsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO2dCQUM3RCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQztnQkFDdkMsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLEdBQUcsQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLFFBQVEsQ0FBQyxVQUFVLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO2dCQUNuRSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUM5QyxPQUFPO1lBQ1QsQ0FBQztZQUVELEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLDBCQUEwQixFQUFFLENBQUMsQ0FBQztZQUNuRSxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNyRixDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFDO2dCQUNyQixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSwwQkFBMEIsRUFBRSxDQUFDLENBQUM7WUFDckUsQ0FBQztZQUNELEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ2pGLENBQUM7SUFDSCxDQUFDO0lBRU8sWUFBWSxDQUFDLEdBQWlDO1FBQ3BELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDO1FBQ3pDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN0QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN6RCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsRCxJQUFJLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQztnQkFDdkMsSUFBSSxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUNqQyxPQUFPLElBQUksQ0FBQztnQkFDZCxDQUFDO1lBQ0gsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELElBQUksTUFBTSxLQUFLLE9BQU8sRUFBRSxDQUFDO1lBQ3ZCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUM5RCxNQUFNLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3hDLElBQUksVUFBVSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQy9DLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RDLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3ZDLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLGFBQWEsQ0FBQyxJQUFxQixFQUFFLEdBQWdDO1FBQzNFLE1BQU0sT0FBTyxHQUFHO1lBQ2QsWUFBWSxFQUFFO2dCQUNaLDJCQUEyQixFQUFFO29CQUMzQixhQUFhLEVBQUUsVUFBVTtvQkFDekIsbUJBQW1CLEVBQUUsQ0FBQztvQkFDdEIsY0FBYyxFQUFFLFVBQVU7b0JBQzFCLHFCQUFxQixFQUFFLENBQUM7b0JBQ3hCLGlCQUFpQixFQUFFLEVBQUU7b0JBQ3JCLGVBQWUsRUFBRSxHQUFHO29CQUNwQixlQUFlLEVBQUUsR0FBRztvQkFDcEIsbUJBQW1CLEVBQUUsQ0FBQyxpQkFBaUIsRUFBRSxpQkFBaUIsQ0FBQztpQkFDNUQ7Z0JBQ0QsMkJBQTJCLEVBQUUsRUFBRTtnQkFDL0IsaUNBQWlDLEVBQUUsRUFBRTthQUN0QztZQUNELFFBQVEsRUFBRTtnQkFDUixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRTtvQkFDaEIsSUFBSSxFQUFFLElBQUksQ0FBQyxRQUFRO29CQUNuQixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsVUFBVSxFQUFFLEtBQUs7b0JBQ2pCLG1CQUFtQixFQUFFO3dCQUNuQiwyQkFBMkIsRUFBRSxFQUFFO3dCQUMvQixpQ0FBaUMsRUFBRSxFQUFFO3FCQUN0QztpQkFDRjthQUNGO1lBQ0QsZUFBZSxFQUFFO2dCQUNmLDJCQUEyQixFQUFFLElBQUksQ0FBQyxTQUFTO2dCQUMzQywyQkFBMkIsRUFBRSxJQUFJLENBQUMsU0FBUztnQkFDM0MsaUNBQWlDLEVBQUUsSUFBSSxDQUFDLFNBQVM7YUFDbEQ7WUFDRCxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsTUFBTSxFQUFFLFdBQVc7WUFDbkIsV0FBVyxFQUFFLHdEQUF3RDtZQUNyRSxTQUFTLEVBQUUsMEJBQTBCO1lBQ3JDLGNBQWMsRUFBRSxxRUFBcUU7WUFDckYsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1NBQzFCLENBQUM7UUFDRixHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxrQkFBa0IsRUFBRSxDQUFDLENBQUM7UUFDM0QsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVPLFNBQVMsQ0FBQyxJQUFxQixFQUFFLElBQVksRUFBRSxHQUFnQztRQUNyRixJQUFJLE1BQVcsQ0FBQztRQUNoQixJQUFJLENBQUM7WUFDSCxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM1QixDQUFDO1FBQUMsTUFBTSxDQUFDO1lBQ1AsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxDQUFDO1lBQ25FLEdBQUcsQ0FBQyxHQUFHLENBQ0wsSUFBSSxDQUFDLFNBQVMsQ0FBQztnQkFDYixJQUFJLEVBQUUsb0NBQW9DO2dCQUMxQyxNQUFNLEVBQUUsR0FBRztnQkFDWCxNQUFNLEVBQUUscUNBQXFDO2FBQzlDLENBQUMsQ0FDSCxDQUFDO1lBQ0YsT0FBTztRQUNULENBQUM7UUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUN4QyxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSwwQkFBMEIsRUFBRSxDQUFDLENBQUM7WUFDbkUsR0FBRyxDQUFDLEdBQUcsQ0FDTCxJQUFJLENBQUMsU0FBUyxDQUFDO2dCQUNiLElBQUksRUFBRSx1Q0FBdUM7Z0JBQzdDLE1BQU0sRUFBRSxHQUFHO2dCQUNYLE1BQU0sRUFBRSxzREFBc0Q7YUFDL0QsQ0FBQyxDQUNILENBQUM7WUFDRixPQUFPO1FBQ1QsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO1FBQzdDLE1BQU0sZUFBZSxHQUFpRCxFQUFFLENBQUM7UUFDekUsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDdEMsTUFBTSxDQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsSUFBNkMsQ0FBQztZQUNqRixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksSUFBSSxFQUFFLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQzdFLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7WUFDckQsQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxLQUFLLFlBQVkscUJBQXFCLEVBQUUsQ0FBQztvQkFDM0MsZUFBZSxDQUFDLElBQUksQ0FBQzt3QkFDbkIsT0FBTzt3QkFDUCxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFO3dCQUNoRCxNQUFNO3FCQUNQLENBQUMsQ0FBQztnQkFDTCxDQUFDO3FCQUFNLENBQUM7b0JBQ04sTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN2RSxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDeEYsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBRUQsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBQzNELEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLGVBQWUsRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNqRixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLElBQXFCLEVBQ3JCLEdBQWlDLEVBQ2pDLEdBQWdDO1FBRWhDLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ2pCLGNBQWMsRUFBRSxtQkFBbUI7WUFDbkMsZUFBZSxFQUFFLFVBQVU7WUFDM0IsVUFBVSxFQUFFLFlBQVk7U0FDekIsQ0FBQyxDQUFDO1FBQ0gsR0FBRyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7WUFDbkIsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sY0FBYyxDQUNwQixJQUFxQixFQUNyQixRQUFnQixFQUNoQixHQUFRLEVBQ1IsR0FBZ0M7UUFFaEMsNkNBQTZDO1FBQzdDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdFLE1BQU0sU0FBUyxHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUN4RCxNQUFNLE1BQU0sR0FBRyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDckQsSUFBSSxTQUFTLEtBQUssSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2pDLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLEVBQUUsY0FBYyxFQUFFLDBCQUEwQixFQUFFLENBQUMsQ0FBQztZQUNuRSxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLGlCQUFpQixFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3pGLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDcEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxDQUFDO1lBQ25FLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsY0FBYyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQ3RGLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztRQUN2RCxHQUFHLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLGNBQWMsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ2pGLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3JCLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsdUJBQXVCO0lBQ3ZCLHlCQUF5QjtJQUVqQixjQUFjLENBQ3BCLElBQXFCLEVBQ3JCLFVBQWtCLEVBQ2xCLElBQXlCLEVBQ3pCLFVBQStCO1FBRS9CLFFBQVEsVUFBVSxFQUFFLENBQUM7WUFDbkIsS0FBSyxXQUFXO2dCQUNkLE9BQU8sSUFBSSxDQUFDO1lBQ2QsS0FBSyxhQUFhO2dCQUNoQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDM0MsS0FBSyxlQUFlO2dCQUNsQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDN0MsS0FBSyxXQUFXO2dCQUNkLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDekMsS0FBSyxhQUFhO2dCQUNoQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDM0MsS0FBSyxlQUFlO2dCQUNsQixPQUFPLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDN0MsS0FBSyxXQUFXO2dCQUNkLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO1lBQ3JELEtBQUssY0FBYztnQkFDakIsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEMsS0FBSyxxQkFBcUI7Z0JBQ3hCLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDL0Q7Z0JBQ0UsTUFBTSxJQUFJLHFCQUFxQixDQUFDLGVBQWUsRUFBRSxtQkFBbUIsVUFBVSxJQUFJLENBQUMsQ0FBQztRQUN4RixDQUFDO0lBQ0gsQ0FBQztJQUVPLGdCQUFnQixDQUFDLElBQXFCLEVBQUUsSUFBeUI7UUFDdkUsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDaEQsSUFBSSxJQUEwQixDQUFDO1FBQy9CLE1BQU0sUUFBUSxHQUFhLEVBQUUsQ0FBQztRQUM5QixJQUFJLElBQUksQ0FBQyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7WUFDckIsSUFBSSxHQUFHLEdBQUcsQ0FBQztRQUNiLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNWLEtBQUssTUFBTSxFQUFFLElBQUksSUFBSSxDQUFDLEdBQWUsRUFBRSxDQUFDO2dCQUN0QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDdkMsSUFBSSxPQUFPLEVBQUUsQ0FBQztvQkFDWixJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUNyQixDQUFDO3FCQUFNLENBQUM7b0JBQ04sUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3JDLE1BQU0sTUFBTSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FDcEQsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQzFDLENBQUM7WUFDRixPQUFPO2dCQUNMLEdBQUcsT0FBTztnQkFDVixXQUFXLEVBQUUsTUFBTSxDQUFDLE1BQU07Z0JBQzFCLFlBQVksRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUMsTUFBTTtnQkFDckUsWUFBWSxFQUFFLE1BQU0sQ0FBQyxNQUFNO2dCQUMzQixhQUFhLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxFQUFFLEtBQUssQ0FBQyxDQUFDLE1BQU07Z0JBQ3RFLFFBQVEsRUFBRTtvQkFDUixZQUFZLEVBQUUsSUFBSTtvQkFDbEIsV0FBVyxFQUFFLElBQUk7b0JBQ2pCLGNBQWMsRUFBRSxJQUFJO29CQUNwQixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsY0FBYyxFQUFFLElBQUk7b0JBQ3BCLGNBQWMsRUFBRSxJQUFJO29CQUNwQixTQUFTLEVBQUUsSUFBSTtvQkFDZixTQUFTLEVBQUUsSUFBSTtvQkFDZixTQUFTLEVBQUUsSUFBSTtpQkFDaEI7Z0JBQ0QsWUFBWSxFQUFFLElBQUk7YUFDbkIsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixLQUFLLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7WUFDekIsSUFBSSxFQUFFLFNBQVM7WUFDZixRQUFRO1NBQ1QsQ0FBQztJQUNKLENBQUM7SUFFTyxrQkFBa0IsQ0FBQyxJQUFxQixFQUFFLElBQXlCO1FBQ3pFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ2pDLElBQUksU0FBUyxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3BELElBQUksT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBQ0QsSUFBSSxPQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDcEMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFDRCxNQUFNLEdBQUcsR0FBRyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDbkQsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixVQUFVLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7WUFDOUIsbUJBQW1CLEVBQUUsS0FBSztZQUMxQixRQUFRLEVBQUUsQ0FBQztZQUNYLEdBQUc7WUFDSCxLQUFLLEVBQUUsR0FBRyxDQUFDLE1BQU07U0FDbEIsQ0FBQztJQUNKLENBQUM7SUFFTyxjQUFjLENBQUMsSUFBcUIsRUFBRSxJQUF5QjtRQUNyRSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3QixNQUFNLElBQUkscUJBQXFCLENBQUMsa0JBQWtCLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztRQUMxRixDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQStCLEVBQUUsQ0FBQztRQUM1QyxNQUFNLFFBQVEsR0FBYSxFQUFFLENBQUM7UUFDOUIsS0FBSyxNQUFNLEVBQUUsSUFBSSxJQUFJLENBQUMsR0FBZSxFQUFFLENBQUM7WUFDdEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbEMsSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDViw2REFBNkQ7Z0JBQzdELHdEQUF3RDtnQkFDeEQsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQztZQUMxQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNwQixDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQ3pCLElBQUk7WUFDSixRQUFRO1NBQ1QsQ0FBQztJQUNKLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFxQixFQUFFLElBQXlCO1FBQ3ZFLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDO1FBQ2pDLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQzlDLElBQUksT0FBTyxNQUFNLENBQUMsU0FBUyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUNELElBQUksT0FBTyxNQUFNLENBQUMsT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FDL0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FDakYsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLE9BQU8sTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNwQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3pDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUNwQixDQUFDLEtBQUssRUFBRSxFQUFFLENBQ1IsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztnQkFDMUQsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQzdFLENBQUM7UUFDSixDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNoRixJQUFJLElBQUksRUFBRSxRQUFRLEtBQUssWUFBWSxFQUFFLENBQUM7WUFDcEMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDbkIsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hGLE9BQU8sSUFBSSxDQUFDLFdBQVcsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7WUFDL0QsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsT0FBTyxJQUFJLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZFLElBQUksR0FBRyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFZLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDcEUsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUM1QixJQUFJLE9BQU8sSUFBSSxDQUFDLEtBQUssS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUNuQyxHQUFHLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFDRCxPQUFPO1lBQ0wsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3pCLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUM5QixtQkFBbUIsRUFBRSxLQUFLO1lBQzFCLFFBQVE7WUFDUixHQUFHO1lBQ0gsS0FBSztTQUNOLENBQUM7SUFDSixDQUFDO0lBRU8sa0JBQWtCLENBQUMsSUFBcUIsRUFBRSxJQUF5QjtRQUN6RSxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ3RDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUMvRCxNQUFNLElBQUkscUJBQXFCLENBQzdCLHdCQUF3QixFQUN4Qix5Q0FBeUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUM3RCxDQUFDO1FBQ0osQ0FBQztRQUNELE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUNsQyxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ3BDLEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pDLElBQUksS0FBSyxDQUFDLEtBQUssSUFBSSxLQUFLLEVBQUUsQ0FBQztnQkFDekIsU0FBUztZQUNYLENBQUM7WUFDRCxLQUFLLE1BQU0sRUFBRSxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDL0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNsQixDQUFDO1lBQ0QsS0FBSyxNQUFNLEVBQUUsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDbEIsQ0FBQztZQUNELEtBQUssTUFBTSxFQUFFLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNqQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDcEIseURBQXlEO29CQUN6RCxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNyQixDQUFDO3FCQUFNLENBQUM7b0JBQ04sU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsQ0FBQztnQkFDRCxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxNQUFNLEVBQUUsSUFBSSxPQUFPLEVBQUUsQ0FBQztZQUN6QixPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3JCLENBQUM7UUFDRCxPQUFPO1lBQ0wsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTO1lBQ3pCLFFBQVEsRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDO1lBQ3ZCLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUM1QixjQUFjLEVBQUUsS0FBSztZQUNyQixPQUFPLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDNUIsT0FBTyxFQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQzVCLFNBQVMsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztTQUNqQyxDQUFDO0lBQ0osQ0FBQztJQUVPLGNBQWMsQ0FDcEIsSUFBcUIsRUFDckIsSUFBeUIsRUFDekIsVUFBK0I7UUFFL0IsTUFBTSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNwQyxNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sVUFBVSxHQUF3QixFQUFFLENBQUM7UUFDM0MsTUFBTSxPQUFPLEdBQXdCLEVBQUUsQ0FBQztRQUN4QyxNQUFNLFVBQVUsR0FBd0IsRUFBRSxDQUFDO1FBQzNDLE1BQU0sU0FBUyxHQUFhLEVBQUUsQ0FBQztRQUMvQixNQUFNLFlBQVksR0FBd0IsRUFBRSxDQUFDO1FBQzdDLE1BQU0sY0FBYyxHQUFhLEVBQUUsQ0FBQztRQUNwQyxNQUFNLGNBQWMsR0FBYSxFQUFFLENBQUM7UUFDcEMsTUFBTSxnQkFBZ0IsR0FBYSxFQUFFLENBQUM7UUFFdEMsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBd0IsQ0FBQyxFQUFFLENBQUM7WUFDNUYsSUFBSSxDQUFDO2dCQUNILE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7Z0JBQ25ELElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ2pDLFVBQVUsQ0FBQyxHQUFHLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDckMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7Z0JBQzlCLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRztvQkFDcEIsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFO29CQUNaLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtvQkFDcEIsUUFBUSxFQUFFLEtBQUssQ0FBQyxRQUFRO29CQUN4QixJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUk7aUJBQ2pCLENBQUM7WUFDSixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLE9BQU8sR0FBRyxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3ZFLFVBQVUsQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLENBQUM7WUFDL0UsQ0FBQztRQUNILENBQUM7UUFFRCxLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUF3QixDQUFDLEVBQUUsQ0FBQztZQUNyRixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1gsVUFBVSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLG1CQUFtQixFQUFFLENBQUM7Z0JBQ3BGLFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxDQUFDO2dCQUNILElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM5QixjQUFjLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUN4QixPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDO1lBQ3JCLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDdkUsVUFBVSxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLENBQUM7WUFDbEUsQ0FBQztRQUNILENBQUM7UUFFRCxLQUFLLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQWEsRUFBRSxDQUFDO1lBQ2xELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDM0IsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUMxQixTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3JCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixZQUFZLENBQUMsRUFBRSxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztZQUN4RixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksY0FBYyxDQUFDLE1BQU0sSUFBSSxjQUFjLENBQUMsTUFBTSxJQUFJLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFO2dCQUNuQixPQUFPLEVBQUUsY0FBYztnQkFDdkIsT0FBTyxFQUFFLGNBQWM7Z0JBQ3ZCLFNBQVMsRUFBRSxnQkFBZ0I7YUFDNUIsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztRQUVELE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsUUFBUTtZQUNSLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUM1QixPQUFPO1lBQ1AsVUFBVTtZQUNWLE9BQU87WUFDUCxVQUFVO1lBQ1YsU0FBUztZQUNULFlBQVk7U0FDYixDQUFDO0lBQ0osQ0FBQztJQUVPLGlCQUFpQixDQUFDLElBQXFCO1FBQzdDLE9BQU87WUFDTCxTQUFTLEVBQUUsSUFBSSxDQUFDLFNBQVM7WUFDekIsS0FBSyxFQUFFLEdBQUc7WUFDVixJQUFJLEVBQUUsSUFBSSxDQUFDLFVBQVU7WUFDckIsUUFBUSxFQUFFLEVBQUU7U0FDYixDQUFDO0lBQ0osQ0FBQztJQUVPLHdCQUF3QixDQUM5QixJQUFxQixFQUNyQixJQUF5QixFQUN6QixVQUErQjtRQUUvQixNQUFNLE9BQU8sR0FBd0IsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sVUFBVSxHQUF3QixFQUFFLENBQUM7UUFDM0MsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBd0IsQ0FBQyxFQUFFLENBQUM7WUFDNUYsSUFBSSxPQUFPLEdBQVcsSUFBSSxDQUFDLE9BQU8sQ0FBQztZQUNuQyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQzNELE1BQU0sUUFBUSxHQUFHLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNsRCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7b0JBQ2QsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHO3dCQUN2QixJQUFJLEVBQUUsbUJBQW1CO3dCQUN6QixXQUFXLEVBQUUsa0NBQWtDLE9BQU8sSUFBSTtxQkFDM0QsQ0FBQztvQkFDRixTQUFTO2dCQUNYLENBQUM7Z0JBQ0QsT0FBTyxHQUFHLFFBQVEsQ0FBQztZQUNyQixDQUFDO1lBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQzlCLFVBQVUsQ0FBQyxVQUFVLENBQUMsR0FBRztvQkFDdkIsSUFBSSxFQUFFLG1CQUFtQjtvQkFDekIsV0FBVyxFQUFFLFVBQVUsT0FBTyxtQkFBbUI7aUJBQ2xELENBQUM7Z0JBQ0YsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDdkYsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNkLFVBQVUsQ0FBQyxVQUFVLENBQUMsR0FBRztvQkFDdkIsSUFBSSxFQUFFLG1CQUFtQjtvQkFDekIsV0FBVyxFQUFFLGFBQWEsSUFBSSxDQUFDLFVBQVUsbUJBQW1CO2lCQUM3RCxDQUFDO2dCQUNGLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxFQUFFLEdBQUcsY0FBYyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUM1QyxNQUFNLFVBQVUsR0FBMEI7Z0JBQ3hDLEVBQUU7Z0JBQ0YsT0FBTztnQkFDUCxVQUFVLEVBQUUsUUFBUSxDQUFDLEVBQUU7Z0JBQ3ZCLFVBQVUsRUFBRSxPQUFPO2dCQUNuQixNQUFNLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUU7YUFDakMsQ0FBQztZQUNGLElBQUksQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQztZQUNyQyxPQUFPLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLFVBQVUsQ0FBQyxVQUFVLEVBQUUsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM3RixDQUFDO1FBQ0QsT0FBTztZQUNMLFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUztZQUN6QixRQUFRLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7WUFDNUIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQzVCLE9BQU87WUFDUCxVQUFVO1lBQ1YsT0FBTyxFQUFFLEVBQUU7WUFDWCxVQUFVLEVBQUUsRUFBRTtZQUNkLFNBQVMsRUFBRSxFQUFFO1lBQ2IsWUFBWSxFQUFFLEVBQUU7U0FDakIsQ0FBQztJQUNKLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsbUJBQW1CO0lBQ25CLHlCQUF5QjtJQUVqQixXQUFXLENBQUMsUUFBZ0I7UUFDbEMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxTQUFTLFFBQVEsbUJBQW1CLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sbUJBQW1CLENBQUMsSUFBcUIsRUFBRSxJQUF5QjtRQUMxRSxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBaUQsQ0FBQztRQUMxRSxJQUFJLENBQUMsVUFBVSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNuRCxNQUFNLElBQUksS0FBSyxDQUFDLG1DQUFtQyxDQUFDLENBQUM7UUFDdkQsQ0FBQztRQUNELEtBQUssTUFBTSxTQUFTLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO2dCQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLFlBQVksU0FBUyxtQkFBbUIsQ0FBQyxDQUFDO1lBQzVELENBQUM7UUFDSCxDQUFDO1FBQ0QsTUFBTSxFQUFFLEdBQUcsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN2QyxNQUFNLFVBQVUsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzVDLE1BQU0sVUFBVSxHQUFHLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQXNDLENBQUM7UUFDaEYsTUFBTSxXQUFXLEdBQUcsQ0FBQyxJQUF5QixFQUFVLEVBQUUsQ0FDeEQsSUFBSSxFQUFFLE1BQU0sSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ25FLE1BQU0sYUFBYSxHQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQWdDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3pGLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUk7WUFDM0IsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLElBQUksWUFBWTtZQUMvQixJQUFJLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU07U0FDL0IsQ0FBQyxDQUFDLENBQUM7UUFDSixNQUFNLGFBQWEsR0FBSSxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFnQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQztZQUN6RixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJO1lBQzNCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxJQUFJLFdBQVc7WUFDOUIsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNO1NBQy9CLENBQUMsQ0FBQyxDQUFDO1FBQ0osTUFBTSxTQUFTLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLEVBQUUsS0FBSyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUVyRyxNQUFNLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUF3QixDQUFDO1FBQ3RELE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQXdCLENBQUM7UUFDbEQsTUFBTSxNQUFNLEdBQUcsUUFBUSxFQUFFLEVBQUUsQ0FBQztRQUM1QixNQUFNLFFBQVEsR0FBRztZQUNmLFNBQVMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUMxRCxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDdEQsWUFBWSxJQUFJLENBQUMsT0FBTyxJQUFJLEVBQUUsRUFBRTtZQUNoQyxTQUFTLFVBQVUsRUFBRTtZQUNyQixFQUFFO1lBQ0YsU0FBUztTQUNWLENBQUM7UUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUU7WUFDckIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUM7WUFDaEQsSUFBSSxFQUFFLGdCQUFnQjtZQUN0QixJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU07U0FDbEIsQ0FBQyxDQUFDO1FBRUgsTUFBTSxvQkFBb0IsR0FBNEQsRUFBRSxDQUFDO1FBQ3pGLEtBQUssTUFBTSxDQUFDLE1BQU0sRUFBRSxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDN0Qsb0JBQW9CLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUssSUFBSSxFQUFFLEVBQUUsV0FBVyxFQUFFLEtBQUssRUFBRSxDQUFDO1FBQ3RGLENBQUM7UUFFRCxPQUFPO1lBQ0wsRUFBRTtZQUNGLE1BQU07WUFDTixRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUU7WUFDeEIsVUFBVSxFQUFFLEVBQUUsR0FBRyxVQUFVLEVBQUU7WUFDN0IsUUFBUSxFQUFFLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRTtZQUM3QixJQUFJLEVBQUUsU0FBUyxDQUFDLE1BQU07WUFDdEIsVUFBVTtZQUNWLE1BQU0sRUFBRSxVQUFVO1lBQ2xCLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUk7WUFDN0IsSUFBSTtZQUNKLEVBQUU7WUFDRixFQUFFLEVBQUUsSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJO1lBQ25CLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUk7WUFDckIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSTtZQUM3QixhQUFhLEVBQUUsS0FBSztZQUNwQixPQUFPLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDO1lBQ2hDLFVBQVUsRUFBRSxvQkFBb0I7WUFDaEMsUUFBUSxFQUFFLGFBQWE7WUFDdkIsUUFBUSxFQUFFLGFBQWE7WUFDdkIsV0FBVyxFQUFFLEVBQUU7U0FDaEIsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSyxVQUFVLENBQUMsS0FBMEIsRUFBRSxLQUEwQjtRQUN2RSxLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1lBQ2xELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO2dCQUMxQixJQUFJLEtBQUssS0FBSyxJQUFJLEVBQUUsQ0FBQztvQkFDbkIsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3JCLENBQUM7cUJBQU0sQ0FBQztvQkFDTixLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixDQUFDO2dCQUNELFNBQVM7WUFDWCxDQUFDO1lBQ0QsSUFBSSxNQUFNLEdBQUcsS0FBSyxDQUFDO1lBQ25CLEtBQUssTUFBTSxPQUFPLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUM1QyxJQUFJLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7b0JBQ3BFLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ3ZCLENBQUM7Z0JBQ0QsTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMzQixDQUFDO1lBQ0QsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDM0MsSUFBSSxLQUFLLEtBQUssSUFBSSxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUUsQ0FBQztnQkFDdEMsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7WUFDdkIsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRUQsd0dBQXdHO0lBQ2hHLFNBQVMsQ0FDZixJQUFxQixFQUNyQixNQUF3RTtRQUV4RSxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQztRQUNoQixJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQztZQUNoQixLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7WUFDakIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRTtZQUM3QixPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sSUFBSSxFQUFFO1lBQzdCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxJQUFJLEVBQUU7U0FDbEMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTyxpQkFBaUIsQ0FBQyxJQUFxQjtRQUM3QyxNQUFNLFdBQVcsR0FBRztZQUNsQixPQUFPLEVBQUUsYUFBYTtZQUN0QixPQUFPLEVBQUU7Z0JBQ1AsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQ2hCLEtBQUssRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztvQkFDekIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO29CQUMzQixNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7aUJBQzNCO2FBQ0Y7U0FDRixDQUFDO1FBQ0YsTUFBTSxPQUFPLEdBQUcsdUJBQXVCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQztRQUN6RSxLQUFLLE1BQU0sQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3ZELElBQUksVUFBVSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUN4QixTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksQ0FBQztnQkFDSCxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzFCLENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1AsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDckMsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
2001
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5qbWFwc2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5qbWFwc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sd0JBQXdCLENBQUM7QUFDbEQsT0FBTyxFQUVMLG9CQUFvQixFQUNwQixvQkFBb0IsRUFDcEIsMEJBQTBCLEdBRTNCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQVlOLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFbkU7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGlDQUFpQyxHQUFHLENBQVUsQ0FBQztBQXFENUQsNERBQTREO0FBQzVELE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFzQjtJQUNuRCxhQUFhLEVBQUUsVUFBVTtJQUN6QixtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLGNBQWMsRUFBRSxVQUFVO0lBQzFCLHFCQUFxQixFQUFFLENBQUM7SUFDeEIsaUJBQWlCLEVBQUUsRUFBRTtJQUNyQixlQUFlLEVBQUUsR0FBRztJQUNwQixlQUFlLEVBQUUsR0FBRztDQUNyQixDQUFDO0FBRUYsNkVBQTZFO0FBQzdFLE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQztBQUUxQixzREFBc0Q7QUFDdEQsTUFBTSx3QkFBd0IsR0FBRztJQUMvQixJQUFJO0lBQ0osUUFBUTtJQUNSLFVBQVU7SUFDVixZQUFZO0lBQ1osVUFBVTtJQUNWLE1BQU07SUFDTixZQUFZO0lBQ1osV0FBVztJQUNYLFdBQVc7SUFDWCxZQUFZO0lBQ1osUUFBUTtJQUNSLE1BQU07SUFDTixJQUFJO0lBQ0osSUFBSTtJQUNKLEtBQUs7SUFDTCxTQUFTO0lBQ1QsU0FBUztJQUNULFFBQVE7SUFDUixlQUFlO0lBQ2YsU0FBUztJQUNULFlBQVk7SUFDWixVQUFVO0lBQ1YsVUFBVTtJQUNWLGFBQWE7Q0FDZCxDQUFDO0FBQ0YsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0FBRWpFLE1BQU0sa0JBQWtCLEdBQUc7SUFDekIsSUFBSTtJQUNKLE1BQU07SUFDTixVQUFVO0lBQ1YsTUFBTTtJQUNOLFdBQVc7SUFDWCxhQUFhO0lBQ2IsY0FBYztJQUNkLGNBQWM7SUFDZCxlQUFlO0lBQ2YsVUFBVTtJQUNWLGNBQWM7Q0FDZixDQUFDO0FBQ0YsTUFBTSx3QkFBd0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRTdELE1BQU0sMkJBQTJCLEdBQUcsSUFBSSxHQUFHLENBQUM7SUFDMUMsV0FBVztJQUNYLE1BQU07SUFDTixTQUFTO0lBQ1QsTUFBTTtJQUNOLElBQUk7SUFDSixRQUFRO0lBQ1IsT0FBTztJQUNQLFlBQVk7SUFDWixZQUFZO0NBQ2IsQ0FBQyxDQUFDO0FBRUgsTUFBTSxzQkFBc0IsR0FBRztJQUM3QixZQUFZLEVBQUUsSUFBSTtJQUNsQixXQUFXLEVBQUUsSUFBSTtJQUNqQixjQUFjLEVBQUUsSUFBSTtJQUNwQixVQUFVLEVBQUUsSUFBSTtJQUNoQixjQUFjLEVBQUUsSUFBSTtJQUNwQixjQUFjLEVBQUUsSUFBSTtJQUNwQixTQUFTLEVBQUUsSUFBSTtJQUNmLFNBQVMsRUFBRSxJQUFJO0lBQ2YsU0FBUyxFQUFFLElBQUk7Q0FDaEIsQ0FBQztBQUVGLE1BQU0sV0FBVyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7QUFFdEMsZ0ZBQWdGO0FBQ2hGLE1BQU0sV0FBVyxHQUFHLENBQUMsSUFBZ0IsRUFBMkIsRUFBRSxDQUNoRSxJQUFJLENBQUMsTUFBTSxZQUFZLFdBQVc7SUFDaEMsQ0FBQyxDQUFFLElBQWdDO0lBQ25DLENBQUMsQ0FBQyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUUzQiwwRkFBMEY7QUFDMUYsTUFBTSxxQkFBc0IsU0FBUSxLQUFLO0lBQ3ZDLFlBQW1CLElBQVksRUFBRSxXQUFvQjtRQUNuRCxLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyxDQUFDO1FBRFYsU0FBSSxHQUFKLElBQUksQ0FBUTtJQUUvQixDQUFDO0NBQ0Y7QUFFRCxNQUFNLG9CQUFxQixTQUFRLEtBQUs7SUFDdEMsWUFDa0IsTUFBdUQ7UUFFdkUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRkUsV0FBTSxHQUFOLE1BQU0sQ0FBaUQ7SUFHekUsQ0FBQztDQUNGO0FBZUQsZ0ZBQWdGO0FBQ2hGLE1BQU0sWUFBWSxHQUFHLENBQUMsS0FBYSxFQUFFLFFBQWdCLEVBQVUsRUFBRTtJQUMvRCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM3QixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxJQUFJLEdBQUcsR0FBRyxRQUFRLENBQUM7SUFDbkIsT0FBTyxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBRSxHQUFHLFdBQVcsQ0FBQyxLQUFLLFdBQVcsRUFBRSxDQUFDO1FBQzlELEdBQUcsRUFBRSxDQUFDO0lBQ1IsQ0FBQztJQUNELE9BQU8sSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUMxRCxDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxlQUFlLEdBQUcsQ0FBQyxJQUFTLEVBQUUsT0FBZSxFQUFPLEVBQUU7SUFDMUQsSUFBSSxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDbkIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUM3QixNQUFNLElBQUksS0FBSyxDQUFDLHlCQUF5QixPQUFPLElBQUksQ0FBQyxDQUFDO0lBQ3hELENBQUM7SUFDRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQyxNQUFNLFFBQVEsR0FBRyxDQUFDLEtBQVUsRUFBRSxLQUFhLEVBQU8sRUFBRTtRQUNsRCxJQUFJLEtBQUssS0FBSyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDNUIsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBRSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQztRQUN6RSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN6QixJQUFJLEtBQUssS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDbEIsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDL0QsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO29CQUNwRCxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUNoQixNQUFNLEVBQ04sRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7b0JBQ2pELENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDZCxDQUFDO1lBQ0QsTUFBTSxVQUFVLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2pDLElBQ0UsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLFVBQVUsR0FBRyxDQUFDO2dCQUMvQyxVQUFVLElBQUksS0FBSyxDQUFDLE1BQU0sRUFDMUIsQ0FBQztnQkFDRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixLQUFLLG9CQUFvQixDQUFDLENBQUM7WUFDcEUsQ0FBQztZQUNELE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUNELElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxJQUFJLEtBQUssRUFBRSxDQUFDO1lBQ2xFLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDM0MsQ0FBQztRQUNELE1BQU0sSUFBSSxLQUFLLENBQUMsdUJBQXVCLEtBQUsscUJBQXFCLENBQUMsQ0FBQztJQUNyRSxDQUFDLENBQUM7SUFDRixPQUFPLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDM0IsQ0FBQyxDQUFDO0FBRUY7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBQ0gsTUFBTSxPQUFPLFVBQVU7SUFzQnJCLFlBQVksVUFBOEIsRUFBRTtRQWpCcEMsYUFBUSxHQUdaLElBQUksR0FBRyxFQUFFLENBQUM7UUFDTixlQUFVLEdBQStCLElBQUksQ0FBQztRQUM5QyxZQUFPLEdBQTRCLElBQUksR0FBRyxFQUFFLENBQUM7UUFDN0MsaUJBQVksR0FBMkIsSUFBSSxHQUFHLEVBQUUsQ0FBQztRQUNqRCwwQkFBcUIsR0FBd0IsSUFBSSxDQUFDO1FBQ2xELGtCQUFhLEdBQWMsRUFBRSxDQUFDO1FBQzlCLHNCQUFpQixHQUFHLENBQUMsQ0FBQztRQUN0Qix5QkFBb0IsR0FBRyxDQUFDLENBQUM7UUFDekIsNkJBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7UUFDckQsdUJBQWtCLEdBQUcsSUFBSSxHQUFHLEVBQWlCLENBQUM7UUFDOUMsMkJBQXNCLEdBQUcsSUFBSSxHQUFHLEVBQW1CLENBQUM7UUFDcEQsYUFBUSxHQUFHLEtBQUssQ0FBQztRQUl2QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLElBQUksSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1FBQzFELE1BQU0sd0JBQXdCLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixJQUFJO1lBQ25FLHFCQUFxQjtZQUNyQixvQkFBb0I7U0FDckIsQ0FBQztRQUNGLElBQ0Usd0JBQXdCLENBQUMsTUFBTSxLQUFLLENBQUM7WUFDckMsd0JBQXdCLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FDMUMsT0FBTyxTQUFTLEtBQUssUUFBUSxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRTtnQkFDbEQsUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FDekIsRUFDRCxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDYix3RUFBd0UsQ0FDekUsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLENBQUMsd0JBQXdCLEdBQUcsd0JBQXdCO2FBQ3JELEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNkLElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxHQUFHLGtCQUFrQixFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzNELEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ3hELElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDL0MsTUFBTSxJQUFJLEtBQUssQ0FBQyxjQUFjLElBQUksbUNBQW1DLENBQUMsQ0FBQztZQUN6RSxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksQ0FBQyx5QkFBeUIsR0FBRyxPQUFPLENBQUMseUJBQXlCO1lBQ2hFLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUM7UUFDbEMsSUFDRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLHlCQUF5QixDQUFDO1lBQ3JELElBQUksQ0FBQyx5QkFBeUIsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLG1CQUFtQixFQUNoRSxDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FDYiw0RkFBNEYsQ0FDN0YsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLHdCQUF3QjtJQUN4Qix5QkFBeUI7SUFFekI7Ozs7T0FJRztJQUNJLE9BQU8sQ0FBQyxRQUFnQixFQUFFLFFBQWdCO1FBQy9DLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztZQUNoQyxNQUFNLElBQUksS0FBSyxDQUFDLFNBQVMsUUFBUSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFDRCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFFRCw4RUFBOEU7SUFDdkUsY0FBYyxDQUFDLFFBQWdCLEVBQUUsS0FBYTtRQUNuRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLFNBQVMsUUFBUSxtQkFBbUIsQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFDRCxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNoQyxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLDJCQUEyQjtJQUMzQix5QkFBeUI7SUFFekIsMEdBQTBHO0lBQ25HLEtBQUssQ0FBQyxJQUFZO1FBQ3ZCLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLE1BQU0sSUFBSSxLQUFLLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztRQUNwRCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7UUFDdEIsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEVBQUU7WUFDcEQsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2xCLEdBQUcsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO29CQUNqQixjQUFjLEVBQUUsMEJBQTBCO29CQUMxQyxZQUFZLEVBQUUsT0FBTztpQkFDdEIsQ0FBQyxDQUFDO2dCQUNILEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDckIsSUFBSSxFQUFFLGFBQWE7b0JBQ25CLE1BQU0sRUFBRSxHQUFHO29CQUNYLE1BQU0sRUFBRSwrQkFBK0I7aUJBQ3hDLENBQUMsQ0FBQyxDQUFDO2dCQUNKLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1lBQ3JELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsc0JBQXNCLENBQUMsQ0FBQztZQUN4RCxJQUFJLFdBQTJCLENBQUM7WUFDaEMsV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLHNCQUFzQixDQUFDO2lCQUNuRSxPQUFPLENBQUMsR0FBRyxFQUFFO2dCQUNaLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsc0JBQXNCLENBQUMsQ0FBQztnQkFDM0QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUM5QyxDQUFDLENBQUMsQ0FBQztZQUNMLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUM7WUFDekMsS0FBSyxXQUFXLENBQUM7UUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLFlBQVksR0FBRyxDQUFDLE1BQTBCLEVBQVEsRUFBRTtZQUN4RCxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN6QixNQUFNLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7Z0JBQ3RCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlCLENBQUMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDdEMsSUFBSSxDQUFDLFVBQVUsR0FBRyxNQUFNLENBQUM7UUFDekIsT0FBTyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyQyxNQUFNLGNBQWMsR0FBRyxDQUFDLEtBQVksRUFBUSxFQUFFO2dCQUM1QyxNQUFNLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsQ0FBQztnQkFDckMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsWUFBWSxDQUFDLENBQUM7Z0JBQ3ZDLElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxNQUFNLEVBQUUsQ0FBQztvQkFDL0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7Z0JBQ3pCLENBQUM7Z0JBQ0QsSUFBSSxDQUFDO29CQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ2hDLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLHlEQUF5RDtnQkFDM0QsQ0FBQztnQkFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDaEIsQ0FBQyxDQUFDO1lBQ0YsTUFBTSxXQUFXLEdBQUcsR0FBUyxFQUFFO2dCQUM3QixNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsQ0FBQztnQkFDcEMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxLQUFLLEVBQUUsRUFBRTtvQkFDM0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ2pDLENBQUMsQ0FBQyxDQUFDO2dCQUNILE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxTQUFTLEdBQUcsT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU87b0JBQ3RELENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSTtvQkFDZCxDQUFDLENBQUMsSUFBSSxDQUFDO2dCQUNULE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNyQixDQUFDLENBQUM7WUFDRixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxjQUFjLENBQUMsQ0FBQztZQUNyQyxNQUFNLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUN0QyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxLQUFLLENBQUMsSUFBSTtRQUNmLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7UUFDL0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUM7UUFDdkIsTUFBTSxjQUFjLEdBQUcsTUFBTTtZQUMzQixDQUFDLENBQUMsSUFBSSxPQUFPLENBQU8sQ0FBQyxPQUFPLEVBQUUsRUFBRTtnQkFDOUIsSUFBSSxDQUFDO29CQUNILE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDaEMsQ0FBQztnQkFBQyxNQUFNLENBQUM7b0JBQ1AsT0FBTyxFQUFFLENBQUM7Z0JBQ1osQ0FBQztZQUNILENBQUMsQ0FBQztZQUNGLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDdEIsS0FBSyxNQUFNLE1BQU0sSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ25ELElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0IsQ0FBQztRQUNELEtBQUssTUFBTSxVQUFVLElBQUksSUFBSSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDckQsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQy9CLFVBQVUsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsK0JBQStCLENBQUMsQ0FBQyxDQUFDO1lBQy9ELENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxNQUFNLE1BQU0sSUFBSSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDbEMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ25CLENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JCLE1BQU0sY0FBYyxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3BDLE1BQU0sT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQzlCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVDLE1BQU0sSUFBSSxjQUFjLENBQUMsTUFBTSxFQUFFLDJCQUEyQixDQUFDLENBQUM7UUFDaEUsQ0FBQztJQUNILENBQUM7SUFFRCx5QkFBeUI7SUFDekIsb0JBQW9CO0lBQ3BCLHlCQUF5QjtJQUV6Qjs7O09BR0c7SUFDSSxLQUFLLENBQUMsWUFBWSxDQUFDLE9BQWdCO1FBQ3hDLElBQUksQ0FBQztZQUNILE1BQU0sU0FBUyxHQUFHLE1BQU0sSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVELElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUseUJBQXlCLENBQUMsQ0FBQztnQkFDakUsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsYUFBYSxFQUNiLHlCQUF5QixFQUN6QjtvQkFDRSxrQkFBa0IsRUFBRSxJQUFJLENBQUMsd0JBQXdCO2lCQUNsRCxDQUNGLENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM3RCxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLGtCQUFrQixDQUFDLENBQUM7Z0JBQzFELE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FDekIsR0FBRyxFQUNILGFBQWEsRUFDYiwrQkFBK0IsQ0FDaEMsQ0FBQztZQUNKLENBQUM7WUFFRCxNQUFNLEdBQUcsR0FBRyxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQztZQUM5QixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBRTVDLElBQ0UsTUFBTSxLQUFLLEtBQUs7Z0JBQ2hCLENBQUMsUUFBUSxLQUFLLG1CQUFtQixJQUFJLFFBQVEsS0FBSyxlQUFlLENBQUMsRUFDbEUsQ0FBQztnQkFDRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ2hELENBQUM7WUFDRCxJQUFJLE1BQU0sS0FBSyxNQUFNLElBQUksUUFBUSxLQUFLLFdBQVcsRUFBRSxDQUFDO2dCQUNsRCxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzFDLENBQUM7WUFDRCxJQUFJLE1BQU0sS0FBSyxNQUFNLElBQUksUUFBUSxDQUFDLFVBQVUsQ0FBQyxlQUFlLENBQUMsRUFBRSxDQUFDO2dCQUM5RCxPQUFPLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDbEUsQ0FBQztZQUNELElBQUksTUFBTSxLQUFLLEtBQUssSUFBSSxRQUFRLENBQUMsVUFBVSxDQUFDLGlCQUFpQixDQUFDLEVBQUUsQ0FBQztnQkFDL0QsT0FBTyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUM7WUFDckQsQ0FBQztZQUNELElBQUksTUFBTSxLQUFLLEtBQUssSUFBSSxRQUFRLEtBQUssbUJBQW1CLEVBQUUsQ0FBQztnQkFDekQsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDO1lBQzlDLENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQztZQUN4RCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUMvRCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sT0FBTyxHQUFHLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2RSxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLGFBQWEsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUMzRCxDQUFDO0lBQ0gsQ0FBQztJQUVELHlCQUF5QjtJQUN6QixpQkFBaUI7SUFDakIseUJBQXlCO0lBRWpCLEtBQUssQ0FBQyxxQkFBcUIsQ0FDakMsT0FBZ0I7UUFFaEIsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUMsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3BELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNaLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkMsSUFBSSxVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN0QixPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztRQUN6RCxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNsRCxJQUFJLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN4QixLQUFLLE1BQU0sQ0FBQyxRQUFRLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUM5QyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ2xDLE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQztnQkFDdEIsQ0FBQztZQUNILENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxJQUFJLE1BQU0sS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUN2QixJQUFJLE9BQWUsQ0FBQztZQUNwQixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMzQixPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQyxNQUFNLENBQ2hDLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQ3RELENBQUM7WUFDSixDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztZQUNELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDeEMsSUFBSSxVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDdEIsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDOUMsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDL0MsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDMUMsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLFFBQVEsS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDO1lBQ3RCLENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsVUFBVTtJQUNWLHlCQUF5QjtJQUVqQixhQUFhLENBQ25CLE9BQXlCLEVBQ3pCLFNBQXlCO1FBRXpCLE1BQU0sT0FBTyxHQUFHO1lBQ2QsWUFBWSxFQUFFO2dCQUNaLENBQUMsb0JBQW9CLENBQUMsRUFBRTtvQkFDdEIsR0FBRyxJQUFJLENBQUMsTUFBTTtvQkFDZCxtQkFBbUIsRUFBRSxDQUFDLGlCQUFpQixDQUFDO2lCQUN6QztnQkFDRCxDQUFDLG9CQUFvQixDQUFDLEVBQUUsRUFBRTtnQkFDMUIsQ0FBQywwQkFBMEIsQ0FBQyxFQUFFLEVBQUU7YUFDakM7WUFDRCxRQUFRLEVBQUU7Z0JBQ1IsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQ25CLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSTtvQkFDbEIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksSUFBSTtvQkFDdEMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVLElBQUksS0FBSztvQkFDdkMsbUJBQW1CLEVBQUU7d0JBQ25CLENBQUMsb0JBQW9CLENBQUMsRUFBRTs0QkFDdEIsb0JBQW9CLEVBQUUsSUFBSTs0QkFDMUIsZUFBZSxFQUFFLElBQUk7NEJBQ3JCLGtCQUFrQixFQUFFLEdBQUc7NEJBQ3ZCLDBCQUEwQixFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYTs0QkFDckQscUJBQXFCLEVBQUUsQ0FBQyxZQUFZLENBQUM7NEJBQ3JDLHdCQUF3QixFQUFFLEtBQUs7eUJBQ2hDO3dCQUNELENBQUMsMEJBQTBCLENBQUMsRUFBRTs0QkFDNUIsY0FBYyxFQUFFLENBQUM7NEJBQ2pCLG9CQUFvQixFQUFFLEVBQUU7eUJBQ3pCO3FCQUNGO2lCQUNGO2FBQ0Y7WUFDRCxlQUFlLEVBQUU7Z0JBQ2YsQ0FBQyxvQkFBb0IsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxTQUFTO2dCQUN6QyxDQUFDLG9CQUFvQixDQUFDLEVBQUUsT0FBTyxDQUFDLFNBQVM7Z0JBQ3pDLENBQUMsMEJBQTBCLENBQUMsRUFBRSxPQUFPLENBQUMsU0FBUzthQUNoRDtZQUNELFFBQVEsRUFBRSxTQUFTLENBQUMsUUFBUTtZQUM1QixNQUFNLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7WUFDbEMsV0FBVyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQ3hCLHdEQUF3RCxDQUN6RDtZQUNELFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLDBCQUEwQixDQUFDO1lBQ3BELGNBQWMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUMzQixxRUFBcUUsQ0FDdEU7WUFDRCxLQUFLLEVBQUUsYUFBYTtTQUNyQixDQUFDO1FBQ0YsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRU8sUUFBUSxDQUFDLElBQVk7UUFDM0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDbEMsT0FBTyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM1RCxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLGVBQWU7SUFDZix5QkFBeUI7SUFFakIsS0FBSyxDQUFDLFNBQVMsQ0FDckIsT0FBeUIsRUFDekIsT0FBZ0I7UUFFaEIsSUFBSSxJQUFJLENBQUMsaUJBQWlCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ2hFLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUMxQixPQUFPLEVBQ1AsbUNBQW1DLENBQ3BDLENBQUM7WUFDRixPQUFPLElBQUksQ0FBQyxhQUFhLENBQ3ZCLEdBQUcsRUFDSCx1QkFBdUIsRUFDdkIsK0JBQStCLENBQ2hDLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxLQUFpQixDQUFDO1lBQ3RCLElBQUksQ0FBQztnQkFDSCxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQ3ZDLE9BQU8sRUFDUCxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FDM0IsQ0FBQztZQUNKLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksS0FBSyxZQUFZLG9CQUFvQixFQUFFLENBQUM7b0JBQzFDLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxlQUFlLEVBQUUsQ0FBQzt3QkFDckMsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsYUFBYSxFQUNiLGdDQUFnQyxDQUNqQyxDQUFDO29CQUNKLENBQUM7b0JBQ0QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUN2QixHQUFHLEVBQ0gsZ0JBQWdCLEVBQ2hCLDhCQUE4QixJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsU0FBUyxDQUNsRSxDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsTUFBTSxLQUFLLENBQUM7WUFDZCxDQUFDO1lBQ0QsSUFBSSxNQUFXLENBQUM7WUFDaEIsSUFBSSxDQUFDO2dCQUNILE1BQU0sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksV0FBVyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7WUFDdkQsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQ3pCLEdBQUcsRUFDSCxvQ0FBb0MsRUFDcEMscUNBQXFDLENBQ3RDLENBQUM7WUFDSixDQUFDO1lBQ0QsSUFDRSxDQUFDLE1BQU07Z0JBQ1AsT0FBTyxNQUFNLEtBQUssUUFBUTtnQkFDMUIsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7Z0JBQzVCLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQ2xDLENBQUM7Z0JBQ0QsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsdUNBQXVDLEVBQ3ZDLHNEQUFzRCxDQUN2RCxDQUFDO1lBQ0osQ0FBQztZQUNELE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUM7Z0JBQ2hDLG9CQUFvQjtnQkFDcEIsb0JBQW9CO2dCQUNwQiwwQkFBMEI7YUFDM0IsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLENBQVMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzVDLEtBQUssTUFBTSxVQUFVLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQy9CLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztvQkFDdkMsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsOENBQThDLEVBQzlDLG1CQUFtQixVQUFVLG9DQUFvQyxDQUNsRSxDQUFDO2dCQUNKLENBQUM7WUFDSCxDQUFDO1lBQ0QsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7Z0JBQzlELE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FDdkIsR0FBRyxFQUNILG1CQUFtQixFQUNuQiw2QkFBNkIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsZ0JBQWdCLENBQzNFLENBQUM7WUFDSixDQUFDO1lBRUQsTUFBTSxVQUFVLEdBQUcsSUFBSSxHQUFHLENBQ3hCLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBMkIsQ0FBQyxDQUNwRSxDQUFDO1lBQ0YsTUFBTSxlQUFlLEdBQTBCLEVBQUUsQ0FBQztZQUNsRCxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDcEIsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBQ3RDLElBQ0UsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVE7b0JBQ25ELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsRUFDM0IsQ0FBQztvQkFDRCxPQUFPLElBQUksQ0FBQyxlQUFlLENBQ3pCLEdBQUcsRUFDSCx1Q0FBdUMsRUFDdkMsNkRBQTZELENBQzlELENBQUM7Z0JBQ0osQ0FBQztnQkFDRCxNQUFNLENBQUMsVUFBVSxFQUFFLE9BQU8sRUFBRSxNQUFNLENBQUMsR0FBRyxJQUlyQyxDQUFDO2dCQUNGLElBQUksQ0FBQztvQkFDSCxNQUFNLElBQUksR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQ3JDLE9BQU8sSUFBSSxFQUFFLEVBQ2IsZUFBZSxDQUNoQixDQUFDO29CQUNGLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLGNBQWMsQ0FDdkMsT0FBTyxFQUNQLFVBQVUsRUFDVixJQUFJLEVBQ0osS0FBSyxFQUNMLFVBQVUsQ0FDWCxDQUFDO29CQUNGLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7d0JBQzVCLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQzt3QkFDekQsSUFBSSxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7NEJBQ2xCLE9BQU8sR0FBRyxJQUFJLENBQUM7d0JBQ2pCLENBQUM7b0JBQ0gsQ0FBQztnQkFDSCxDQUFDO2dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7b0JBQ2YsSUFBSSxLQUFLLFlBQVkscUJBQXFCLEVBQUUsQ0FBQzt3QkFDM0MsZUFBZSxDQUFDLElBQUksQ0FBQzs0QkFDbkIsT0FBTzs0QkFDUCxFQUFFLElBQUksRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLFdBQVcsRUFBRSxLQUFLLENBQUMsT0FBTyxFQUFFOzRCQUNoRCxNQUFNO3lCQUNQLENBQUMsQ0FBQztvQkFDTCxDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxPQUFPLEdBQUcsS0FBSyxZQUFZLEtBQUs7NEJBQ3BDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTzs0QkFDZixDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO3dCQUNsQixlQUFlLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFO2dDQUM3QixJQUFJLEVBQUUsWUFBWTtnQ0FDbEIsV0FBVyxFQUFFLE9BQU87NkJBQ3JCLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztvQkFDZCxDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDWixNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4QyxDQUFDO1lBRUQsTUFBTSxZQUFZLEdBQXdCO2dCQUN4QyxlQUFlO2dCQUNmLFlBQVksRUFBRSxhQUFhO2FBQzVCLENBQUM7WUFDRixJQUFJLE1BQU0sQ0FBQyxVQUFVLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3BDLFlBQVksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBQ0QsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztRQUM5QyxDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNLLHFCQUFxQixDQUMzQixJQUF5QixFQUN6QixjQUFxQztRQUVyQyxNQUFNLFFBQVEsR0FBd0IsRUFBRSxDQUFDO1FBQ3pDLEtBQUssTUFBTSxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDekIsUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztnQkFDdEIsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLElBQUksSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDO2dCQUNqQixNQUFNLElBQUkscUJBQXFCLENBQzdCLGtCQUFrQixFQUNsQiwrQkFBK0IsSUFBSSxXQUFXLElBQUksSUFBSSxDQUN2RCxDQUFDO1lBQ0osQ0FBQztZQUNELElBQ0UsQ0FBQyxLQUFLO2dCQUNOLE9BQU8sS0FBSyxLQUFLLFFBQVE7Z0JBQ3pCLE9BQU8sS0FBSyxDQUFDLFFBQVEsS0FBSyxRQUFRO2dCQUNsQyxPQUFPLEtBQUssQ0FBQyxJQUFJLEtBQUssUUFBUTtnQkFDOUIsT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFDOUIsQ0FBQztnQkFDRCxNQUFNLElBQUkscUJBQXFCLENBQzdCLHdCQUF3QixFQUN4QixLQUFLLElBQUksMENBQTBDLENBQ3BELENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLElBQUksQ0FDaEMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsUUFBUSxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxLQUFLLENBQUMsSUFBSSxDQUNsRSxDQUFDO1lBQ0YsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNaLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isd0JBQXdCLEVBQ3hCLG1DQUFtQyxLQUFLLENBQUMsUUFBUSxlQUFlLEtBQUssQ0FBQyxJQUFJLElBQUksQ0FDL0UsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0gsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzFELENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isd0JBQXdCLEVBQ3hCLEtBQUssWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FDdkQsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxRQUFRLENBQUM7SUFDbEIsQ0FBQztJQUVELHlCQUF5QjtJQUN6QixrQkFBa0I7SUFDbEIseUJBQXlCO0lBRWpCLEtBQUssQ0FBQyxjQUFjLENBQzFCLE9BQXlCLEVBQ3pCLFVBQWtCLEVBQ2xCLElBQXlCLEVBQ3pCLEtBQWtCLEVBQ2xCLFVBQStCO1FBSS9CLE1BQU0sa0JBQWtCLEdBQTJCO1lBQ2pELFdBQVcsRUFBRSxvQkFBb0I7WUFDakMsYUFBYSxFQUFFLG9CQUFvQjtZQUNuQyxlQUFlLEVBQUUsb0JBQW9CO1lBQ3JDLGlCQUFpQixFQUFFLG9CQUFvQjtZQUN2QyxZQUFZLEVBQUUsb0JBQW9CO1lBQ2xDLFdBQVcsRUFBRSxvQkFBb0I7WUFDakMsYUFBYSxFQUFFLG9CQUFvQjtZQUNuQyxlQUFlLEVBQUUsb0JBQW9CO1lBQ3JDLG9CQUFvQixFQUFFLG9CQUFvQjtZQUMxQyxXQUFXLEVBQUUsb0JBQW9CO1lBQ2pDLGNBQWMsRUFBRSwwQkFBMEI7WUFDMUMscUJBQXFCLEVBQUUsMEJBQTBCO1NBQ2xELENBQUM7UUFDRixNQUFNLFVBQVUsR0FBRyxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNsRCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7WUFDaEIsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixlQUFlLEVBQ2YsbUJBQW1CLFVBQVUsSUFBSSxDQUNsQyxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixlQUFlLEVBQ2YsV0FBVyxVQUFVLDhCQUE4QixVQUFVLGVBQWUsQ0FDN0UsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLFVBQVUsS0FBSyxXQUFXLEVBQUUsQ0FBQztZQUMvQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ3ZDLENBQUM7UUFFRCxRQUFRLFVBQVUsRUFBRSxDQUFDO1lBQ25CLEtBQUssV0FBVztnQkFDZCxPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQzlDLEtBQUssYUFBYTtnQkFDaEIsT0FBTyxDQUFDO3dCQUNOLElBQUksRUFBRSxVQUFVO3dCQUNoQixNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztxQkFDbkQsQ0FBQyxDQUFDO1lBQ0wsS0FBSyxlQUFlO2dCQUNsQixPQUFPLENBQUM7d0JBQ04sSUFBSSxFQUFFLFVBQVU7d0JBQ2hCLE1BQU0sRUFBRSxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDO3FCQUNyRCxDQUFDLENBQUM7WUFDTCxLQUFLLGlCQUFpQjtnQkFDcEIsT0FBTyxDQUFDO3dCQUNOLElBQUksRUFBRSxVQUFVO3dCQUNoQixNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsb0JBQW9CLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztxQkFDdkQsQ0FBQyxDQUFDO1lBQ0wsS0FBSyxZQUFZO2dCQUNmLE9BQU8sQ0FBQzt3QkFDTixJQUFJLEVBQUUsVUFBVTt3QkFDaEIsTUFBTSxFQUFFLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDO3FCQUNsRCxDQUFDLENBQUM7WUFDTCxLQUFLLFdBQVc7Z0JBQ2QsT0FBTyxDQUFDO3dCQUNOLElBQUksRUFBRSxVQUFVO3dCQUNoQixNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUM7cUJBQ2pELENBQUMsQ0FBQztZQUNMLEtBQUssYUFBYTtnQkFDaEIsT0FBTyxDQUFDO3dCQUNOLElBQUksRUFBRSxVQUFVO3dCQUNoQixNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztxQkFDbkQsQ0FBQyxDQUFDO1lBQ0wsS0FBSyxlQUFlO2dCQUNsQixPQUFPLENBQUM7d0JBQ04sSUFBSSxFQUFFLFVBQVU7d0JBQ2hCLE1BQU0sRUFBRSxNQUFNLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDO3FCQUNyRCxDQUFDLENBQUM7WUFDTCxLQUFLLG9CQUFvQjtnQkFDdkIsdUVBQXVFO2dCQUN2RSxNQUFNLElBQUkscUJBQXFCLENBQzdCLHdCQUF3QixFQUN4QixnRUFBZ0UsQ0FDakUsQ0FBQztZQUNKLEtBQUssV0FBVyxDQUFDLENBQUMsQ0FBQztnQkFDakIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7Z0JBQ3BFLE9BQU8sQ0FBQzt3QkFDTixJQUFJLEVBQUUsVUFBVTt3QkFDaEIsTUFBTTt3QkFDTixPQUFPLEVBQUUsTUFBTSxDQUFDLFFBQVEsS0FBSyxNQUFNLENBQUMsUUFBUTtxQkFDN0MsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztZQUNELEtBQUssY0FBYztnQkFDakIsT0FBTyxDQUFDO3dCQUNOLElBQUksRUFBRSxVQUFVO3dCQUNoQixNQUFNLEVBQUUsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQztxQkFDcEQsQ0FBQyxDQUFDO1lBQ0wsS0FBSyxxQkFBcUI7Z0JBQ3hCLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDbEU7Z0JBQ0UsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixlQUFlLEVBQ2YsbUJBQW1CLFVBQVUsSUFBSSxDQUNsQyxDQUFDO1FBQ04sQ0FBQztJQUNILENBQUM7SUFFTyxnQkFBZ0IsQ0FDdEIsT0FBeUIsRUFDekIsSUFBeUI7UUFFekIsSUFBSSxPQUFPLElBQUksQ0FBQyxTQUFTLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdkMsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixrQkFBa0IsRUFDbEIsd0JBQXdCLENBQ3pCLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUkscUJBQXFCLENBQzdCLGlCQUFpQixFQUNqQixZQUFZLElBQUksQ0FBQyxTQUFTLDZDQUE2QyxDQUN4RSxDQUFDO1FBQ0osQ0FBQztJQUNILENBQUM7SUFFRCx5QkFBeUI7SUFDekIsa0JBQWtCO0lBQ2xCLHlCQUF5QjtJQUVqQixLQUFLLENBQUMsZ0JBQWdCLENBQzVCLE9BQXlCLEVBQ3pCLElBQXlCO1FBRXpCLElBQUksR0FBRyxHQUFvQixJQUFJLENBQUM7UUFDaEMsSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsR0FBRyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUM3QixNQUFNLElBQUkscUJBQXFCLENBQzdCLGtCQUFrQixFQUNsQixzQ0FBc0MsQ0FDdkMsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUM7Z0JBQ2xELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsaUJBQWlCLEVBQ2pCLGdDQUFnQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsSUFBSSxDQUNoRSxDQUFDO1lBQ0osQ0FBQztZQUNELEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBZSxDQUFDO1FBQzdCLENBQUM7UUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQ3hDLElBQUksQ0FBQyxVQUFVLEVBQ2Ysd0JBQXdCLENBQ3pCLENBQUM7UUFDRixNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDdkUsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRTtZQUN2QyxNQUFNLElBQUksR0FBd0I7Z0JBQ2hDLEdBQUcsT0FBTztnQkFDVixZQUFZLEVBQUUsT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJO2dCQUMxQyxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsSUFBSSxFQUFFLEdBQUcsc0JBQXNCLEVBQUU7YUFDNUQsQ0FBQztZQUNGLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUUsVUFBVSxJQUFJLGtCQUFrQixDQUFDLENBQUM7UUFDcEUsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPO1lBQ0wsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO1lBQzVCLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSztZQUNuQixJQUFJO1lBQ0osUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1NBQzFCLENBQUM7SUFDSixDQUFDO0lBRU8sS0FBSyxDQUFDLGtCQUFrQixDQUM5QixPQUF5QixFQUN6QixJQUF5QjtRQUV6QixNQUFNLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUF3QixDQUFDO1FBQzFELElBQUksVUFBVSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ3pCLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsbUJBQW1CLEVBQ25CLG9EQUFvRCxDQUNyRCxDQUFDO1FBQ0osQ0FBQztRQUNELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxDQUFDLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7Z0JBQ2hELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsbUJBQW1CLEVBQ25CLDZCQUE2QixHQUFHLHFCQUFxQixDQUN0RCxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFDRCxLQUFLLE1BQU0sVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFLENBQStCLEVBQUUsQ0FBQztZQUN6RSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUN6RCxNQUFNLElBQUkscUJBQXFCLENBQzdCLGlCQUFpQixFQUNqQiwwQkFBMEIsVUFBVSxDQUFDLFFBQVEscUJBQXFCLENBQ25FLENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUN4RSxJQUFJLFNBQVMsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQzVCLElBQUksT0FBTyxNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3BDLFNBQVMsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMxRSxDQUFDO1FBQ0QsSUFBSSxPQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDcEMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFFLENBQUM7UUFDRCxJQUFJLFVBQVUsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUN6QixTQUFTLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQ3ZDLE9BQU8sQ0FBQyxRQUFRLEtBQUssTUFBTSxDQUFDLFFBQVEsQ0FDckMsQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUErQixDQUFDO1FBQ3BFLElBQUksV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3ZCLFNBQVMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO2dCQUN2QyxLQUFLLE1BQU0sVUFBVSxJQUFJLFdBQVcsRUFBRSxDQUFDO29CQUNyQyxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUMsV0FBVyxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDNUQsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFFBQWdDLENBQUM7b0JBQzdELE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzlCLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQy9CLElBQUksSUFBSSxHQUFHLEtBQUssRUFBRSxDQUFDO3dCQUNqQixPQUFPLENBQUMsU0FBUyxDQUFDO29CQUNwQixDQUFDO29CQUNELElBQUksSUFBSSxHQUFHLEtBQUssRUFBRSxDQUFDO3dCQUNqQixPQUFPLFNBQVMsQ0FBQztvQkFDbkIsQ0FBQztnQkFDSCxDQUFDO2dCQUNELE9BQU8sQ0FBQyxDQUFDO1lBQ1gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdDLElBQUksR0FBRyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDakUsSUFBSSxPQUFPLElBQUksQ0FBQyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDbkMsR0FBRyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsTUFBTSxRQUFRLEdBQXdCO1lBQ3BDLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixVQUFVLEVBQUUsTUFBTSxDQUFDLEtBQUs7WUFDeEIsbUJBQW1CLEVBQUUsS0FBSztZQUMxQixRQUFRO1lBQ1IsR0FBRztTQUNKLENBQUM7UUFDRixJQUFJLElBQUksQ0FBQyxjQUFjLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDakMsUUFBUSxDQUFDLEtBQUssR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ3BDLENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRU8sS0FBSyxDQUFDLG9CQUFvQixDQUNoQyxPQUF5QixFQUN6QixJQUF5QjtRQUV6QixNQUFNLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRSxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQ2xELE9BQU8sQ0FBQyxTQUFTLEVBQ2pCLFVBQVUsRUFDVixVQUFVLENBQ1gsQ0FBQztRQUNGLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNiLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isd0JBQXdCLEVBQ3hCLGlEQUFpRCxVQUFVLElBQUksQ0FDaEUsQ0FBQztRQUNKLENBQUM7UUFDRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQztJQUN0RCxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLGlCQUFpQjtJQUNqQix5QkFBeUI7SUFFakIsS0FBSyxDQUFDLGVBQWUsQ0FDM0IsT0FBeUIsRUFDekIsSUFBeUI7UUFFekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixrQkFBa0IsRUFDbEIsbUNBQW1DLENBQ3BDLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2xELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsaUJBQWlCLEVBQ2pCLGdDQUFnQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsSUFBSSxDQUNoRSxDQUFDO1FBQ0osQ0FBQztRQUNELHNFQUFzRTtRQUN0RSxtRUFBbUU7UUFDbkUsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBZSxDQUFDLENBQUMsQ0FBQztRQUN0RCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDckUsT0FBTztZQUNMLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7WUFDbkIsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1lBQ2pCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtTQUMxQixDQUFDO0lBQ0osQ0FBQztJQUVELHlCQUF5QjtJQUN6QixnQkFBZ0I7SUFDaEIseUJBQXlCO0lBRWpCLEtBQUssQ0FBQyxjQUFjLENBQzFCLE9BQXlCLEVBQ3pCLElBQXlCO1FBRXpCLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxJQUFJLElBQUksSUFBSSxDQUFDLEdBQUcsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNoRCw2RUFBNkU7WUFDN0UsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixpQkFBaUIsRUFDakIsMERBQTBELENBQzNELENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDN0IsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixrQkFBa0IsRUFDbEIsa0NBQWtDLENBQ25DLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2xELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsaUJBQWlCLEVBQ2pCLGdDQUFnQyxJQUFJLENBQUMsTUFBTSxDQUFDLGVBQWUsSUFBSSxDQUNoRSxDQUFDO1FBQ0osQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FDeEMsSUFBSSxDQUFDLFVBQVUsRUFDZixzQkFBc0IsQ0FDdkIsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQ3pDLE9BQU8sQ0FBQyxTQUFTLEVBQ2pCLElBQUksQ0FBQyxHQUFlLEVBQ3BCLFVBQVUsQ0FDWCxDQUFDO1FBQ0YsTUFBTSxtQkFBbUIsR0FBRyxVQUFVLElBQUksd0JBQXdCLENBQUM7UUFDbkUsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUN0QyxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQWEsRUFBRSxtQkFBbUIsQ0FBQyxDQUFDO1lBQ3pFLElBQUksbUJBQW1CLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQy9DLFNBQVMsQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDNUQsQ0FBQztZQUNELE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTztZQUNMLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7WUFDbkIsSUFBSTtZQUNKLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtTQUMxQixDQUFDO0lBQ0osQ0FBQztJQUVELHFGQUFxRjtJQUM3RSxlQUFlLENBQ3JCLE1BQXdCLEVBQ3hCLElBQXlCO1FBRXpCLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7UUFDakMsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDckMsS0FBSyxNQUFNLE1BQU0sSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO2dCQUNwRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDdEMsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ25DLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLEVBQUUsQ0FBQztvQkFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzFCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLG1CQUFtQixLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3RDLEtBQUssTUFBTSxJQUFJLElBQUksTUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDO2dCQUNuQyxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksSUFBSSxFQUFFLENBQUM7b0JBQ3hCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUMxQixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUM7UUFDRCxNQUFNLFFBQVEsR0FDWixPQUFPLElBQUksQ0FBQyxpQkFBaUIsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLGlCQUFpQixHQUFHLENBQUM7WUFDdEUsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUI7WUFDeEIsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNYLE1BQU0sTUFBTSxHQUF3QyxFQUFFLENBQUM7UUFDdkQsS0FBSyxNQUFNLE1BQU0sSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUM1QixNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDZixTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksS0FBSyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUM7WUFDNUIsSUFBSSxXQUFXLEdBQUcsU0FBUyxDQUFDLFdBQVcsS0FBSyxJQUFJLENBQUM7WUFDakQsSUFBSSxRQUFRLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ3RCLE1BQU0sU0FBUyxHQUFHLFlBQVksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7Z0JBQ2hELElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ3BDLEtBQUssR0FBRyxTQUFTLENBQUM7b0JBQ2xCLFdBQVcsR0FBRyxJQUFJLENBQUM7Z0JBQ3JCLENBQUM7WUFDSCxDQUFDO1lBQ0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxDQUFDO1FBQzFDLENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRU8sS0FBSyxDQUFDLGdCQUFnQixDQUM1QixPQUF5QixFQUN6QixJQUF5QjtRQUV6QixNQUFNLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUF3QixDQUFDO1FBQzFELElBQUksVUFBVSxJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ3pCLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsbUJBQW1CLEVBQ25CLDhEQUE4RCxDQUMvRCxDQUFDO1FBQ0osQ0FBQztRQUNELEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1lBQ3RDLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDMUMsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixtQkFBbUIsRUFDbkIsMkJBQTJCLEdBQUcscUJBQXFCLENBQ3BELENBQUM7WUFDSixDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFLENBQStCLENBQUM7UUFDN0QsS0FBSyxNQUFNLFVBQVUsSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUM5QixJQUFJLFVBQVUsQ0FBQyxRQUFRLEtBQUssWUFBWSxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsaUJBQWlCLEVBQ2pCLHdCQUF3QixVQUFVLENBQUMsUUFBUSxxQkFBcUIsQ0FDakUsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQ3RELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isa0JBQWtCLEVBQ2xCLDBCQUEwQixDQUMzQixDQUFDO1FBQ0osQ0FBQztRQUNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7WUFDL0QsTUFBTSxFQUFFLE1BQTBCO1lBQ2xDLElBQUksRUFBRSxJQUEwRDtZQUNoRSxRQUFRO1lBQ1IsS0FBSyxFQUFFLE9BQU8sSUFBSSxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUk7WUFDekQsY0FBYyxFQUFFLElBQUksQ0FBQyxjQUFjLEtBQUssSUFBSTtTQUM3QyxDQUFDLENBQUM7UUFDSCxNQUFNLFFBQVEsR0FBd0I7WUFDcEMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO1lBQzVCLFVBQVUsRUFBRSxNQUFNLENBQUMsVUFBVTtZQUM3QixtQkFBbUIsRUFBRSxLQUFLO1lBQzFCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixHQUFHLEVBQUUsTUFBTSxDQUFDLEdBQUc7U0FDaEIsQ0FBQztRQUNGLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNqQyxRQUFRLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDO1FBQ3JDLENBQUM7UUFDRCxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRU8sS0FBSyxDQUFDLGtCQUFrQixDQUM5QixPQUF5QixFQUN6QixJQUF5QjtRQUV6QixNQUFNLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNsRSxNQUFNLE9BQU8sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUNoRCxPQUFPLENBQUMsU0FBUyxFQUNqQixVQUFVLEVBQ1YsVUFBVSxDQUNYLENBQUM7UUFDRixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDYixNQUFNLElBQUkscUJBQXFCLENBQzdCLHdCQUF3QixFQUN4Qix5Q0FBeUMsVUFBVSxJQUFJLENBQ3hELENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxFQUFFLEdBQUcsT0FBTyxFQUFFLENBQUM7SUFDdEQsQ0FBQztJQUVPLEtBQUssQ0FBQyxjQUFjLENBQzFCLE9BQXlCLEVBQ3pCLElBQXlCLEVBQ3pCLFVBQStCO1FBRS9CLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQ2xDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQXdCLENBQzNDLENBQUM7UUFDRixNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUNsQyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUF3QixDQUMzQyxDQUFDO1FBQ0YsTUFBTSxVQUFVLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBYSxDQUFDO1FBQ3BELElBQ0UsYUFBYSxDQUFDLE1BQU0sR0FBRyxhQUFhLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNO1lBQzdELElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxFQUM3QixDQUFDO1lBQ0QsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixpQkFBaUIsRUFDakIsNENBQTRDLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxJQUFJLENBQzVFLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxPQUFPLElBQUksQ0FBQyxTQUFTLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDdkMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ3BFLElBQUksT0FBTyxDQUFDLEtBQUssS0FBSyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3JDLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsZUFBZSxFQUNmLGNBQWMsSUFBSSxDQUFDLFNBQVMsdUNBQXVDLE9BQU8sQ0FBQyxLQUFLLElBQUksQ0FDckYsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsTUFBTSxjQUFjLEdBQXlCLEVBQUUsQ0FBQztRQUNoRCxNQUFNLGVBQWUsR0FBa0MsRUFBRSxDQUFDO1FBRTFELElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3pCLGNBQWMsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBQzNCLEtBQUssTUFBTSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxhQUFhLEVBQUUsQ0FBQztnQkFDL0MsY0FBYyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsR0FBRyxJQUF3QixDQUFDO1lBQy9ELENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxhQUFhLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDekIsY0FBYyxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUM7WUFDM0IsS0FBSyxNQUFNLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUN4QyxJQUFJLENBQUM7b0JBQ0gsY0FBYyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMscUJBQXFCLENBQ3BELEtBQTRCLENBQzdCLENBQUM7Z0JBQ0osQ0FBQztnQkFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO29CQUNmLGVBQWUsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLFlBQVkscUJBQXFCO3dCQUMxRCxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsS0FBSyxDQUFDLE9BQU8sRUFBRTt3QkFDbEQsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7Z0JBQzNELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ3RCLGNBQWMsQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO1FBQ3RDLENBQUM7UUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUN6QyxPQUFPLENBQUMsU0FBUyxFQUNqQixjQUFjLENBQ2YsQ0FBQztRQUVGLE1BQU0sT0FBTyxHQUF3QixFQUFFLENBQUM7UUFDeEMsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDbEUsVUFBVSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3RDLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRztnQkFDcEIsRUFBRSxFQUFFLE1BQU0sQ0FBQyxFQUFFO2dCQUNiLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtnQkFDckIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO2dCQUN6QixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7YUFDbEIsQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLE9BQU8sR0FBeUIsRUFBRSxDQUFDO1FBQ3pDLEtBQUssTUFBTSxFQUFFLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2hDLE9BQU8sQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQztRQUNELE9BQU87WUFDTCxTQUFTLEVBQUUsT0FBTyxDQUFDLFNBQVM7WUFDNUIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRO1lBQ3pCLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUTtZQUN6QixPQUFPO1lBQ1AsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVO1lBQzdCLE9BQU87WUFDUCxVQUFVLEVBQUUsRUFBRSxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsR0FBRyxlQUFlLEVBQUU7WUFDeEQsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO1lBQzNCLFlBQVksRUFBRSxNQUFNLENBQUMsWUFBWTtTQUNsQyxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0sscUJBQXFCLENBQUMsS0FBMEI7UUFDdEQsTUFBTSxNQUFNLEdBQXFCLEVBQUUsQ0FBQztRQUNwQyxNQUFNLFFBQVEsR0FBRyxDQUFDLEtBQWEsRUFBVSxFQUFFLENBQ3pDLEtBQUssQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDcEQsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNsRCxJQUFJLElBQUksS0FBSyxVQUFVLElBQUksSUFBSSxLQUFLLFlBQVksRUFBRSxDQUFDO2dCQUNqRCxJQUNFLEtBQUssS0FBSyxJQUFJLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQ25FLENBQUM7b0JBQ0QsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixtQkFBbUIsRUFDbkIsSUFBSSxJQUFJLHNCQUFzQixDQUMvQixDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsTUFBTSxVQUFVLEdBQTRCLEVBQUUsQ0FBQztnQkFDL0MsS0FDRSxNQUFNLENBQUMsR0FBRyxFQUFFLFVBQVUsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQ3ZDLEtBQTRCLENBQzdCLEVBQ0QsQ0FBQztvQkFDRCxJQUFJLFVBQVUsS0FBSyxJQUFJLEVBQUUsQ0FBQzt3QkFDeEIsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixtQkFBbUIsRUFDbkIsY0FBYyxJQUFJLCtEQUErRCxDQUNsRixDQUFDO29CQUNKLENBQUM7b0JBQ0QsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztnQkFDekIsQ0FBQztnQkFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDO2dCQUMxQixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDckMsSUFBSSxVQUFVLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDdEIsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixtQkFBbUIsRUFDbkIsbUJBQW1CLElBQUksNEJBQTRCLENBQ3BELENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDM0MsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDeEMsSUFDRSxDQUFDLFFBQVEsS0FBSyxVQUFVLElBQUksUUFBUSxLQUFLLFlBQVksQ0FBQztnQkFDdEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFDM0IsQ0FBQztnQkFDRCxNQUFNLElBQUkscUJBQXFCLENBQzdCLGNBQWMsRUFDZCwyQkFBMkIsSUFBSSxJQUFJLENBQ3BDLENBQUM7WUFDSixDQUFDO1lBQ0QsTUFBTSxHQUFHLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQzNCLE1BQU0sZUFBZSxHQUFHLEtBQUssS0FBSyxJQUFJO2dCQUNwQyxDQUFDLENBQUMsSUFBSTtnQkFDTixDQUFDLENBQUMsS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssS0FBSztvQkFDbkMsQ0FBQyxDQUFDLElBQUk7b0JBQ04sQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUNkLElBQUksZUFBZSxLQUFLLFNBQVMsRUFBRSxDQUFDO2dCQUNsQyxNQUFNLElBQUkscUJBQXFCLENBQzdCLGNBQWMsRUFDZCxvQkFBb0IsSUFBSSx5QkFBeUIsQ0FDbEQsQ0FBQztZQUNKLENBQUM7WUFDRCxJQUFJLFFBQVEsS0FBSyxVQUFVLEVBQUUsQ0FBQztnQkFDNUIsTUFBTSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQztnQkFDbEQsTUFBTSxDQUFDLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxlQUFlLENBQUM7WUFDOUMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQU0sQ0FBQyxlQUFlLEdBQUcsTUFBTSxDQUFDLGVBQWUsSUFBSSxFQUFFLENBQUM7Z0JBQ3RELE1BQU0sQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLEdBQUcsZUFBZSxDQUFDO1lBQ2hELENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsUUFBUSxJQUFJLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUM1QyxNQUFNLElBQUkscUJBQXFCLENBQzdCLGNBQWMsRUFDZCw0RUFBNEUsQ0FDN0UsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksTUFBTSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ2hELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0IsY0FBYyxFQUNkLGdGQUFnRixDQUNqRixDQUFDO1FBQ0osQ0FBQztRQUNELE9BQU8sTUFBTSxDQUFDO0lBQ2hCLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsZ0NBQWdDO0lBQ2hDLHlCQUF5QjtJQUVqQixLQUFLLENBQUMsaUJBQWlCLENBQzdCLE9BQXlCLEVBQ3pCLElBQXlCO1FBRXpCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ25FLElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDdkIsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO1FBQzlCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBZSxDQUFDLENBQUM7WUFDN0MsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUQsS0FBSyxNQUFNLEVBQUUsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQztvQkFDakQsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTztZQUNMLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixLQUFLLEVBQUUsTUFBTSxDQUFDLEtBQUs7WUFDbkIsSUFBSTtZQUNKLFFBQVE7U0FDVCxDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyx3QkFBd0IsQ0FDcEMsT0FBeUIsRUFDekIsSUFBeUIsRUFDekIsVUFBK0I7UUFJL0IsTUFBTSxPQUFPLEdBQXdCLEVBQUUsQ0FBQztRQUN4QyxNQUFNLFVBQVUsR0FBa0MsRUFBRSxDQUFDO1FBQ3JELE1BQU0sVUFBVSxHQUFrQyxFQUFFLENBQUM7UUFDckQsTUFBTSxZQUFZLEdBQWtDLEVBQUUsQ0FBQztRQUN2RCx5RUFBeUU7UUFDekUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsRUFHL0IsQ0FBQztRQUVKLE1BQU0sZ0JBQWdCLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FDdkQsT0FBTyxDQUFDLFNBQVMsQ0FDbEIsQ0FBQztRQUVGLEtBQ0UsTUFBTSxDQUFDLFVBQVUsRUFBRSxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUN4QyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksRUFBRSxDQUF3QixDQUMzQyxFQUNELENBQUM7WUFDRCxJQUFJLE9BQU8sR0FBVyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQ25DLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDM0QsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xELElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztvQkFDZCxVQUFVLENBQUMsVUFBVSxDQUFDLEdBQUc7d0JBQ3ZCLElBQUksRUFBRSxtQkFBbUI7d0JBQ3pCLFdBQVcsRUFBRSxrQ0FBa0MsT0FBTyxJQUFJO3FCQUMzRCxDQUFDO29CQUNGLFNBQVM7Z0JBQ1gsQ0FBQztnQkFDRCxPQUFPLEdBQUcsUUFBUSxDQUFDO1lBQ3JCLENBQUM7WUFDRCxNQUFNLFdBQVcsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7Z0JBQ2xFLE9BQU87YUFDUixDQUFDLENBQUM7WUFDSCxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ2xDLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxVQUFVLENBQUMsVUFBVSxDQUFDLEdBQUc7b0JBQ3ZCLElBQUksRUFBRSxtQkFBbUI7b0JBQ3pCLFdBQVcsRUFBRSxVQUFVLE9BQU8sbUJBQW1CO2lCQUNsRCxDQUFDO2dCQUNGLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FDekMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLFVBQVUsQ0FDaEQsQ0FBQztZQUNGLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDZCxVQUFVLENBQUMsVUFBVSxDQUFDLEdBQUc7b0JBQ3ZCLElBQUksRUFBRSxtQkFBbUI7b0JBQ3pCLFdBQVcsRUFBRSxhQUFhLElBQUksQ0FBQyxVQUFVLG1CQUFtQjtpQkFDN0QsQ0FBQztnQkFDRixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQ25DLElBQUksQ0FBQyxRQUFRLEVBQ2IsUUFBUSxDQUFDLEtBQUssRUFDZCxLQUFLLENBQ04sQ0FBQztZQUNGLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM1QixVQUFVLENBQUMsVUFBVSxDQUFDLEdBQUc7b0JBQ3ZCLElBQUksRUFBRSxjQUFjO29CQUNwQixXQUFXLEVBQ1Qsa0VBQWtFO2lCQUNyRSxDQUFDO2dCQUNGLFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN6RSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQ1YsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHO29CQUN2QixJQUFJLEVBQUUsbUJBQW1CO29CQUN6QixXQUFXLEVBQUUscUJBQXFCLEtBQUssQ0FBQyxNQUFNLG1CQUFtQjtpQkFDbEUsQ0FBQztnQkFDRixTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksQ0FBQztnQkFDSCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUU7b0JBQ25FLE9BQU87b0JBQ1AsVUFBVSxFQUFFLFFBQVEsQ0FBQyxFQUFFO29CQUN2QixRQUFRO29CQUNSLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSTtpQkFDbkIsQ0FBQyxDQUFDO2dCQUNILGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUU7b0JBQ2pDLFlBQVksRUFBRSxVQUFVLENBQUMsRUFBRTtvQkFDM0IsT0FBTztpQkFDUixDQUFDLENBQUM7Z0JBQ0gsT0FBTyxDQUFDLFVBQVUsQ0FBQyxHQUFHO29CQUNwQixFQUFFLEVBQUUsVUFBVSxDQUFDLEVBQUU7b0JBQ2pCLFVBQVUsRUFBRSxVQUFVLENBQUMsVUFBVTtvQkFDakMsTUFBTSxFQUFFLFVBQVUsQ0FBQyxNQUFNO2lCQUMxQixDQUFDO1lBQ0osQ0FBQztZQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7Z0JBQ2YsVUFBVSxDQUFDLFVBQVUsQ0FBQyxHQUFHO29CQUN2QixJQUFJLEVBQUUsaUJBQWlCO29CQUN2QixXQUFXLEVBQUUsS0FBSyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztpQkFDcEUsQ0FBQztZQUNKLENBQUM7UUFDSCxDQUFDO1FBRUQsS0FBSyxNQUFNLEVBQUUsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxFQUFFLENBQXdCLENBQUMsRUFBRSxDQUFDO1lBQ3pFLFVBQVUsQ0FBQyxFQUFFLENBQUMsR0FBRztnQkFDZixJQUFJLEVBQUUsV0FBVztnQkFDakIsV0FBVyxFQUFFLDRDQUE0QzthQUMxRCxDQUFDO1FBQ0osQ0FBQztRQUNELEtBQUssTUFBTSxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBYSxFQUFFLENBQUM7WUFDbEQsWUFBWSxDQUFDLEVBQUUsQ0FBQyxHQUFHO2dCQUNqQixJQUFJLEVBQUUsV0FBVztnQkFDakIsV0FBVyxFQUFFLDZDQUE2QzthQUMzRCxDQUFDO1FBQ0osQ0FBQztRQUVELE1BQU0sU0FBUyxHQUVYO1lBQ0Y7Z0JBQ0UsSUFBSSxFQUFFLHFCQUFxQjtnQkFDM0IsTUFBTSxFQUFFO29CQUNOLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztvQkFDNUIsUUFBUSxFQUFFLElBQUk7b0JBQ2QsUUFBUSxFQUFFLEdBQUc7b0JBQ2IsT0FBTztvQkFDUCxVQUFVO29CQUNWLE9BQU8sRUFBRSxFQUFFO29CQUNYLFVBQVU7b0JBQ1YsU0FBUyxFQUFFLEVBQUU7b0JBQ2IsWUFBWTtpQkFDYjtnQkFDRCxPQUFPLEVBQUUsa0JBQWtCLENBQUMsSUFBSSxHQUFHLENBQUM7YUFDckM7U0FDRixDQUFDO1FBRUYseUVBQXlFO1FBQ3pFLHlFQUF5RTtRQUN6RSxtREFBbUQ7UUFDbkQsTUFBTSxvQkFBb0IsR0FBRyxDQUMzQixTQUFpQixFQUNpQyxFQUFFO1lBQ3BELElBQUksU0FBUyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO2dCQUM5QixPQUFPLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDO1lBQzVELENBQUM7WUFDRCxLQUFLLE1BQU0sS0FBSyxJQUFJLGtCQUFrQixDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUM7Z0JBQ2hELElBQUksS0FBSyxDQUFDLFlBQVksS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDckMsT0FBTyxLQUFLLENBQUM7Z0JBQ2YsQ0FBQztZQUNILENBQUM7WUFDRCxPQUFPLElBQUksQ0FBQztRQUNkLENBQUMsQ0FBQztRQUNGLE1BQU0sV0FBVyxHQUF3QixFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDMUUsSUFBSSxjQUFjLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQ0UsSUFBSSxDQUFDLG9CQUFvQixJQUFJLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixLQUFLLFFBQVEsRUFDMUUsQ0FBQztZQUNELE1BQU0sTUFBTSxHQUF3QixFQUFFLENBQUM7WUFDdkMsS0FDRSxNQUFNLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQ3hDLElBQUksQ0FBQyxvQkFBMkMsQ0FDakQsRUFDRCxDQUFDO2dCQUNELE1BQU0sS0FBSyxHQUFHLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxDQUFDO2dCQUM5QyxJQUFJLEtBQUssRUFBRSxDQUFDO29CQUNWLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsS0FBSyxDQUFDO29CQUM5QixjQUFjLEdBQUcsSUFBSSxDQUFDO2dCQUN4QixDQUFDO1lBQ0gsQ0FBQztZQUNELFdBQVcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQzlCLENBQUM7UUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEVBQUUsQ0FBQztZQUM5QyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7WUFDN0IsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMscUJBQWlDLEVBQUUsQ0FBQztnQkFDL0QsTUFBTSxLQUFLLEdBQUcsb0JBQW9CLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQzlDLElBQUksS0FBSyxFQUFFLENBQUM7b0JBQ1YsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQzVCLGNBQWMsR0FBRyxJQUFJLENBQUM7Z0JBQ3hCLENBQUM7WUFDSCxDQUFDO1lBQ0QsV0FBVyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDaEMsQ0FBQztRQUNELElBQUksY0FBYyxFQUFFLENBQUM7WUFDbkIsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUN0QyxPQUFPLEVBQ1AsV0FBVyxFQUNYLFVBQVUsQ0FDWCxDQUFDO1lBQ0YsU0FBUyxDQUFDLElBQUksQ0FBQztnQkFDYixJQUFJLEVBQUUsV0FBVztnQkFDakIsTUFBTTtnQkFDTixPQUFPLEVBQUUsTUFBTSxDQUFDLFFBQVEsS0FBSyxNQUFNLENBQUMsUUFBUTthQUM3QyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUVELGtGQUFrRjtJQUMxRSxlQUFlLENBQ3JCLFlBQWlCLEVBQ2pCLGFBQXFCLEVBQ3JCLEtBQXVCO1FBRXZCLElBQ0UsWUFBWTtZQUNaLE9BQU8sWUFBWSxLQUFLLFFBQVE7WUFDaEMsWUFBWSxDQUFDLFFBQVEsRUFBRSxLQUFLO1lBQzVCLEtBQUssQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxFQUNsQyxDQUFDO1lBQ0QsT0FBTztnQkFDTCxRQUFRLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEVBQUU7Z0JBQ3hELE1BQU0sRUFBRSxZQUFZLENBQUMsTUFBTTtxQkFDeEIsTUFBTSxDQUFDLENBQUMsU0FBYyxFQUFFLEVBQUUsQ0FBQyxPQUFPLFNBQVMsRUFBRSxLQUFLLEtBQUssUUFBUSxDQUFDO3FCQUNoRSxHQUFHLENBQUMsQ0FBQyxTQUFjLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7YUFDekQsQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQ3JDLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxFQUFFLEVBQUUsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDbkQsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQ2pDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ2hDLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTztZQUNMLFFBQVEsRUFBRSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxJQUFJLGFBQWEsRUFBRTtZQUM1RCxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztTQUN0RSxDQUFDO0lBQ0osQ0FBQztJQUVELHlCQUF5QjtJQUN6QixvQkFBb0I7SUFDcEIseUJBQXlCO0lBRWpCLEtBQUssQ0FBQyxpQkFBaUIsQ0FDN0IsT0FBZ0IsRUFDaEIsTUFBYztRQUVkLElBQUksQ0FBQztZQUNILElBQUksT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDcEMsQ0FBQztRQUNILENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxvRUFBb0U7UUFDdEUsQ0FBQztJQUNILENBQUM7SUFFTyxLQUFLLENBQUMsc0JBQXNCLENBQ2xDLE9BQWdCLEVBQ2hCLFFBQWdCO1FBRWhCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDN0QsSUFBSSxjQUFjLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDNUIsSUFDRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDO2dCQUM3QixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxDQUFDLEVBQzdDLENBQUM7Z0JBQ0QsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLHdCQUF3QixDQUFDLENBQUM7Z0JBQ2hFLE1BQU0sSUFBSSxvQkFBb0IsQ0FBQyxlQUFlLENBQUMsQ0FBQztZQUNsRCxDQUFDO1lBQ0QsSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUM7Z0JBQ3RDLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSx3QkFBd0IsQ0FBQyxDQUFDO2dCQUNoRSxNQUFNLElBQUksb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUM7WUFDN0MsQ0FBQztRQUNILENBQUM7UUFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ2xCLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztRQUMxQixDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUN4QyxNQUFNLE1BQU0sR0FBaUIsRUFBRSxDQUFDO1FBQ2hDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQztRQUNkLElBQUksQ0FBQztZQUNILE9BQU8sSUFBSSxFQUFFLENBQUM7Z0JBQ1osTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxJQUFJO29CQUFFLE1BQU07Z0JBQ2hCLEtBQUssSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDO2dCQUMxQixJQUFJLEtBQUssR0FBRyxRQUFRLEVBQUUsQ0FBQztvQkFDckIsTUFBTSxNQUFNLENBQUMsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7b0JBQzlDLE1BQU0sSUFBSSxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDN0MsQ0FBQztnQkFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JCLENBQUM7UUFDSCxDQUFDO2dCQUFTLENBQUM7WUFDVCxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdkIsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ25DLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNmLEtBQUssTUFBTSxLQUFLLElBQUksTUFBTSxFQUFFLENBQUM7WUFDM0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDeEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDN0IsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLHFCQUFxQixDQUMzQixPQUFnQixFQUNoQixZQUFvQjtRQVFwQixNQUFNLGVBQWUsR0FBRyxJQUFJLGVBQWUsRUFBRSxDQUFDO1FBQzlDLElBQUksTUFBTSxHQUFtRCxJQUFJLENBQUM7UUFDbEUsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQ2xCLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztRQUNyQixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUM7UUFFdEIsTUFBTSxNQUFNLEdBQUcsS0FBSyxFQUFFLE1BQWUsRUFBaUIsRUFBRTtZQUN0RCxJQUFJLFNBQVMsSUFBSSxRQUFRO2dCQUFFLE9BQU87WUFDbEMsU0FBUyxHQUFHLElBQUksQ0FBQztZQUNqQixlQUFlLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQzlCLElBQUksQ0FBQztnQkFDSCxJQUFJLE1BQU0sRUFBRSxDQUFDO29CQUNYLE1BQU0sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDOUIsQ0FBQztxQkFBTSxJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNoRCxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUNwQyxDQUFDO1lBQ0gsQ0FBQztZQUFDLE1BQU0sQ0FBQztnQkFDUCwyREFBMkQ7WUFDN0QsQ0FBQztRQUNILENBQUMsQ0FBQztRQUNGLE1BQU0sY0FBYyxHQUFHLEdBQVMsRUFBRTtZQUNoQyxLQUFLLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUM7UUFDdEUsQ0FBQyxDQUFDO1FBQ0YsT0FBTyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsY0FBYyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDekUsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU87WUFBRSxjQUFjLEVBQUUsQ0FBQztRQUU3QyxNQUFNLE1BQU0sR0FBRyxJQUFJLGNBQWMsQ0FBYTtZQUM1QyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVU7Z0JBQ25CLElBQUksU0FBUyxFQUFFLENBQUM7b0JBQ2QsVUFBVSxDQUFDLEtBQUssQ0FDZCxlQUFlLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxDQUNoRSxDQUFDO29CQUNGLE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDO29CQUNsQixJQUFJLFlBQVksS0FBSyxDQUFDLEVBQUUsQ0FBQzt3QkFDdkIsUUFBUSxHQUFHLElBQUksQ0FBQzt3QkFDaEIsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNyQixDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxLQUFLLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3dCQUN6RCxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3dCQUM3QixVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUMxQixDQUFDO29CQUNELE9BQU87Z0JBQ1QsQ0FBQztnQkFDRCxNQUFNLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDcEMsTUFBTSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxNQUFNLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxJQUFJLEVBQUUsQ0FBQztvQkFDVCxJQUFJLFNBQVMsS0FBSyxZQUFZLEVBQUUsQ0FBQzt3QkFDL0IsTUFBTSxLQUFLLEdBQUcsSUFBSSxvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO3dCQUN6RCxlQUFlLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3dCQUM3QixVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3dCQUN4QixPQUFPO29CQUNULENBQUM7b0JBQ0QsUUFBUSxHQUFHLElBQUksQ0FBQztvQkFDaEIsVUFBVSxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUNuQixPQUFPO2dCQUNULENBQUM7Z0JBQ0QsU0FBUyxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUM7Z0JBQzlCLElBQUksU0FBUyxHQUFHLFlBQVksRUFBRSxDQUFDO29CQUM3QixNQUFNLEtBQUssR0FBRyxJQUFJLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLENBQUM7b0JBQ3pELE1BQU0sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUNwQixVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO29CQUN4QixPQUFPO2dCQUNULENBQUM7Z0JBQ0QsVUFBVSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixDQUFDO1lBQ0QsTUFBTTtTQUNQLEVBQUUsRUFBRSxhQUFhLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUV6QixPQUFPO1lBQ0wsTUFBTTtZQUNOLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTTtZQUM5QixVQUFVLEVBQUUsR0FBRyxFQUFFLENBQUMsUUFBUTtZQUMxQixNQUFNO1lBQ04sT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUNaLE9BQU8sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQztTQUM5RCxDQUFDO0lBQ0osQ0FBQztJQUVPLHlCQUF5QixDQUFDLEtBQWM7UUFDOUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxjQUFjLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sSUFBSSxDQUFDO1FBQzFCLElBQ0UsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLEdBQUc7WUFDekQsT0FBTyxDQUFDLE1BQU0sR0FBRyxHQUFHO1lBQ3BCLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFDZixDQUFDO1lBQ0QsTUFBTSxJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFDRCxNQUFNLElBQUksR0FBRztZQUNYLElBQUksRUFBRSxPQUFPLENBQUMsSUFBSSxJQUFJLGFBQWE7WUFDbkMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1lBQ3RCLE1BQU0sRUFBRSxPQUFPLENBQUMsTUFBTTtZQUN0QixHQUFHLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7U0FDbkQsQ0FBQztRQUNGLE1BQU0sT0FBTyxHQUEyQjtZQUN0QyxjQUFjLEVBQUUsMEJBQTBCO1NBQzNDLENBQUM7UUFDRixJQUFJLE9BQU8sQ0FBQyxpQkFBaUIsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUM1QyxPQUFPLENBQUMsYUFBYSxDQUFDLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFDRCxPQUFPLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDeEMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUFNO1lBQ3RCLE9BQU87U0FDUixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sd0JBQXdCLENBQzlCLEtBQTJCLEVBQzNCLEtBQWE7UUFFYixJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssZUFBZSxFQUFFLENBQUM7WUFDckMsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsYUFBYSxFQUNiLGdDQUFnQyxDQUNqQyxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3RDLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FDekIsR0FBRyxFQUNILGFBQWEsRUFDYixpREFBaUQsQ0FDbEQsQ0FBQztRQUNKLENBQUM7UUFDRCxNQUFNLE9BQU8sR0FBRyxLQUFLLEtBQUssZUFBZTtZQUN2QyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhO1lBQzNCLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQztRQUMvQixPQUFPLElBQUksQ0FBQyxhQUFhLENBQ3ZCLEdBQUcsRUFDSCxLQUFLLEVBQ0wsOEJBQThCLE9BQU8sU0FBUyxDQUMvQyxDQUFDO0lBQ0osQ0FBQztJQUVPLEtBQUssQ0FBQyxxQkFBcUIsQ0FDakMsT0FBeUIsRUFDekIsT0FBZ0IsRUFDaEIsSUFBWTtRQUVaLE1BQU0sYUFBYSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDNUQsSUFBSSxhQUFhLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDM0IsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLHlCQUF5QixDQUFDLENBQUM7WUFDakUsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsYUFBYSxFQUNiLDZCQUE2QixDQUM5QixDQUFDO1FBQ0osQ0FBQztRQUNELElBQ0UsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztZQUM1QixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQzVDLENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsd0JBQXdCLENBQUMsQ0FBQztZQUNoRSxPQUFPLElBQUksQ0FBQyxlQUFlLENBQ3pCLEdBQUcsRUFDSCxhQUFhLEVBQ2IsZ0NBQWdDLENBQ2pDLENBQUM7UUFDSixDQUFDO1FBQ0QsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLGFBQWEsQ0FBQyxDQUFDO1FBQzNDLElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDN0MsTUFBTSxJQUFJLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLHdCQUF3QixDQUFDLENBQUM7WUFDaEUsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUN2QixHQUFHLEVBQ0gsZUFBZSxFQUNmLDZCQUE2QixJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsU0FBUyxDQUNoRSxDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxJQUFJLFlBQVksS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUN4QyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQ3pCLEdBQUcsRUFDSCxhQUFhLEVBQ2IsaURBQWlELENBQ2xELENBQUM7UUFDSixDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sRUFBRSxZQUFZLENBQUMsQ0FBQztRQUMvRCxNQUFNLE1BQU0sR0FBMEI7WUFDcEMsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLElBQUksRUFBRSxZQUFZO1lBQ2xCLElBQUk7WUFDSixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07U0FDcEIsQ0FBQztRQUNGLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxnQkFBaUIsQ0FDakQsT0FBTyxDQUFDLFNBQVMsRUFDakIsTUFBTSxDQUNQLENBQUM7WUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxFQUFFLENBQUM7Z0JBQ3ZCLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLG9CQUFvQixDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztnQkFDOUQsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUN6QixHQUFHLEVBQ0gsYUFBYSxFQUNiLDREQUE0RCxDQUM3RCxDQUFDO1lBQ0osQ0FBQztZQUNELElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxZQUFZLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxJQUFJLEtBQUssQ0FDYiwyQkFBMkIsTUFBTSxDQUFDLElBQUksZ0JBQWdCLFlBQVksZ0JBQWdCLENBQ25GLENBQUM7WUFDSixDQUFDO1lBQ0QsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRTtnQkFDNUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO2dCQUM1QixNQUFNLEVBQUUsTUFBTSxDQUFDLE1BQU07Z0JBQ3JCLElBQUk7Z0JBQ0osSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO2FBQ2xCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3pCLElBQUksS0FBSyxZQUFZLG9CQUFvQixFQUFFLENBQUM7Z0JBQzFDLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsQ0FBQztZQUMvRCxDQUFDO1lBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLHlCQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3JELElBQUksTUFBTTtnQkFBRSxPQUFPLE1BQU0sQ0FBQztZQUMxQixNQUFNLEtBQUssQ0FBQztRQUNkLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZLENBQ3hCLE9BQXlCLEVBQ3pCLFNBQXlCLEVBQ3pCLFFBQWdCLEVBQ2hCLE9BQWdCO1FBRWhCLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDdEQsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQ25CLENBQUM7UUFDRixNQUFNLFNBQVMsR0FBRyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7UUFDeEQsSUFBSSxTQUFTLEtBQUssT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3pELE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFDckUsQ0FBQztRQUVELE1BQU0sZ0JBQWdCLEdBQ3BCLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3RCxJQUNFLGdCQUFnQixJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CO1lBQ25ELElBQUksQ0FBQyxvQkFBb0IsSUFBSSxJQUFJLENBQUMseUJBQXlCLEVBQzNELENBQUM7WUFDRCxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsa0NBQWtDLENBQUMsQ0FBQztZQUMxRSxPQUFPLElBQUksQ0FBQyxhQUFhLENBQ3ZCLEdBQUcsRUFDSCxxQkFBcUIsRUFDckIsOEJBQThCLENBQy9CLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLHdCQUF3QixDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLGdCQUFnQixHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzVFLElBQUksQ0FBQztZQUNILE1BQU0sSUFBSSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQztnQkFDOUMsMEJBQTBCLENBQUM7WUFDN0IsSUFBSSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsZ0JBQWdCLEtBQUssVUFBVSxFQUFFLENBQUM7Z0JBQ3hELE9BQU8sTUFBTSxJQUFJLENBQUMscUJBQXFCLENBQUMsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNsRSxDQUFDO1lBQ0QsSUFBSSxJQUFnQixDQUFDO1lBQ3JCLElBQUksQ0FBQztnQkFDSCxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsc0JBQXNCLENBQ3RDLE9BQU8sRUFDUCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FDMUIsQ0FBQztZQUNKLENBQUM7WUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO2dCQUNmLElBQUksS0FBSyxZQUFZLG9CQUFvQixFQUFFLENBQUM7b0JBQzFDLE9BQU8sSUFBSSxDQUFDLHdCQUF3QixDQUFDLEtBQUssRUFBRSxlQUFlLENBQUMsQ0FBQztnQkFDL0QsQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUNwRCxPQUFPLENBQUMsU0FBUyxFQUNqQixJQUFJLEVBQ0osSUFBSSxDQUNMLENBQUM7Z0JBQ0YsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsRUFBRTtvQkFDNUIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxTQUFTO29CQUM1QixNQUFNO29CQUNOLElBQUk7b0JBQ0osSUFBSTtpQkFDTCxDQUFDLENBQUM7WUFDTCxDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMseUJBQXlCLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3JELElBQUksTUFBTTtvQkFBRSxPQUFPLE1BQU0sQ0FBQztnQkFDMUIsTUFBTSxLQUFLLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDNUIsTUFBTSx5QkFBeUIsR0FDN0IsQ0FBQyxJQUFJLENBQUMsd0JBQXdCLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbkUsSUFBSSx5QkFBeUIsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDbkMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDM0QsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLElBQUksQ0FBQyx3QkFBd0IsQ0FBQyxHQUFHLENBQy9CLFNBQVMsQ0FBQyxRQUFRLEVBQ2xCLHlCQUF5QixDQUMxQixDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWMsQ0FDMUIsT0FBeUIsRUFDekIsUUFBZ0IsRUFDaEIsR0FBUTtRQUVSLDZDQUE2QztRQUM3QyxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQ3RELE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUNuQixDQUFDO1FBQ0YsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sTUFBTSxHQUFHLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUNyRCxNQUFNLElBQUksR0FBRyxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxDQUFDLENBQUM7UUFDdkQsSUFBSSxTQUFTLEtBQUssT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3BDLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLEVBQUUsYUFBYSxFQUFFLGlCQUFpQixDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELE1BQU0sSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUNuRSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDVixPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxFQUFFLGFBQWEsRUFBRSxjQUFjLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBQ0QsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQztRQUN2RCxPQUFPLElBQUksUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDMUMsTUFBTSxFQUFFLEdBQUc7WUFDWCxPQUFPLEVBQUU7Z0JBQ1AsY0FBYyxFQUFFLElBQUk7Z0JBQ3BCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQztnQkFDMUMscUJBQXFCLEVBQUUseUJBQ3JCLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FDekIsR0FBRzthQUNKO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELHlCQUF5QjtJQUN6QixxQkFBcUI7SUFDckIseUJBQXlCO0lBRWpCLGlCQUFpQixDQUFDLE9BQXlCLEVBQUUsR0FBUTtRQUMzRCxNQUFNLFVBQVUsR0FBRyxHQUFHLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLENBQUM7UUFDeEQsTUFBTSxLQUFLLEdBQUcsVUFBVSxLQUFLLEdBQUcsSUFBSSxVQUFVLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUNwRSxVQUFVO2FBQ1AsS0FBSyxDQUFDLEdBQUcsQ0FBQzthQUNWLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO2FBQzVCLE1BQU0sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FDdkMsQ0FBQztRQUNGLE1BQU0sZUFBZSxHQUFHLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxLQUFLLE9BQU8sQ0FBQztRQUN2RSxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7UUFDNUQsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxPQUFPLEdBQUcsQ0FBQztZQUN6RCxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUNsQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRU4sTUFBTSxLQUFLLEdBQXNCO1lBQy9CLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztZQUM1QixLQUFLO1lBQ0wsZUFBZTtZQUNmLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFNBQVMsRUFBRSxJQUFJO1lBQ2YsUUFBUSxFQUFFLElBQUksR0FBRyxFQUFFO1lBQ25CLE1BQU0sRUFBRSxLQUFLO1NBQ2QsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLElBQUksY0FBYyxDQUFhO1lBQzVDLEtBQUssRUFBRSxDQUFDLFVBQVUsRUFBRSxFQUFFO2dCQUNwQixLQUFLLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztnQkFDOUIsVUFBVSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLHlCQUF5QixDQUFDLENBQUMsQ0FBQztnQkFDbEUsSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7b0JBQ3BCLEtBQUssQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRTt3QkFDakMsSUFBSSxDQUFDLGFBQWEsQ0FDaEIsS0FBSyxFQUNMLGtDQUFrQyxXQUFXLE9BQU8sQ0FDckQsQ0FBQztvQkFDSixDQUFDLEVBQUUsV0FBVyxHQUFHLElBQUksQ0FBQyxDQUFDO2dCQUN6QixDQUFDO2dCQUNELElBQUksQ0FBQztvQkFDSCxJQUFJLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUM3QixDQUFDO2dCQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7b0JBQ2YsdUVBQXVFO29CQUN2RSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBQzdCLE1BQU0sS0FBSyxDQUFDO2dCQUNkLENBQUM7WUFDSCxDQUFDO1lBQ0QsTUFBTSxFQUFFLEdBQUcsRUFBRTtnQkFDWCxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDL0IsQ0FBQztTQUNGLENBQUMsQ0FBQztRQUNILE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxFQUFFO1lBQzFCLE1BQU0sRUFBRSxHQUFHO1lBQ1gsT0FBTyxFQUFFO2dCQUNQLGNBQWMsRUFBRSxtQkFBbUI7Z0JBQ25DLGVBQWUsRUFBRSxVQUFVO2FBQzVCO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGNBQWMsQ0FBQyxLQUF3QjtRQUM3QyxJQUFJLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDaEMsSUFBSSxDQUFDLHFCQUFxQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtnQkFDdEUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN6RCxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsS0FBd0I7UUFDL0MsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7UUFDcEIsSUFBSSxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDcEIsYUFBYSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUMvQixLQUFLLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDO1FBQ0QsSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzFELE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxxQkFBcUIsQ0FBQztZQUMvQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDO1lBQ2xDLElBQUksQ0FBQztnQkFDSCxXQUFXLEVBQUUsQ0FBQztZQUNoQixDQUFDO1lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztnQkFDZixJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNqQyxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFTyxXQUFXLENBQUMsS0FBd0I7UUFDMUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQztZQUNILEtBQUssQ0FBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLENBQUM7UUFDNUIsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLDRCQUE0QjtRQUM5QixDQUFDO0lBQ0gsQ0FBQztJQUVPLGFBQWEsQ0FBQyxLQUF3QixFQUFFLE9BQWU7UUFDN0QsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3RDLE9BQU87UUFDVCxDQUFDO1FBQ0QsSUFBSSxDQUFDO1lBQ0gsS0FBSyxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3hELENBQUM7UUFBQyxNQUFNLENBQUM7WUFDUCxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLGVBQWUsQ0FDckIsU0FBaUIsRUFDakIsT0FBK0I7UUFFL0IsS0FBSyxNQUFNLEtBQUssSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO1lBQ2xELElBQUksS0FBSyxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDbEMsU0FBUztZQUNYLENBQUM7WUFDRCxNQUFNLFFBQVEsR0FBMkIsRUFBRSxDQUFDO1lBQzVDLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3hELElBQUksS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7b0JBQzFDLFNBQVM7Z0JBQ1gsQ0FBQztnQkFDRCxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLFNBQVMsRUFBRSxDQUFDO29CQUMzQyxTQUFTO2dCQUNYLENBQUM7Z0JBQ0QsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLFNBQVMsQ0FBQztZQUM3QixDQUFDO1lBQ0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ2xDLFNBQVM7WUFDWCxDQUFDO1lBQ0QsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDekQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3RDLENBQUM7WUFDRCxNQUFNLFdBQVcsR0FBRztnQkFDbEIsT0FBTyxFQUFFLGFBQWE7Z0JBQ3RCLE9BQU8sRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLEVBQUUsUUFBUSxFQUFFO2FBQ25DLENBQUM7WUFDRixJQUFJLENBQUMsYUFBYSxDQUNoQixLQUFLLEVBQ0wsdUJBQXVCLElBQUksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FDekQsQ0FBQztZQUNGLElBQUksS0FBSyxDQUFDLGVBQWUsRUFBRSxDQUFDO2dCQUMxQixJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzFCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxLQUFLLENBQUMsaUJBQWlCLENBQUMsT0FBeUI7UUFDdkQsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDNUIsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLENBQUMsTUFBTSxFQUFFLFNBQVMsRUFBRSxPQUFPLENBQUMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUM7WUFDckQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDN0MsSUFBSSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7U0FDL0MsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFO1lBQ3RDLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSztZQUNuQixNQUFNLEVBQUUsT0FBTyxDQUFDLEtBQUs7WUFDckIsT0FBTyxFQUFFLFNBQVMsQ0FBQyxLQUFLO1NBQ3pCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCx5QkFBeUI7SUFDekIsdUJBQXVCO0lBQ3ZCLHlCQUF5QjtJQUVqQixlQUFlLENBQ3JCLEdBQWlDO1FBRWpDLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQztRQUNuQixJQUFJLE9BQU8sR0FBRyxHQUFTLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFDN0IsT0FBTyxJQUFJLGNBQWMsQ0FBYTtZQUNwQyxLQUFLLENBQUMsVUFBVTtnQkFDZCxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ1osTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFhLEVBQVEsRUFBRTtvQkFDckMsSUFBSSxNQUFNO3dCQUFFLE9BQU87b0JBQ25CLFVBQVUsQ0FBQyxPQUFPLENBQ2hCLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQ2pFLENBQUM7b0JBQ0YsSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQzt3QkFBRSxHQUFHLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ3RELENBQUMsQ0FBQztnQkFDRixNQUFNLEtBQUssR0FBRyxHQUFTLEVBQUU7b0JBQ3ZCLElBQUksTUFBTTt3QkFBRSxPQUFPO29CQUNuQixNQUFNLEdBQUcsSUFBSSxDQUFDO29CQUNkLE9BQU8sRUFBRSxDQUFDO29CQUNWLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDckIsQ0FBQyxDQUFDO2dCQUNGLE1BQU0sU0FBUyxHQUFHLEdBQVMsRUFBRTtvQkFDM0IsSUFBSSxNQUFNO3dCQUFFLE9BQU87b0JBQ25CLE1BQU0sR0FBRyxJQUFJLENBQUM7b0JBQ2QsT0FBTyxFQUFFLENBQUM7b0JBQ1YsVUFBVSxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xFLENBQUMsQ0FBQztnQkFDRixNQUFNLE9BQU8sR0FBRyxDQUFDLEtBQVksRUFBUSxFQUFFO29CQUNyQyxJQUFJLE1BQU07d0JBQUUsT0FBTztvQkFDbkIsTUFBTSxHQUFHLElBQUksQ0FBQztvQkFDZCxPQUFPLEVBQUUsQ0FBQztvQkFDVixVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUMxQixDQUFDLENBQUM7Z0JBQ0YsT0FBTyxHQUFHLEdBQUcsRUFBRTtvQkFDYixHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztvQkFDeEIsR0FBRyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQ3RCLEdBQUcsQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO29CQUM5QixHQUFHLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDNUIsQ0FBQyxDQUFDO2dCQUNGLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDO2dCQUN2QixHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztnQkFDdkIsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDLENBQUM7Z0JBQy9CLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQzdCLENBQUM7WUFDRCxJQUFJO2dCQUNGLElBQUksQ0FBQyxNQUFNO29CQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUM1QixDQUFDO1lBQ0QsTUFBTTtnQkFDSixJQUFJLE1BQU07b0JBQUUsT0FBTztnQkFDbkIsTUFBTSxHQUFHLElBQUksQ0FBQztnQkFDZCxPQUFPLEVBQUUsQ0FBQztnQkFDVixvRUFBb0U7Z0JBQ3BFLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNmLENBQUM7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLGlCQUFpQixDQUM3QixHQUFpQyxFQUNqQyxHQUFnQyxFQUNoQyxzQkFBdUM7UUFFdkMsTUFBTSxZQUFZLEdBQUcsQ0FBQyxNQUFlLEVBQVEsRUFBRTtZQUM3QyxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO2dCQUMzQyxzQkFBc0IsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDdkMsQ0FBQztRQUNILENBQUMsQ0FBQztRQUNGLE1BQU0sZ0JBQWdCLEdBQUcsR0FBUyxFQUFFO1lBQ2xDLFlBQVksQ0FBQyxJQUFJLEtBQUssQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDLENBQUM7UUFDckUsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxjQUFjLEdBQUcsQ0FBQyxLQUFZLEVBQVEsRUFBRTtZQUM1QyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdEIsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxjQUFjLEdBQUcsR0FBUyxFQUFFO1lBQ2hDLGtFQUFrRTtZQUNsRSwrREFBK0Q7WUFDL0QsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRO2dCQUFFLGdCQUFnQixFQUFFLENBQUM7UUFDeEMsQ0FBQyxDQUFDO1FBQ0YsTUFBTSxlQUFlLEdBQUcsR0FBUyxFQUFFO1lBQ2pDLElBQUksQ0FBQyxHQUFHLENBQUMsYUFBYSxFQUFFLENBQUM7Z0JBQ3ZCLFlBQVksQ0FDVixJQUFJLEtBQUssQ0FBQyxvREFBb0QsQ0FBQyxDQUNoRSxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUMsQ0FBQztRQUNGLEdBQUcsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLGdCQUFnQixDQUFDLENBQUM7UUFDdEMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDbEMsR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFDbkMsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ25ELE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7WUFDOUIsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUM7Z0JBQzdCLFlBQVk7Z0JBQ1osUUFBUTtnQkFDUixZQUFZO2dCQUNaLGtCQUFrQjtnQkFDbEIsbUJBQW1CO2dCQUNuQixTQUFTO2FBQ1YsQ0FBQyxDQUFDO1lBQ0gsS0FBSyxNQUFNLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7Z0JBQ3ZELElBQUksS0FBSyxLQUFLLFNBQVMsSUFBSSxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQUM7b0JBQ2pFLFNBQVM7Z0JBQ1gsQ0FBQztnQkFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNwRSxDQUFDO1lBQ0QsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLElBQUksV0FBVyxDQUFDO1lBQzdDLE1BQU0sV0FBVyxHQUFzQztnQkFDckQsTUFBTTtnQkFDTixPQUFPO2dCQUNQLE1BQU0sRUFBRSxzQkFBc0IsQ0FBQyxNQUFNO2FBQ3RDLENBQUM7WUFDRixJQUFJLE1BQU0sS0FBSyxLQUFLLElBQUksTUFBTSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUMxQyxXQUFXLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQzdDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQzlCLENBQUM7WUFDRCxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FDekIsVUFBVSxJQUFJLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLEVBQUUsRUFDakMsV0FBVyxDQUNaLENBQUM7WUFFRixNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFbEQsTUFBTSxlQUFlLEdBQTJCLEVBQUUsQ0FBQztZQUNuRCxRQUFRLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtnQkFDdEMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUMvQixDQUFDLENBQUMsQ0FBQztZQUNILEdBQUcsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxlQUFlLENBQUMsQ0FBQztZQUNoRCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNuQixHQUFHLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ1YsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ3pDLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztZQUN6QixHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLEVBQUU7Z0JBQ25CLFlBQVksR0FBRyxJQUFJLENBQUM7Z0JBQ3BCLG9FQUFvRTtnQkFDcEUsb0VBQW9FO2dCQUNwRSxLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdkMsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUM7Z0JBQ0gsT0FBTyxJQUFJLEVBQUUsQ0FBQztvQkFDWixNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO29CQUM1QyxJQUFJLElBQUksSUFBSSxZQUFZLElBQUksR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDO3dCQUMxQyxNQUFNO29CQUNSLENBQUM7b0JBQ0QsR0FBRyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztnQkFDbkIsQ0FBQztZQUNILENBQUM7WUFBQyxNQUFNLENBQUM7Z0JBQ1Asc0NBQXNDO1lBQ3hDLENBQUM7WUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUNuQixHQUFHLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDWixDQUFDO1FBQ0gsQ0FBQztRQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7WUFDZixNQUFNLE9BQU8sR0FBRyxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQztnQkFDckIsR0FBRyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsRUFBRSxjQUFjLEVBQUUsMEJBQTBCLEVBQUUsQ0FBQyxDQUFDO1lBQ3JFLENBQUM7WUFDRCxHQUFHLENBQUMsR0FBRyxDQUNMLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQ3RFLENBQUM7UUFDSixDQUFDO2dCQUFTLENBQUM7WUFDVCxHQUFHLENBQUMsR0FBRyxDQUFDLFNBQVMsRUFBRSxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3JDLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1lBQ2pDLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLGNBQWMsQ0FBQyxDQUFDO1lBQ2pDLEdBQUcsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQ3BDLENBQUM7SUFDSCxDQUFDO0lBRUQseUJBQXlCO0lBQ3pCLGdDQUFnQztJQUNoQyx5QkFBeUI7SUFFakIsa0JBQWtCLENBQ3hCLFNBQWMsRUFDZCxLQUFrQjtRQUVsQixJQUFJLFNBQVMsS0FBSyxJQUFJLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2xELE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDOUIsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixrQkFBa0IsRUFDbEIsc0NBQXNDLENBQ3ZDLENBQUM7UUFDSixDQUFDO1FBQ0QsS0FBSyxNQUFNLFFBQVEsSUFBSSxTQUFTLEVBQUUsQ0FBQztZQUNqQyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztnQkFDekQsTUFBTSxJQUFJLHFCQUFxQixDQUM3QixrQkFBa0IsRUFDbEIscUJBQXFCLE1BQU0sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUMxQyxDQUFDO1lBQ0osQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsR0FBRyxTQUFTLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRU8sYUFBYSxDQUNuQixNQUEyQixFQUMzQixVQUFvQjtRQUVwQixNQUFNLFNBQVMsR0FBd0IsRUFBRSxDQUFDO1FBQzFDLEtBQUssTUFBTSxRQUFRLElBQUksVUFBVSxFQUFFLENBQUM7WUFDbEMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxTQUFTO2dCQUNsRCxDQUFDLENBQUMsSUFBSTtnQkFDTixDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3ZCLENBQUM7UUFDRCxPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRU8sZ0JBQWdCLENBQUMsSUFBeUI7UUFDaEQsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLElBQUksRUFBRSxDQUFDO1lBQzFELE9BQU8sQ0FBQyxDQUFDO1FBQ1gsQ0FBQztRQUNELElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzFELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isa0JBQWtCLEVBQ2xCLDBDQUEwQyxDQUMzQyxDQUFDO1FBQ0osQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDLFFBQWtCLENBQUM7SUFDakMsQ0FBQztJQUVPLG1CQUFtQixDQUFDLElBQXlCO1FBSW5ELElBQUksT0FBTyxJQUFJLENBQUMsVUFBVSxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQ3hDLE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isa0JBQWtCLEVBQ2xCLHlCQUF5QixDQUMxQixDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksVUFBOEIsQ0FBQztRQUNuQyxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssU0FBUyxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQy9ELE1BQU0sSUFBSSxxQkFBcUIsQ0FDN0Isa0JBQWtCLEVBQ2xCLHdDQUF3QyxDQUN6QyxDQUFDO1lBQ0osQ0FBQztZQUNELFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBb0IsQ0FBQztRQUN6QyxDQUFDO1FBQ0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQ3JELENBQUM7SUFFTyxZQUFZLENBQUMsTUFBYyxFQUFFLElBQWE7UUFDaEQsT0FBTyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFO1lBQ3hDLE1BQU07WUFDTixPQUFPLEVBQUUsRUFBRSxjQUFjLEVBQUUsa0JBQWtCLEVBQUU7U0FDaEQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVPLGVBQWUsQ0FDckIsTUFBYyxFQUNkLElBQVksRUFDWixNQUFjLEVBQ2QsZUFBdUMsRUFBRTtRQUV6QyxPQUFPLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUU7WUFDNUQsTUFBTTtZQUNOLE9BQU8sRUFBRSxFQUFFLGNBQWMsRUFBRSwwQkFBMEIsRUFBRSxHQUFHLFlBQVksRUFBRTtTQUN6RSxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sYUFBYSxDQUNuQixNQUFjLEVBQ2QsS0FBYSxFQUNiLE1BQWM7UUFFZCxPQUFPLElBQUksUUFBUSxDQUNqQixJQUFJLENBQUMsU0FBUyxDQUFDO1lBQ2IsSUFBSSxFQUFFLGtDQUFrQztZQUN4QyxLQUFLO1lBQ0wsTUFBTTtZQUNOLE1BQU07U0FDUCxDQUFDLEVBQ0YsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLEVBQUUsY0FBYyxFQUFFLDBCQUEwQixFQUFFLEVBQUUsQ0FDcEUsQ0FBQztJQUNKLENBQUM7Q0FDRiJ9
|